Merge mozilla-inbound and mozilla-central

This commit is contained in:
Marco Bonardo 2011-07-02 10:39:08 +02:00
Родитель acd9c6140f e09c349e78
Коммит 6d250b33b2
68 изменённых файлов: 1269 добавлений и 601 удалений

Просмотреть файл

@ -5462,7 +5462,7 @@ function hrefAndLinkNodeForClickEvent(event)
// If there is no linkNode, try simple XLink.
let href, baseURI;
node = event.target;
while (node) {
while (node && !href) {
if (node.nodeType == Node.ELEMENT_NODE) {
href = node.getAttributeNS("http://www.w3.org/1999/xlink", "href");
if (href)

Просмотреть файл

@ -53,7 +53,7 @@ let gTests = [
setup: function() {},
clean: function() {},
event: {},
target: "commonlink",
targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ],
expectedInvokedMethods: [],
preventDefault: false,
},
@ -64,7 +64,7 @@ let gTests = [
clean: function() {},
event: { ctrlKey: true,
metaKey: true },
target: "commonlink",
targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ],
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
preventDefault: true,
},
@ -77,17 +77,28 @@ let gTests = [
clean: function() {},
event: { shiftKey: true,
altKey: true },
target: "commonlink",
targets: [ "commonlink", "maplink" ],
expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ],
preventDefault: true,
},
{
desc: "Shift+Alt left click on XLinks",
setup: function() {},
clean: function() {},
event: { shiftKey: true,
altKey: true },
targets: [ "mathxlink", "svgxlink"],
expectedInvokedMethods: [ "saveURL" ],
preventDefault: true,
},
{
desc: "Shift click",
setup: function() {},
clean: function() {},
event: { shiftKey: true },
target: "commonlink",
targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ],
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
preventDefault: true,
},
@ -97,17 +108,27 @@ let gTests = [
setup: function() {},
clean: function() {},
event: { altKey: true },
target: "commonlink",
targets: [ "commonlink", "maplink" ],
expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ],
preventDefault: true,
},
{
desc: "Alt click on XLinks",
setup: function() {},
clean: function() {},
event: { altKey: true },
targets: [ "mathxlink", "svgxlink" ],
expectedInvokedMethods: [ "saveURL" ],
preventDefault: true,
},
{
desc: "Panel click",
setup: function() {},
clean: function() {},
event: {},
target: "panellink",
targets: [ "panellink" ],
expectedInvokedMethods: [ "urlSecurityCheck", "getShortcutOrURI", "loadURI" ],
preventDefault: true,
},
@ -117,7 +138,7 @@ let gTests = [
setup: function() {},
clean: function() {},
event: { button: 1 },
target: "commonlink",
targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ],
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
preventDefault: true,
},
@ -133,7 +154,7 @@ let gTests = [
} catch(ex) {}
},
event: { button: 1 },
target: "commonlink",
targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ],
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
preventDefault: true,
},
@ -153,7 +174,7 @@ let gTests = [
} catch(ex) {}
},
event: { button: 1 },
target: "emptylink",
targets: [ "emptylink" ],
expectedInvokedMethods: [ "middleMousePaste" ],
preventDefault: true,
},
@ -206,7 +227,7 @@ function test() {
// Click handler used to steal click events.
let gClickHandler = {
handleEvent: function (event) {
let linkId = event.target.id;
let linkId = event.target.id || event.target.localName;
is(event.type, "click",
gCurrentTest.desc + ":Handler received a click event on " + linkId);
@ -223,7 +244,7 @@ let gClickHandler = {
});
if (gInvokedMethods.length != gCurrentTest.expectedInvokedMethods.length) {
is(false, "More than the expected methods have been called");
ok(false, "Wrong number of invoked methods");
gInvokedMethods.forEach(function (method) info(method + " was invoked"));
}
@ -257,35 +278,45 @@ function setupTestBrowserWindow() {
let doc = gTestWin.content.document;
let mainDiv = doc.createElement("div");
mainDiv.innerHTML =
'<a id="commonlink" href="http://mochi.test/moz/">Common link</a>' +
'<a id="panellink" href="http://mochi.test/moz/">Panel link</a>' +
'<a id="emptylink">Empty link</a>';
'<p><a id="commonlink" href="http://mochi.test/moz/">Common link</a></p>' +
'<p><a id="panellink" href="http://mochi.test/moz/">Panel link</a></p>' +
'<p><a id="emptylink">Empty link</a></p>' +
'<p><math id="mathxlink" xmlns="http://www.w3.org/1998/Math/MathML" xlink:type="simple" xlink:href="http://mochi.test/moz/"><mtext>MathML XLink</mtext></math></p>' +
'<p><svg id="svgxlink" xmlns="http://www.w3.org/2000/svg" width="100px" height="50px" version="1.1"><a xlink:type="simple" xlink:href="http://mochi.test/moz/"><text transform="translate(10, 25)">SVG XLink</text></a></svg></p>' +
'<p><map name="map" id="map"><area href="http://mochi.test/moz/" shape="rect" coords="0,0,128,128" /></map><img id="maplink" usemap="#map" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAIAAABMXPacAAAABGdBTUEAALGPC%2FxhBQAAAOtJREFUeF7t0IEAAAAAgKD9qRcphAoDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGBgwIAAAT0N51AAAAAASUVORK5CYII%3D"/></p>'
doc.body.appendChild(mainDiv);
}
function runNextTest() {
if (gCurrentTest) {
if (!gCurrentTest) {
gCurrentTest = gTests.shift();
gCurrentTest.setup();
}
if (gCurrentTest.targets.length == 0) {
info(gCurrentTest.desc + ": cleaning up...")
gCurrentTest.clean();
gInvokedMethods.length = 0;
if (gTests.length > 0) {
gCurrentTest = gTests.shift();
gCurrentTest.setup();
}
else {
finishTest();
return;
}
}
if (gTests.length > 0) {
gCurrentTest = gTests.shift();
// Move to next target.
gInvokedMethods.length = 0;
let target = gCurrentTest.targets.shift();
info(gCurrentTest.desc + ": starting...");
// Prepare for test.
gCurrentTest.setup();
info(gCurrentTest.desc + ": testing " + target);
// Fire click event.
let target = gTestWin.content.document.getElementById(gCurrentTest.target);
ok(target, gCurrentTest.desc + ": target is valid (" + target.id + ")");
EventUtils.synthesizeMouse(target, 2, 2, gCurrentTest.event, gTestWin.content);
}
else {
// No more tests to run.
finishTest()
}
// Fire click event.
let targetElt = gTestWin.content.document.getElementById(target);
ok(targetElt, gCurrentTest.desc + ": target is valid (" + targetElt.id + ")");
EventUtils.synthesizeMouseAtCenter(targetElt, gCurrentTest.event, gTestWin.content);
}
function finishTest() {

Просмотреть файл

@ -431,6 +431,19 @@ PlacesViewBase.prototype = {
}
},
toggleCutNode: function PVB_toggleCutNode(aNode, aValue) {
let elt = aNode._DOMElement;
if (elt) {
// We may get the popup for menus, but we need the menu itself.
if (elt.localName == "menupopup")
elt = elt.parentNode;
if (aValue)
elt.setAttribute("cutting", "true");
else
elt.removeAttribute("cutting");
}
},
nodeURIChanged: function PVB_nodeURIChanged(aPlacesNode, aURIString) {
let elt = aPlacesNode._DOMElement;
if (!elt)
@ -658,6 +671,7 @@ PlacesViewBase.prototype = {
}
if (this._controller) {
this._controller.terminate();
this._viewElt.controllers.removeController(this._controller);
this._controller = null;
}

Просмотреть файл

@ -117,6 +117,9 @@ function PlacesController(aView) {
XPCOMUtils.defineLazyServiceGetter(this, "clipboard",
"@mozilla.org/widget/clipboard;1",
"nsIClipboard");
XPCOMUtils.defineLazyGetter(this, "profileName", function () {
return Services.dirsvc.get("ProfD", Ci.nsIFile).leafName;
});
}
PlacesController.prototype = {
@ -125,6 +128,20 @@ PlacesController.prototype = {
*/
_view: null,
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIClipboardOwner
]),
// nsIClipboardOwner
LosingOwnership: function PC_LosingOwnership (aXferable) {
this.cutNodes = [];
},
terminate: function PC_terminate() {
if (this._cutNodes.length > 0)
this._clearClipboard();
},
supportsCommand: function PC_supportsCommand(aCommand) {
//LOG("supportsCommand: " + command);
// Non-Places specific commands that we also support
@ -1086,74 +1103,127 @@ PlacesController.prototype = {
}
},
get clipboardAction () {
let action = {};
let actionOwner;
try {
let xferable = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
xferable.addDataFlavor(PlacesUtils.TYPE_X_MOZ_PLACE_ACTION)
this.clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
xferable.getTransferData(PlacesUtils.TYPE_X_MOZ_PLACE_ACTION, action, {});
[action, actionOwner] =
action.value.QueryInterface(Ci.nsISupportsString).data.split(",");
} catch(ex) {
// Paste from external sources don't have any associated action, just
// fallback to a copy action.
return "copy";
}
// For cuts also check who inited the action, since cuts across different
// instances should instead be handled as copies (The sources are not
// available for this instance).
if (action == "cut" && actionOwner != this.profileName)
action = "copy";
return action;
},
_clearClipboard: function PC__clearClipboard() {
this.clipboard.emptyClipboard(Ci.nsIClipboard.kGlobalClipboard);
// Unfortunately just invoking emptyClipboard is not enough, since it
// does not act on the native clipboard.
let xferable = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
// GTK doesn't like empty transferables, so just add an unknown type.
xferable.addDataFlavor("text/x-moz-place-empty");
this.clipboard.setData(xferable, null, Ci.nsIClipboard.kGlobalClipboard);
},
_populateClipboard: function PC__populateClipboard(aNodes, aAction) {
// This order is _important_! It controls how this and other applications
// select data to be inserted based on type.
let contents = [
{ type: PlacesUtils.TYPE_X_MOZ_PLACE, entries: [] },
{ type: PlacesUtils.TYPE_X_MOZ_URL, entries: [] },
{ type: PlacesUtils.TYPE_HTML, entries: [] },
{ type: PlacesUtils.TYPE_UNICODE, entries: [] },
];
// Avoid handling descendants of a copied node, the transactions take care
// of them automatically.
let copiedFolders = [];
aNodes.forEach(function (node) {
if (this._shouldSkipNode(node, copiedFolders))
return;
if (PlacesUtils.nodeIsFolder(node))
copiedFolders.push(node);
let overrideURI = PlacesUtils.nodeIsLivemarkContainer(node) ?
PlacesUtils.livemarks.getFeedURI(node.itemId).spec : null;
let resolveShortcuts = !PlacesControllerDragHelper.canMoveNode(node);
contents.forEach(function (content) {
content.entries.push(
PlacesUtils.wrapNode(node, content.type, overrideURI, resolveShortcuts)
);
});
}, this);
function addData(type, data) {
xferable.addDataFlavor(type);
xferable.setTransferData(type, PlacesUtils.toISupportsString(data),
data.length * 2);
}
let xferable = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
let hasData = false;
// This order matters here! It controls how this and other applications
// select data to be inserted based on type.
contents.forEach(function (content) {
if (content.entries.length > 0) {
hasData = true;
let glue =
content.type == PlacesUtils.TYPE_X_MOZ_PLACE ? "," : PlacesUtils.endl;
addData(content.type, content.entries.join(glue));
}
});
// Track the exected action in the xferable. This must be the last flavor
// since it's the least preferred one.
// Enqueue a unique instance identifier to distinguish operations across
// concurrent instances of the application.
addData(PlacesUtils.TYPE_X_MOZ_PLACE_ACTION, aAction + "," + this.profileName);
if (hasData)
this.clipboard.setData(xferable, this, Ci.nsIClipboard.kGlobalClipboard);
},
_cutNodes: [],
set cutNodes(aNodes) {
let self = this;
function updateCutNodes(aValue) {
self._cutNodes.forEach(function (aNode) {
self._view.toggleCutNode(aNode, aValue);
});
}
updateCutNodes(false);
this._cutNodes = aNodes;
updateCutNodes(true);
return aNodes;
},
/**
* Copy Bookmarks and Folders to the clipboard
*/
copy: function PC_copy() {
let result = this._view.result;
let didSuppressNotifications = result.suppressNotifications;
if (!didSuppressNotifications)
result.suppressNotifications = true;
try {
let nodes = this._view.selectedNodes;
let xferable = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
let foundFolder = false, foundLink = false;
let copiedFolders = [];
let placeString, mozURLString, htmlString, unicodeString;
placeString = mozURLString = htmlString = unicodeString = "";
for (let i = 0; i < nodes.length; ++i) {
let node = nodes[i];
if (this._shouldSkipNode(node, copiedFolders))
continue;
if (PlacesUtils.nodeIsFolder(node))
copiedFolders.push(node);
function generateChunk(type, overrideURI) {
let suffix = i < (nodes.length - 1) ? PlacesUtils.endl : "";
let uri = overrideURI;
if (PlacesUtils.nodeIsLivemarkContainer(node))
uri = PlacesUtils.livemarks.getFeedURI(node.itemId).spec
mozURLString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_X_MOZ_URL,
uri) + suffix);
unicodeString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_UNICODE,
uri) + suffix);
htmlString += (PlacesUtils.wrapNode(node, PlacesUtils.TYPE_HTML,
uri) + suffix);
let placeSuffix = i < (nodes.length - 1) ? "," : "";
let resolveShortcuts = !PlacesControllerDragHelper.canMoveNode(node);
return PlacesUtils.wrapNode(node, type, overrideURI, resolveShortcuts) + placeSuffix;
}
// all items wrapped as TYPE_X_MOZ_PLACE
placeString += generateChunk(PlacesUtils.TYPE_X_MOZ_PLACE);
}
function addData(type, data) {
xferable.addDataFlavor(type);
xferable.setTransferData(type, PlacesUIUtils._wrapString(data), data.length * 2);
}
// This order is _important_! It controls how this and other applications
// select data to be inserted based on type.
if (placeString)
addData(PlacesUtils.TYPE_X_MOZ_PLACE, placeString);
if (mozURLString)
addData(PlacesUtils.TYPE_X_MOZ_URL, mozURLString);
if (unicodeString)
addData(PlacesUtils.TYPE_UNICODE, unicodeString);
if (htmlString)
addData(PlacesUtils.TYPE_HTML, htmlString);
if (placeString || unicodeString || htmlString || mozURLString) {
this.clipboard.setData(xferable, null, Ci.nsIClipboard.kGlobalClipboard);
}
this._populateClipboard(this._view.selectedNodes, "copy");
}
finally {
if (!didSuppressNotifications)
@ -1165,101 +1235,94 @@ PlacesController.prototype = {
* Cut Bookmarks and Folders to the clipboard
*/
cut: function PC_cut() {
this.copy();
this.remove("Cut Selection");
let result = this._view.result;
let didSuppressNotifications = result.suppressNotifications;
if (!didSuppressNotifications)
result.suppressNotifications = true;
try {
this._populateClipboard(this._view.selectedNodes, "cut");
this.cutNodes = this._view.selectedNodes;
}
finally {
if (!didSuppressNotifications)
result.suppressNotifications = false;
}
},
/**
* Paste Bookmarks and Folders from the clipboard
*/
paste: function PC_paste() {
// Strategy:
//
// There can be data of various types (folder, separator, link) on the
// clipboard. We need to get all of that data and build edit transactions
// for them. This means asking the clipboard once for each type and
// aggregating the results.
/**
* Constructs a transferable that can receive data of specific types.
* @param types
* The types of data the transferable can hold, in order of
* preference.
* @returns The transferable.
*/
function makeXferable(types) {
var xferable = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
for (var i = 0; i < types.length; ++i)
xferable.addDataFlavor(types[i]);
return xferable;
}
var clipboard = this.clipboard;
var ip = this._view.insertionPoint;
// No reason to proceed if there isn't a valid insertion point.
let ip = this._view.insertionPoint;
if (!ip)
throw Cr.NS_ERROR_NOT_AVAILABLE;
/**
* Gets a list of transactions to perform the paste of specific types.
* @param types
* The types of data to form paste transactions for
* @returns An array of transactions that perform the paste.
*/
function getTransactions(types) {
var xferable = makeXferable(types);
clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
let action = this.clipboardAction;
var data = { }, type = { };
try {
xferable.getAnyTransferData(type, data, { });
data = data.value.QueryInterface(Ci.nsISupportsString).data;
var items = PlacesUtils.unwrapNodes(data, type.value);
var transactions = [];
var index = ip.index;
for (var i = 0; i < items.length; ++i) {
var txn;
if (ip.isTag) {
var uri = PlacesUtils._uri(items[i].uri);
txn = PlacesUIUtils.ptm.tagURI(uri, [ip.itemId]);
}
else {
// adjusted to make sure that items are given the correct index
// transactions insert differently if index == -1
// transaction will enqueue the item.
if (ip.index > -1)
index = ip.index + i;
txn = PlacesUIUtils.makeTransaction(items[i], type.value,
ip.itemId, index, true);
}
transactions.push(txn);
}
return transactions;
}
catch (e) {
// getAnyTransferData will throw if there is no data of the specified
// type on the clipboard.
// unwrapNodes will throw if the data that is present is malformed in
// some way.
// In either case, don't fail horribly, just return no data.
}
return [];
let xferable = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
// This order matters here! It controls the preferred flavors for this
// paste operation.
[ PlacesUtils.TYPE_X_MOZ_PLACE,
PlacesUtils.TYPE_X_MOZ_URL,
PlacesUtils.TYPE_UNICODE,
].forEach(function (type) xferable.addDataFlavor(type));
this.clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
// Now get the clipboard contents, in the best available flavor.
let data = {}, type = {}, items = [];
try {
xferable.getAnyTransferData(type, data, {});
data = data.value.QueryInterface(Ci.nsISupportsString).data;
type = type.value;
items = PlacesUtils.unwrapNodes(data, type);
} catch(ex) {
// No supported data exists or nodes unwrap failed, just bail out.
return;
}
// Get transactions to paste any folders, separators or links that might
// be on the clipboard, aggregate them and execute them.
var transactions = getTransactions([PlacesUtils.TYPE_X_MOZ_PLACE,
PlacesUtils.TYPE_X_MOZ_URL,
PlacesUtils.TYPE_UNICODE]);
var txn = PlacesUIUtils.ptm.aggregateTransactions("Paste", transactions);
PlacesUIUtils.ptm.doTransaction(txn);
let transactions = [];
let insertionIndex = ip.index;
for (let i = 0; i < items.length; ++i) {
if (ip.isTag) {
// Pasting into a tag container means tagging the item, regardless of
// the requested action.
transactions.push(
new PlacesTagURITransaction(PlacesUtils._uri(items[i].uri),
[ip.itemId])
);
continue;
}
// select the pasted items, they should be consecutive
var insertedNodeIds = [];
for (var i = 0; i < transactions.length; ++i)
insertedNodeIds.push(PlacesUtils.bookmarks
.getIdForItemAt(ip.itemId, ip.index + i));
// Adjust index to make sure items are pasted in the correct position.
// If index is DEFAULT_INDEX, items are just appended.
if (ip.index != PlacesUtils.bookmarks.DEFAULT_INDEX)
insertionIndex = ip.index + i;
transactions.push(
PlacesUIUtils.makeTransaction(items[i], type, ip.itemId,
insertionIndex, action == "copy")
);
}
PlacesUtils.transactionManager.doTransaction(
new PlacesAggregatedTransaction("Paste", transactions)
);
// Cut/past operations are not repeatable, so clear the clipboard.
if (action == "cut") {
this._clearClipboard();
}
// Select the pasted items, they should be consecutive.
let insertedNodeIds = [];
for (let i = 0; i < transactions.length; ++i) {
insertedNodeIds.push(
PlacesUtils.bookmarks.getIdForItemAt(ip.itemId, ip.index + i)
);
}
if (insertedNodeIds.length > 0)
this._view.selectItems(insertedNodeIds, false);
}

Просмотреть файл

@ -60,6 +60,14 @@
if (result) {
result.root.containerOpen = false;
}
// Unregister the controllber before unlinking the view, otherwise it
// may still try to update commands on a view with a null result.
if (this._controller) {
this._controller.terminate();
this.controllers.removeController(this._controller);
}
this.view = null;
]]></destructor>
@ -333,6 +341,17 @@
]]></getter>
</property>
<method name="toggleCutNode">
<parameter name="aNode"/>
<parameter name="aValue"/>
<body><![CDATA[
aNode._cutting = aValue;
try {
this.view.nodeIconChanged(aNode);
} catch(ex) { /* ignore no more valid nodes */ }
]]></body>
</method>
<!-- nsIPlacesView -->
<property name="removableSelectionRanges">
<getter><![CDATA[

Просмотреть файл

@ -1093,6 +1093,11 @@ PlacesTreeView.prototype = {
return;
let node = this._getNodeForRow(aRow);
if (node._cutting) {
aProperties.AppendElement(this._getAtomFor("cutting"));
}
if (!node._cellProperties) {
let properties = new Array();
let itemId = node.itemId;

Просмотреть файл

@ -75,19 +75,6 @@ var PlacesUIUtils = {
return URIFixup.createFixupURI(aSpec, Ci.nsIURIFixup.FIXUP_FLAG_NONE);
},
/**
* Wraps a string in a nsISupportsString wrapper
* @param aString
* The string to wrap
* @returns A nsISupportsString object containing a string.
*/
_wrapString: function PUIU__wrapString(aString) {
var s = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
s.data = aString;
return s;
},
getFormattedString: function PUIU_getFormattedString(key, params) {
return bundle.formatStringFromName(key, params, params.length);
},
@ -814,9 +801,7 @@ var PlacesUIUtils = {
browserWindow.whereToOpenLink(aEvent, false, true) : "window";
if (where == "window") {
// There is no browser window open, thus open a new one.
var uriList = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
uriList.data = urls.join("|");
var uriList = PlacesUtils.toISupportsString(urls.join("|"));
var args = Cc["@mozilla.org/supports-array;1"].
createInstance(Ci.nsISupportsArray);
args.AppendElement(uriList);

Просмотреть файл

@ -73,6 +73,7 @@ _BROWSER_TEST_FILES = \
browser_toolbar_migration.js \
browser_library_batch_delete.js \
browser_555547.js \
browser_416459_cut.js \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)

Просмотреть файл

@ -0,0 +1,68 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
const TEST_URL = "http://example.com/";
let gLibrary;
let gItemId;
function test() {
waitForExplicitFinish();
gLibrary = openLibrary(onLibraryReady);
}
function onLibraryReady(library) {
PlacesOrganizer = gLibrary.PlacesOrganizer;
// Sanity checks.
ok(PlacesUtils, "PlacesUtils in scope");
ok(PlacesUIUtils, "PlacesUIUtils in scope");
ok(PlacesOrganizer, "PlacesOrganizer in scope");
gItemId = PlacesUtils.bookmarks.insertBookmark(
PlacesUtils.toolbarFolderId, NetUtil.newURI(TEST_URL),
PlacesUtils.bookmarks.DEFAULT_INDEX, "test"
);
selectBookmarkIn("BookmarksToolbar");
waitForClipboard(function(aData) !!aData,
cutSelection,
onClipboardReady,
PlacesUtils.TYPE_X_MOZ_PLACE);
}
function selectBookmarkIn(aLeftPaneQuery) {
info("Selecting " + aLeftPaneQuery + " in the left pane");
PlacesOrganizer.selectLeftPaneQuery(aLeftPaneQuery);
let rootId = PlacesUtils.getConcreteItemId(PlacesOrganizer._places.selectedNode);
is(PlacesUtils.bookmarks.getFolderIdForItem(gItemId), rootId,
"Bookmark has the right parent");
info("Selecting the bookmark in the right pane");
PlacesOrganizer._content.selectItems([gItemId]);
let bookmarkNode = PlacesOrganizer._content.selectedNode;
is(bookmarkNode.uri, TEST_URL, "Found the expected bookmark");
}
function cutSelection() {
info("Cutting selection");
PlacesOrganizer._content.controller.cut();
}
function pasteClipboard(aLeftPaneQuery) {
info("Selecting " + aLeftPaneQuery + " in the left pane");
PlacesOrganizer.selectLeftPaneQuery(aLeftPaneQuery);
info("Pasting clipboard");
PlacesOrganizer._content.controller.paste();
}
function onClipboardReady() {
pasteClipboard("UnfiledBookmarks");
selectBookmarkIn("UnfiledBookmarks");
// Cleanup.
gLibrary.close();
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
finish();
}

Просмотреть файл

@ -16,9 +16,13 @@ registerCleanupFunction(function(){
function openLibrary(callback) {
var library = window.openDialog("chrome://browser/content/places/places.xul",
let library = window.openDialog("chrome://browser/content/places/places.xul",
"", "chrome,toolbar=yes,dialog=no,resizable");
waitForFocus(function () {
callback(library);
}, library);
return library;
}
Components.utils.import("resource://gre/modules/NetUtil.jsm");

Просмотреть файл

@ -230,6 +230,16 @@ menuitem.bookmark-item {
list-style-image: url("moz-icon://stock/gtk-directory?size=menu");
}
.bookmark-item[cutting] > .toolbarbutton-icon,
.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-icon {
opacity: 0.5;
}
.bookmark-item[cutting] > .toolbarbutton-text,
.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-text {
opacity: 0.7;
}
/* Stock icons for the menu bar items */
menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
-moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic");

Просмотреть файл

@ -99,13 +99,12 @@ treechildren::-moz-tree-image(title, query, folder) {
list-style-image: url("moz-icon://stock/gtk-directory?size=menu");
}
treechildren::-moz-tree-row(session-start) {
border-top:1px dotted ThreeDShadow;
font-weight: bold;
treechildren::-moz-tree-image(cutting) {
opacity: 0.5;
}
treechildren::-moz-tree-cell-text(date, session-continue) {
color: -moz-Field;
treechildren::-moz-tree-cell-text(cutting) {
opacity: 0.7;
}
/**** menuitem stock icons ****/

Просмотреть файл

@ -263,6 +263,16 @@ toolbarbutton.bookmark-item > menupopup {
height: 16px;
}
.bookmark-item[cutting] > .toolbarbutton-icon,
.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-icon {
opacity: 0.5;
}
.bookmark-item[cutting] > .toolbarbutton-text,
.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-text {
opacity: 0.7;
}
#bookmarksToolbarFolderMenu,
#BMB_bookmarksToolbar {
list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png");

Просмотреть файл

@ -119,10 +119,6 @@ treechildren::-moz-tree-image(title, separator) {
margin: 0;
}
treechildren::-moz-tree-row(session-start) {
border-top:1px dotted ThreeDShadow;
}
treechildren::-moz-tree-image(container, OrganizerQuery_AllBookmarks) {
list-style-image: url("chrome://browser/skin/places/allBookmarks.png");
}
@ -178,12 +174,6 @@ treechildren::-moz-tree-image(title, query, folder, open) {
-moz-image-region: rect(0, 16px, 16px, 0);
}
/* FIXME this should make the date field invisible, but only does it for
unselected items and maybe won't work for different color schemes. */
treechildren::-moz-tree-cell-text(date, session-continue) {
color:white;
}
treechildren::-moz-tree-cell-text(title, separator) {
color: ThreeDShadow;
margin: 0px 5px;
@ -197,3 +187,11 @@ treechildren::-moz-tree-twisty(title, separator) {
-moz-appearance: none;
padding: 0px;
}
treechildren::-moz-tree-image(cutting) {
opacity: 0.5;
}
treechildren::-moz-tree-cell-text(cutting) {
opacity: 0.7;
}

Просмотреть файл

@ -566,6 +566,16 @@ menuitem.bookmark-item {
-moz-image-region: rect(16px, 32px, 32px, 16px);
}
.bookmark-item[cutting] > .toolbarbutton-icon,
.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-icon {
opacity: 0.5;
}
.bookmark-item[cutting] > .toolbarbutton-text,
.bookmark-item[cutting] > .menu-iconic-left > .menu-iconic-text {
opacity: 0.7;
}
/* ::::: primary toolbar buttons ::::: */
.toolbarbutton-1 {

Просмотреть файл

@ -116,13 +116,12 @@ treechildren::-moz-tree-image(title, query, folder, open) {
-moz-image-region: rect(16px, 32px, 32px, 16px);
}
treechildren::-moz-tree-row(session-start) {
border-top:1px dotted ThreeDShadow;
font-weight: bold;
treechildren::-moz-tree-image(cutting) {
opacity: 0.5;
}
treechildren::-moz-tree-cell-text(date, session-continue) {
color: -moz-Field;
treechildren::-moz-tree-cell-text(cutting) {
opacity: 0.7;
}
/* Browser Sidebars */

Просмотреть файл

@ -1,3 +1,5 @@
# -*- makefile -*-
# vim:set ts=8 sw=8 sts=8 noet:
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
@ -23,6 +25,7 @@
# Benjamin Smedberg <bsmedberg@covad.net>
# Chase Phillips <chase@mozilla.org>
# Mark Mentovai <mark@moxienet.com>
# Joey Armstrong <joey@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
@ -95,14 +98,11 @@ endif
AUTOCONF ?= $(shell which autoconf-2.13 autoconf2.13 autoconf213 2>/dev/null | grep -v '^no autoconf' | head -1)
ifeq (,$(strip $(AUTOCONF)))
AUTOCONF=$(error Couldn't find autoconf 2.13)
AUTOCONF=$(error Could not find autoconf 2.13)
endif
MKDIR := mkdir
SH := /bin/sh
ifndef MAKE
MAKE := gmake
endif
PERL ?= perl
PYTHON ?= python

Просмотреть файл

@ -8451,7 +8451,10 @@ if test -z "${GLIB_CFLAGS}" -o -z "${GLIB_LIBS}" ; then
fi
fi
if test -z "${GLIB_GMODULE_LIBS}" -a -n "${GLIB_CONFIG}"; then
if test -z "${GLIB_GMODULE_LIBS}" \
-a -n "${GLIB_CONFIG}"\
-a "${GLIB_CONFIG}" != no\
; then
GLIB_GMODULE_LIBS=`$GLIB_CONFIG gmodule --libs`
fi

Просмотреть файл

@ -72,8 +72,10 @@ public:
NS_DECL_NSIDOMFILE
NS_DECL_NSIXHRSENDABLE
nsDOMFile(nsIFile *aFile, const nsAString& aContentType)
nsDOMFile(nsIFile *aFile, const nsAString& aContentType,
nsISupports *aCacheToken = nsnull)
: mFile(aFile),
mCacheToken(aCacheToken),
mContentType(aContentType),
mIsFullFile(true)
{}
@ -86,6 +88,7 @@ public:
nsDOMFile(const nsDOMFile* aOther, PRUint64 aStart, PRUint64 aLength,
const nsAString& aContentType)
: mFile(aOther->mFile),
mCacheToken(aOther->mCacheToken),
mStart(aOther->mIsFullFile ? aStart :
(aOther->mStart + aStart)),
mLength(aLength),
@ -112,6 +115,7 @@ public:
protected:
nsCOMPtr<nsIFile> mFile;
nsCOMPtr<nsISupports> mCacheToken;
// start and length in
PRUint64 mStart;

Просмотреть файл

@ -1915,6 +1915,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
}
tmp->mFirstChild = nsnull;
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mScriptEventManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mXPathEvaluatorTearoff)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCachedRootElement)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDisplayDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstBaseNodeWithHref)
@ -1937,16 +1939,27 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
tmp->mBoxObjectTable = nsnull;
}
if (tmp->mListenerManager) {
tmp->mListenerManager->Disconnect();
tmp->mListenerManager = nsnull;
}
if (tmp->mSubDocuments) {
PL_DHashTableDestroy(tmp->mSubDocuments);
tmp->mSubDocuments = nsnull;
}
tmp->mAnimationFrameListeners.Clear();
tmp->mRadioGroups.Clear();
// nsDocument has a pretty complex destructor, so we're going to
// assume that *most* cycles you actually want to break somewhere
// else, and not unlink an awful lot here.
//
// In rare cases where you think an unlink will help here, add one
// manually.
tmp->mInUnlinkOrDeletion = PR_FALSE;
tmp->mIdentifierMap.Clear();
tmp->mInUnlinkOrDeletion = PR_FALSE;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

Просмотреть файл

@ -1616,8 +1616,25 @@ void nsXMLHttpRequest::CreateResponseBlob(nsIRequest *request)
if (file) {
nsCAutoString contentType;
mChannel->GetContentType(contentType);
mResponseBlob = new nsDOMFile(file,
NS_ConvertASCIItoUTF16(contentType));
nsCOMPtr<nsISupports> cacheToken;
if (cc) {
cc->GetCacheToken(getter_AddRefs(cacheToken));
}
NS_ConvertASCIItoUTF16 wideContentType(contentType);
nsCOMPtr<nsIDOMBlob> blob =
new nsDOMFile(file, wideContentType, cacheToken);
// XXXkhuey this is a complete hack ... but we need to get 6 out the door
// The response blob here should not be a File object, it should only
// be a Blob. Unfortunately, because nsDOMFile has grown through
// accretion over the years and is in dangerous need of a refactoring,
// slicing it is the easiest way to get there ...
PRUint64 size = 0;
blob->GetSize(&size);
blob->MozSlice(0, size, wideContentType, 2, getter_AddRefs(mResponseBlob));
mResponseBody.Truncate();
mResponseBodyUnicode.SetIsVoid(PR_TRUE);
}
@ -1888,9 +1905,20 @@ nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult
void *blobData = PR_Malloc(blobLen);
if (blobData) {
memcpy(blobData, mResponseBody.BeginReading(), blobLen);
mResponseBlob =
NS_ConvertASCIItoUTF16 wideContentType(contentType);
nsCOMPtr<nsIDOMBlob> blob =
new nsDOMMemoryFile(blobData, blobLen, EmptyString(),
NS_ConvertASCIItoUTF16(contentType));
wideContentType);
// XXXkhuey this is a complete hack ... but we need to get 6 out the door
// The response blob here should not be a File object, it should only
// be a Blob. Unfortunately, because nsDOMFile has grown through
// accretion over the years and is in dangerous need of a refactoring,
// slicing it is the easiest way to get there ...
blob->MozSlice(0, blobLen, wideContentType,
2, getter_AddRefs(mResponseBlob));
mResponseBody.Truncate();
}
NS_ASSERTION(mResponseBodyUnicode.IsVoid(),

Просмотреть файл

@ -160,6 +160,8 @@ checkResponseTextAccessThrows(xhr);
checkResponseXMLAccessThrows(xhr);
b = xhr.response;
ok(b, "should have a non-null blob");
ok(b instanceof Blob, "should be a Blob");
ok(!(b instanceof File), "should not be a File");
is(b.size, "hello pass\n".length, "wrong blob size");
var fr = new FileReader();

Просмотреть файл

@ -57,6 +57,21 @@ NS_INTERFACE_MAP_END
/* Implementation */
static nsresult
GetValueFromString(const nsAString &aValueAsString,
PRBool *aValue)
{
if (aValueAsString.EqualsLiteral("true")) {
*aValue = PR_TRUE;
return NS_OK;
}
if (aValueAsString.EqualsLiteral("false")) {
*aValue = PR_FALSE;
return NS_OK;
}
return NS_ERROR_DOM_SYNTAX_ERR;
}
nsresult
nsSVGBoolean::SetBaseValueString(const nsAString &aValueAsString,
nsSVGElement *aSVGElement,
@ -64,12 +79,10 @@ nsSVGBoolean::SetBaseValueString(const nsAString &aValueAsString,
{
PRBool val;
if (aValueAsString.EqualsLiteral("true"))
val = PR_TRUE;
else if (aValueAsString.EqualsLiteral("false"))
val = PR_FALSE;
else
return NS_ERROR_DOM_SYNTAX_ERR;
nsresult rv = GetValueFromString(aValueAsString, &val);
if (NS_FAILED(rv)) {
return rv;
}
mBaseVal = val;
if (!mIsAnimated) {
@ -148,17 +161,17 @@ nsSVGBoolean::SMILBool::ValueFromString(const nsAString& aStr,
nsSMILValue& aValue,
PRBool& aPreventCachingOfSandwich) const
{
PRBool value;
nsresult rv = GetValueFromString(aStr, &value);
if (NS_FAILED(rv)) {
return rv;
}
nsSMILValue val(&SMILBoolType::sSingleton);
if (aStr.EqualsLiteral("true"))
val.mU.mBool = PR_TRUE;
else if (aStr.EqualsLiteral("false"))
val.mU.mBool = PR_FALSE;
else
return NS_ERROR_FAILURE;
val.mU.mBool = value;
aValue = val;
aPreventCachingOfSandwich = PR_FALSE;
return NS_OK;
}

Просмотреть файл

@ -391,6 +391,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULDocument, nsXMLDocument)
delete tmp->mTemplateBuilderTable;
tmp->mTemplateBuilderTable = nsnull;
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCommandDispatcher)
//XXX We should probably unlink all the objects we traverse.
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

Просмотреть файл

@ -190,13 +190,20 @@ nsXULPrototypeDocument::~nsXULPrototypeDocument()
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPrototypeDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsXULPrototypeDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULPrototypeDocument)
tmp->mPrototypeWaiters.Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULPrototypeDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mRoot,
nsXULPrototypeElement)
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mGlobalObject");
cb.NoteXPCOMChild(static_cast<nsIScriptGlobalObject*>(tmp->mGlobalObject));
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mNodeInfoManager,
nsNodeInfoManager)
for (PRUint32 i = 0; i < tmp->mPrototypeWaiters.Length(); ++i) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mPrototypeWaiters[i]");
cb.NoteXPCOMChild(static_cast<nsINode*>(tmp->mPrototypeWaiters[i].get()));
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULPrototypeDocument)

Просмотреть файл

@ -81,9 +81,15 @@ public:
mQuerySetPriority(aQuerySetPriority),
mContainer(aContainer),
mResult(aResult),
mNext(nsnull) {}
mNext(nsnull)
{
MOZ_COUNT_CTOR(nsTemplateMatch);
}
~nsTemplateMatch() {}
~nsTemplateMatch()
{
MOZ_COUNT_DTOR(nsTemplateMatch);
}
static nsTemplateMatch*
Create(nsFixedSizeAllocator& aPool,

Просмотреть файл

@ -275,6 +275,11 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateBuilder)
if (tmp->mMatchMap.IsInitialized()) {
tmp->mMatchMap.Enumerate(DestroyMatchList, &(tmp->mPool));
}
for (PRUint32 i = 0; i < tmp->mQuerySets.Length(); ++i) {
nsTemplateQuerySet* qs = tmp->mQuerySets[i];
delete qs;
}
tmp->mQuerySets.Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULTemplateBuilder)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDataSource)

Просмотреть файл

@ -86,7 +86,9 @@ nsIRDFResource* nsXULTemplateQueryProcessorRDF::kNC_BookmarkSeparator;
nsIRDFResource* nsXULTemplateQueryProcessorRDF::kRDF_type;
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateQueryProcessorRDF)
NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsXULTemplateQueryProcessorRDF)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateQueryProcessorRDF)
tmp->Done();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
static PLDHashOperator
BindingDependenciesTraverser(nsISupports* key,
@ -1056,7 +1058,7 @@ nsXULTemplateQueryProcessorRDF::SynchronizeAll(nsIRDFResource* aSource,
// Get all the matches whose assignments are currently supported
// by aSource and aProperty: we'll need to recompute them.
nsCOMArray<nsXULTemplateResultRDF>* results;
if (!mBindingDependencies.Get(aSource, &results))
if (!mBindingDependencies.Get(aSource, &results) || !mBuilder)
return NS_OK;
PRUint32 length = results->Count();
@ -1125,6 +1127,7 @@ nsXULTemplateQueryProcessorRDF::CheckContainer(nsIRDFResource* aResource,
PRBool* aIsContainer)
{
NS_ENSURE_ARG_POINTER(aIsContainer);
NS_ENSURE_STATE(mDB);
// We have to look at all of the arcs extending out of the
// resource: if any of them are that "containment" property, then
@ -1159,6 +1162,7 @@ nsresult
nsXULTemplateQueryProcessorRDF::CheckEmpty(nsIRDFResource* aResource,
PRBool* aIsEmpty)
{
NS_ENSURE_STATE(mDB);
*aIsEmpty = PR_TRUE;
for (nsResourceSet::ConstIterator property = mContainmentProperties.First();
@ -1186,6 +1190,7 @@ nsresult
nsXULTemplateQueryProcessorRDF::CheckIsSeparator(nsIRDFResource* aResource,
PRBool* aIsSeparator)
{
NS_ENSURE_STATE(mDB);
return mDB->HasAssertion(aResource, kRDF_type, kNC_BookmarkSeparator,
PR_TRUE, aIsSeparator);
}
@ -1903,7 +1908,7 @@ nsXULTemplateQueryProcessorRDF::GetContainerIndexOf(nsIXULTemplateResult* aResul
nsCOMPtr<nsISupports> ref;
nsresult rv = aResult->GetBindingObjectFor(mRefVariable,
getter_AddRefs(ref));
if (NS_FAILED(rv))
if (NS_FAILED(rv) || !mDB)
return -1;
nsCOMPtr<nsIRDFResource> container = do_QueryInterface(ref);
@ -1940,7 +1945,7 @@ nsXULTemplateQueryProcessorRDF::GetSortValue(nsIXULTemplateResult* aResult,
return rv;
nsCOMPtr<nsIRDFNode> value;
if (source) {
if (source && mDB) {
// first check predicate?sort=true so that datasources may use a
// custom value for sorting
rv = mDB->GetTarget(source, aSortPredicate, PR_TRUE,

Просмотреть файл

@ -81,6 +81,7 @@ class nsXULTreeBuilder : public nsXULTemplateBuilder,
public:
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeBuilder, nsXULTemplateBuilder)
// nsIXULTreeBuilder
NS_DECL_NSIXULTREEBUILDER
@ -304,15 +305,42 @@ NS_NewXULTreeBuilder(nsISupports* aOuter, REFNSIID aIID, void** aResult)
return rv;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTreeBuilder)
NS_IMPL_ADDREF_INHERITED(nsXULTreeBuilder, nsXULTemplateBuilder)
NS_IMPL_RELEASE_INHERITED(nsXULTreeBuilder, nsXULTemplateBuilder)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeBuilder, nsXULTemplateBuilder)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mBoxObject)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSelection)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPersistStateStore)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mObservers)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
static PRBool TraverseObservers(nsISupports* aElement, void *aData)
{
nsCycleCollectionTraversalCallback *cb =
static_cast<nsCycleCollectionTraversalCallback*>(aData);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mObservers[i]");
cb->NoteXPCOMChild(aElement);
return PR_TRUE;
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeBuilder, nsXULTemplateBuilder)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mBoxObject)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSelection)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPersistStateStore)
if (tmp->mObservers) {
tmp->mObservers->EnumerateForwards(TraverseObservers, &cb);
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
DOMCI_DATA(XULTreeBuilder, nsXULTreeBuilder)
NS_INTERFACE_MAP_BEGIN(nsXULTreeBuilder)
NS_INTERFACE_MAP_ENTRY(nsIXULTreeBuilder)
NS_INTERFACE_MAP_ENTRY(nsITreeView)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XULTreeBuilder)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXULTreeBuilder)
NS_INTERFACE_MAP_ENTRY(nsIXULTreeBuilder)
NS_INTERFACE_MAP_ENTRY(nsITreeView)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XULTreeBuilder)
NS_INTERFACE_MAP_END_INHERITING(nsXULTemplateBuilder)

Просмотреть файл

@ -120,10 +120,19 @@ interface nsIXPCComponents_utils_Sandbox : nsISupports
{
};
/**
* interface for callback to be passed to Cu.schedulePreciseGC
*/
[scriptable, function, uuid(71000535-b0fd-44d1-8ce0-909760e3953c)]
interface ScheduledGCCallback : nsISupports
{
void callback();
};
/**
* interface of Components.utils
*/
[scriptable, uuid(5f0acf45-135a-48d1-976c-082ce3b24ead)]
[scriptable, uuid(fed2d752-6cb3-4135-97b0-2c290e541e2d)]
interface nsIXPCComponents_Utils : nsISupports
{
@ -228,6 +237,13 @@ interface nsIXPCComponents_Utils : nsISupports
*/
void forceGC();
/*
* Schedule a garbage collection cycle for a point in the future when no JS
* is running. Call the provided function once this has occurred.
*/
[implicit_jscontext]
void schedulePreciseGC(in ScheduledGCCallback callback);
/*
* To be called from JS only.
*

Просмотреть файл

@ -55,6 +55,7 @@
#include "nsNullPrincipal.h"
#include "nsJSUtils.h"
#include "mozJSComponentLoader.h"
#include "nsContentUtils.h"
/***************************************************************************/
// stuff used by all
@ -3775,6 +3776,48 @@ nsXPCComponents_Utils::ForceGC()
return NS_OK;
}
class PreciseGCRunnable : public nsRunnable
{
public:
PreciseGCRunnable(JSContext *aCx, ScheduledGCCallback* aCallback)
: mCallback(aCallback), mCx(aCx) {}
NS_IMETHOD Run()
{
nsCOMPtr<nsIJSRuntimeService> runtimeSvc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
NS_ENSURE_STATE(runtimeSvc);
JSRuntime* rt = nsnull;
runtimeSvc->GetRuntime(&rt);
NS_ENSURE_STATE(rt);
JSContext *cx;
JSContext *iter = nsnull;
while ((cx = JS_ContextIterator(rt, &iter)) != NULL) {
if (JS_IsRunning(cx)) {
return NS_DispatchToMainThread(this);
}
}
JS_GC(mCx);
mCallback->Callback();
return NS_OK;
}
private:
nsRefPtr<ScheduledGCCallback> mCallback;
JSContext *mCx;
};
/* [inline_jscontext] void schedulePreciseGC(in ScheduledGCCallback callback); */
NS_IMETHODIMP
nsXPCComponents_Utils::SchedulePreciseGC(ScheduledGCCallback* aCallback, JSContext* aCx)
{
nsRefPtr<PreciseGCRunnable> event = new PreciseGCRunnable(aCx, aCallback);
return NS_DispatchToMainThread(event);
}
/* void getGlobalForObject(); */
NS_IMETHODIMP
nsXPCComponents_Utils::GetGlobalForObject()

Просмотреть файл

@ -66,6 +66,7 @@ _CHROME_FILES = \
test_bug596580.xul \
test_bug654370.xul \
test_bug658560.xul \
test_precisegc.xul \
$(NULL)
# Disabled until this test gets updated to test the new proxy based

Просмотреть файл

@ -0,0 +1,29 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=533596
-->
<window title="Mozilla Bug 661927"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
</body>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
Components.utils.schedulePreciseGC(
function() {
ok(true, "callback executed");
SimpleTest.finish();
});
SimpleTest.waitForExplicitFinish();
]]></script>
</window>

Просмотреть файл

@ -3656,6 +3656,7 @@ DocumentViewerImpl::Print(nsIPrintSettings* aPrintSettings,
return pDoc->Print();
if (!mPrintEngine) {
NS_ENSURE_STATE(mDeviceContext);
mPrintEngine = new nsPrintEngine();
rv = mPrintEngine->Initialize(this, mContainer, mDocument,

Просмотреть файл

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="data:text/css,
tree { height: 100px; -moz-appearance: none; border: none; }
treecol, treecolpicker { visibility: hidden; }
treechildren::-moz-tree-cell-text { opacity: 0; }
"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<tree>
<treecols>
<treecol flex="1"/>
</treecols>
<treechildren>
<treeitem>
<treerow>
<treecell label="test"/>
</treerow>
</treeitem>
</treechildren>
</tree>
</window>

Просмотреть файл

@ -1649,3 +1649,4 @@ fails-if(layersGPUAccelerated&&cocoaWidget) == 654950-1.html 654950-1-ref.html #
== 658952.html 658952-ref.html
== 664127-1.xul 664127-1-ref.xul
== 660682-1.html 660682-1-ref.html
== 668319-1.xul about:blank

Просмотреть файл

@ -3553,6 +3553,9 @@ nsTreeBodyFrame::PaintText(PRInt32 aRowIndex,
// out and to paint.
nsStyleContext* textContext = GetPseudoStyleContext(nsCSSAnonBoxes::moztreecelltext);
// Obtain opacity value for the image.
float opacity = textContext->GetStyleDisplay()->mOpacity;
// Obtain the margins for the text and then deflate our rect by that
// amount. The text is assumed to be contained within the deflated rect.
nsRect textRect(aTextRect);
@ -3619,8 +3622,19 @@ nsTreeBodyFrame::PaintText(PRInt32 aRowIndex,
PRUint8 direction = aTextRTL ? NS_STYLE_DIRECTION_RTL :
NS_STYLE_DIRECTION_LTR;
gfxContext* ctx = aRenderingContext.ThebesContext();
if (opacity != 1.0f) {
ctx->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
}
nsLayoutUtils::DrawString(this, &aRenderingContext, text.get(), text.Length(),
textRect.TopLeft() + nsPoint(0, baseline), direction);
if (opacity != 1.0f) {
ctx->PopGroupToSource();
ctx->Paint(opacity);
}
#ifdef MOZ_TIMELINE
NS_TIMELINE_STOP_TIMER("Render Outline Text");
NS_TIMELINE_MARK_TIMER("Render Outline Text");

Просмотреть файл

@ -428,12 +428,14 @@ HistoryTracker.prototype = {
onEndUpdateBatch: function HT_onEndUpdateBatch() {},
onPageChanged: function HT_onPageChanged() {},
onTitleChanged: function HT_onTitleChanged() {},
onDeleteVisits: function () {},
onDeleteURI: function () {},
/* Every add is worth 1 point.
* OnBeforeDeleteURI will triggger a sync for MULTI-DEVICE (see below)
* Clearing all history will trigger a sync for MULTI-DEVICE (see below)
*/
_upScoreXLarge: function BMT__upScore() {
_upScoreXLarge: function HT__upScoreXLarge() {
this.score += SCORE_INCREMENT_XLARGE;
},
@ -445,18 +447,16 @@ HistoryTracker.prototype = {
this.score += SCORE_INCREMENT_SMALL;
}
},
onDeleteVisits: function onDeleteVisits() {
},
onBeforeDeleteURI: function onBeforeDeleteURI(uri, guid) {
if (this.ignoreAll)
onBeforeDeleteURI: function onBeforeDeleteURI(uri, guid, reason) {
if (this.ignoreAll || reason == Ci.nsINavHistoryObserver.REASON_EXPIRED)
return;
this._log.trace("onBeforeDeleteURI: " + uri.spec);
if (this.addChangedID(guid)) {
this._upScoreXLarge();
}
},
onDeleteURI: function HT_onDeleteURI(uri, guid) {
},
onClearHistory: function HT_onClearHistory() {
this._log.trace("onClearHistory");
this._upScoreXLarge();

Просмотреть файл

@ -21,10 +21,10 @@ let tracker = engine._tracker;
let _counter = 0;
function addVisit() {
PlacesUtils.history.addVisit(
Utils.makeURI("http://getfirefox.com/" + _counter),
Date.now() * 1000, null, 1, false, 0);
_counter += 1;
let uri = Utils.makeURI("http://getfirefox.com/" + _counter);
PlacesUtils.history.addVisit(uri, Date.now() * 1000, null, 1, false, 0);
_counter++;
return uri;
}
@ -87,6 +87,38 @@ add_test(function test_track_delete() {
PlacesUtils.history.removePage(uri);
});
add_test(function test_dont_track_expiration() {
_("Expirations are not tracked.");
let uriToExpire = addVisit();
let guidToExpire = engine._store.GUIDForUri(uriToExpire);
let uriToRemove = addVisit();
let guidToRemove = engine._store.GUIDForUri(uriToRemove);
tracker.clearChangedIDs();
do_check_false(guidToExpire in tracker.changedIDs);
do_check_false(guidToRemove in tracker.changedIDs);
onScoreUpdated(function() {
do_check_false(guidToExpire in tracker.changedIDs);
do_check_true(guidToRemove in tracker.changedIDs);
do_check_eq([id for (id in tracker.changedIDs)].length, 1);
run_next_test();
});
// Observe expiration.
Services.obs.addObserver(function onExpiration(aSubject, aTopic, aData) {
Services.obs.removeObserver(onExpiration, aTopic);
// Remove the remaining page to update its score.
PlacesUtils.history.removePage(uriToRemove);
}, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
// Force expiration of 1 entry.
Services.prefs.setIntPref("places.history.expiration.max_pages", 0);
Cc["@mozilla.org/places/expiration;1"]
.getService(Ci.nsIObserver)
.observe(null, "places-debug-start-expiration", 1);
});
add_test(function test_stop_tracking() {
_("Let's stop tracking again.");
tracker.clearChangedIDs();

Просмотреть файл

@ -1858,19 +1858,25 @@ nsDownloadManager::OnVisit(nsIURI *aURI, PRInt64 aVisitID, PRTime aTime,
}
NS_IMETHODIMP
nsDownloadManager::OnTitleChanged(nsIURI *aURI, const nsAString &aPageTitle)
nsDownloadManager::OnTitleChanged(nsIURI *aURI,
const nsAString &aPageTitle,
const nsACString &aGUID)
{
return NS_OK;
}
NS_IMETHODIMP
nsDownloadManager::OnBeforeDeleteURI(nsIURI *aURI, const nsACString& aGUID)
nsDownloadManager::OnBeforeDeleteURI(nsIURI *aURI,
const nsACString& aGUID,
PRUint16 aReason)
{
return NS_OK;
}
NS_IMETHODIMP
nsDownloadManager::OnDeleteURI(nsIURI *aURI, const nsACString& aGUID)
nsDownloadManager::OnDeleteURI(nsIURI *aURI,
const nsACString& aGUID,
PRUint16 aReason)
{
return RemoveDownloadsForURI(aURI);
}
@ -1882,15 +1888,18 @@ nsDownloadManager::OnClearHistory()
}
NS_IMETHODIMP
nsDownloadManager::OnPageChanged(nsIURI *aURI, PRUint32 aWhat,
const nsAString &aValue)
nsDownloadManager::OnPageChanged(nsIURI *aURI,
PRUint32 aChangedAttribute,
const nsAString& aNewValue,
const nsACString &aGUID)
{
return NS_OK;
}
NS_IMETHODIMP
nsDownloadManager::OnDeleteVisits(nsIURI *aURI, PRTime aVisitTime,
const nsACString& aGUID)
const nsACString& aGUID,
PRUint16 aReason)
{
// Don't bother removing downloads until the page is removed.
return NS_OK;

Просмотреть файл

@ -120,7 +120,7 @@ FetchPageInfo(StatementCache<mozIStorageStatement>& aStmtCache,
nsCOMPtr<mozIStorageStatement> stmt =
aStmtCache.GetCachedStatement(NS_LITERAL_CSTRING(
"SELECT h.id, h.favicon_id, "
"SELECT h.id, h.favicon_id, h.guid, "
"(") + redirectedBookmarksFragment + NS_LITERAL_CSTRING(") "
"FROM moz_places h WHERE h.url = :page_url"
));
@ -142,19 +142,20 @@ FetchPageInfo(StatementCache<mozIStorageStatement>& aStmtCache,
rv = stmt->GetInt64(0, &_page.id);
NS_ENSURE_SUCCESS(rv, rv);
PRBool isNull;
stmt->GetIsNull(1, &isNull);
rv = stmt->GetIsNull(1, &isNull);
NS_ENSURE_SUCCESS(rv, rv);
// favicon_id can be NULL.
if (!isNull) {
rv = stmt->GetInt64(1, &_page.iconId);
NS_ENSURE_SUCCESS(rv, rv);
}
stmt->GetIsNull(2, &isNull);
rv = stmt->GetUTF8String(2, _page.guid);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->GetIsNull(3, &isNull);
NS_ENSURE_SUCCESS(rv, rv);
// The page could not be bookmarked.
if (!isNull) {
rv = stmt->GetUTF8String(2, _page.bookmarkedSpec);
rv = stmt->GetUTF8String(3, _page.bookmarkedSpec);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -807,6 +808,10 @@ AsyncAssociateIconToPage::Run()
rv = stmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
// Get the new id and GUID.
rv = FetchPageInfo(mFaviconSvc->mSyncStatements, mPage);
NS_ENSURE_SUCCESS(rv, rv);
mIcon.status |= ICON_STATUS_ASSOCIATED;
}
// Otherwise just associate the icon to the page, if needed.
@ -959,7 +964,7 @@ NotifyIconObservers::Run()
rv = NS_NewURI(getter_AddRefs(pageURI), mPage.spec);
NS_ENSURE_SUCCESS(rv, rv);
mFaviconSvc->SendFaviconNotifications(pageURI, iconURI);
mFaviconSvc->SendFaviconNotifications(pageURI, iconURI, mPage.guid);
// If the page is bookmarked and the bookmarked url is different from the
// updated one, start a new task to update its icon as well.

Просмотреть файл

@ -102,6 +102,7 @@ struct PageData
, canAddToHistory(true)
, iconId(0)
{
guid.SetIsVoid(PR_TRUE);
}
PRInt64 id;
@ -110,6 +111,7 @@ struct PageData
nsString revHost;
bool canAddToHistory; // False for disabled history and unsupported schemas.
PRInt64 iconId;
nsCString guid;
};
/**

Просмотреть файл

@ -499,9 +499,11 @@ public:
* The new title to notify about.
*/
NotifyTitleObservers(const nsCString& aSpec,
const nsString& aTitle)
const nsString& aTitle,
const nsCString& aGUID)
: mSpec(aSpec)
, mTitle(aTitle)
, mGUID(aGUID)
{
}
@ -514,13 +516,14 @@ public:
NS_ENSURE_TRUE(navHistory, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIURI> uri;
(void)NS_NewURI(getter_AddRefs(uri), mSpec);
navHistory->NotifyTitleChange(uri, mTitle);
navHistory->NotifyTitleChange(uri, mTitle, mGUID);
return NS_OK;
}
private:
const nsCString mSpec;
const nsString mTitle;
const nsCString mGUID;
};
/**
@ -697,7 +700,7 @@ public:
// Notify about title change if needed.
if ((!known && !place.title.IsVoid()) || place.titleChanged) {
event = new NotifyTitleObservers(place.spec, place.title);
event = new NotifyTitleObservers(place.spec, place.title, place.guid);
rv = NS_DispatchToMainThread(event);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -1166,7 +1169,7 @@ public:
}
nsCOMPtr<nsIRunnable> event =
new NotifyTitleObservers(mPlace.spec, mPlace.title);
new NotifyTitleObservers(mPlace.spec, mPlace.title, mPlace.guid);
nsresult rv = NS_DispatchToMainThread(event);
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -129,6 +129,8 @@ var PlacesUtils = {
TYPE_HTML: "text/html",
// Place entries as raw URL text
TYPE_UNICODE: "text/unicode",
// Used to track the action that populated the clipboard.
TYPE_X_MOZ_PLACE_ACTION: "text/x-moz-place-action",
EXCLUDE_FROM_BACKUP_ANNO: "places/excludeFromBackup",
GUID_ANNO: "placesInternal/GUID",
@ -165,6 +167,19 @@ var PlacesUtils = {
return NetUtil.newURI(aSpec);
},
/**
* Wraps a string in a nsISupportsString wrapper.
* @param aString
* The string to wrap.
* @returns A nsISupportsString object containing a string.
*/
toISupportsString: function PU_toISupportsString(aString) {
let s = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
s.data = aString;
return s;
},
getFormattedString: function PU_getFormattedString(key, params) {
return bundle.formatStringFromName(key, params, params.length);
},

Просмотреть файл

@ -256,16 +256,92 @@ nsFaviconService::SetFaviconUrlForPage(nsIURI* aPageURI, nsIURI* aFaviconURI)
NS_ENSURE_ARG(aPageURI);
NS_ENSURE_ARG(aFaviconURI);
if (mFaviconsExpirationRunning)
// If we are about to expire all favicons, don't bother setting a new one.
if (mFaviconsExpirationRunning) {
return NS_OK;
}
PRBool hasData;
nsresult rv = SetFaviconUrlForPageInternal(aPageURI, aFaviconURI, &hasData);
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
if (history->InPrivateBrowsingMode()) {
return NS_OK;
}
nsresult rv;
PRInt64 iconId = -1;
PRBool hasData = PR_FALSE;
{
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBGetIconInfo);
rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("icon_url"), aFaviconURI);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasResult = PR_FALSE;
if (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
// We already have an entry for this icon, just get its stats.
rv = stmt->GetInt64(0, &iconId);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 dataSize;
rv = stmt->GetInt32(1, &dataSize);
NS_ENSURE_SUCCESS(rv, rv);
if (dataSize > 0) {
hasData = PR_TRUE;
}
}
}
mozStorageTransaction transaction(mDBConn, PR_FALSE);
if (iconId == -1) {
// We did not find any entry for this icon, so create a new one.
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBInsertIcon);
rv = stmt->BindNullByName(NS_LITERAL_CSTRING("icon_id"));
NS_ENSURE_SUCCESS(rv, rv);
rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("icon_url"), aFaviconURI);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindNullByName(NS_LITERAL_CSTRING("data"));
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindNullByName(NS_LITERAL_CSTRING("mime_type"));
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindNullByName(NS_LITERAL_CSTRING("expiration"));
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
{
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(getInfoStmt, mDBGetIconInfo);
rv = URIBinder::Bind(getInfoStmt, NS_LITERAL_CSTRING("icon_url"), aFaviconURI);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasResult;
rv = getInfoStmt->ExecuteStep(&hasResult);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(hasResult, "hasResult is false but the call succeeded?");
iconId = getInfoStmt->AsInt64(0);
}
}
// Now, link our icon entry with the page.
PRInt64 pageId;
nsCAutoString guid;
rv = history->GetOrCreateIdForPage(aPageURI, &pageId, guid);
NS_ENSURE_SUCCESS(rv, rv);
// send favicon change notifications if the URL has any data
if (hasData)
SendFaviconNotifications(aPageURI, aFaviconURI);
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBSetPageFavicon);
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("page_id"), pageId);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("icon_id"), iconId);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
// Send favicon change notifications only if the icon has any data.
if (hasData) {
SendFaviconNotifications(aPageURI, aFaviconURI, guid);
}
return NS_OK;
}
@ -284,115 +360,18 @@ nsFaviconService::GetDefaultFavicon(nsIURI** _retval)
return mDefaultIcon->Clone(_retval);
}
// nsFaviconService::SetFaviconUrlForPageInternal
//
// This creates a new entry in the favicon table if necessary and tells the
// history service to associate the given favicon ID with the given URI. We
// don't want to update the history table directly since that may involve
// creating a new row in the history table, which should only be done by
// history.
//
// This sets aHasData if there was already icon data for this favicon. Used
// to know if we should try reloading.
//
// Does NOT send out notifications. Caller should send out notifications
// if the favicon has data.
nsresult
nsFaviconService::SetFaviconUrlForPageInternal(nsIURI* aPageURI,
nsIURI* aFaviconURI,
PRBool* aHasData)
{
nsresult rv;
PRInt64 iconId = -1;
*aHasData = PR_FALSE;
nsNavHistory* historyService = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(historyService, NS_ERROR_OUT_OF_MEMORY);
if (historyService->InPrivateBrowsingMode())
return NS_OK;
mozStorageTransaction transaction(mDBConn, PR_FALSE);
{
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBGetIconInfo);
rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("icon_url"), aFaviconURI);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasResult = PR_FALSE;
if (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
// We already have an entry for this icon, just get the stats
rv = stmt->GetInt64(0, &iconId);
NS_ENSURE_SUCCESS(rv, rv);
// see if this icon has data already
PRInt32 dataSize;
rv = stmt->GetInt32(1, &dataSize);
NS_ENSURE_SUCCESS(rv, rv);
if (dataSize > 0)
*aHasData = PR_TRUE;
}
}
if (iconId == -1) {
// We did not find any entry, so create a new one
// not-binded params are automatically nullified by mozStorage
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBInsertIcon);
rv = stmt->BindNullByName(NS_LITERAL_CSTRING("icon_id"));
NS_ENSURE_SUCCESS(rv, rv);
rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("icon_url"), aFaviconURI);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
{
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(getInfoStmt, mDBGetIconInfo);
rv = URIBinder::Bind(getInfoStmt, NS_LITERAL_CSTRING("icon_url"), aFaviconURI);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasResult;
rv = getInfoStmt->ExecuteStep(&hasResult);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(hasResult, "hasResult is false but the call succeeded?");
iconId = getInfoStmt->AsInt64(0);
}
}
// now link our icon entry with the page
PRInt64 pageId;
rv = historyService->GetUrlIdFor(aPageURI, &pageId, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBSetPageFavicon);
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("page_id"), pageId);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("icon_id"), iconId);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
// nsFaviconService::SendFaviconNotifications
//
// Call to send out favicon changed notifications. Should only be called
// when you know there is data loaded for the favicon.
void
nsFaviconService::SendFaviconNotifications(nsIURI* aPageURI,
nsIURI* aFaviconURI)
nsIURI* aFaviconURI,
const nsACString& aGUID)
{
nsCAutoString faviconSpec;
nsNavHistory* historyService = nsNavHistory::GetHistoryService();
if (historyService && NS_SUCCEEDED(aFaviconURI->GetSpec(faviconSpec))) {
historyService->SendPageChangedNotification(aPageURI,
nsINavHistoryObserver::ATTRIBUTE_FAVICON,
NS_ConvertUTF8toUTF16(faviconSpec));
nsNavHistory* history = nsNavHistory::GetHistoryService();
if (history && NS_SUCCEEDED(aFaviconURI->GetSpec(faviconSpec))) {
history->SendPageChangedNotification(aPageURI,
nsINavHistoryObserver::ATTRIBUTE_FAVICON,
NS_ConvertUTF8toUTF16(faviconSpec),
aGUID);
}
}

Просмотреть файл

@ -144,7 +144,18 @@ public:
*/
nsresult FinalizeStatements();
void SendFaviconNotifications(nsIURI* aPage, nsIURI* aFaviconURI);
/**
* Call to send out favicon changed notifications. Should only be called
* when there is data loaded for the favicon.
* @param aPageURI
* The URI of the page to notify about.
* @param aFaviconURI
* The moz-anno:favicon URI of the icon.
* @param aGUID
* The unique ID associated with the page.
*/
void SendFaviconNotifications(nsIURI* aPageURI, nsIURI* aFaviconURI,
const nsACString& aGUID);
/**
* This cache should be used only for background thread statements.

Просмотреть файл

@ -809,7 +809,7 @@ interface nsINavHistoryResult : nsISupports
* DANGER! If you are in the middle of a batch transaction, there may be a
* database transaction active. You can still access the DB, but be careful.
*/
[scriptable, uuid(06602bb6-0774-4576-8855-ea930bb85bbe)]
[scriptable, uuid(c837f6ba-6ad7-4810-a425-8ce29e05d17e)]
interface nsINavHistoryObserver : nsISupports
{
/**
@ -870,9 +870,21 @@ interface nsINavHistoryObserver : nsISupports
* The URI of the page.
* @param aPageTitle
* The new title of the page.
* @param aGUID
* The unique ID associated with the page.
*/
void onTitleChanged(in nsIURI aURI,
in AString aPageTitle);
in AString aPageTitle,
in ACString aGUID);
/**
* Removed by the user.
*/
const unsigned short REASON_DELETED = 0;
/**
* Removed by automatic expiration.
*/
const unsigned short REASON_EXPIRED = 1;
/**
* This page and all of its visits are about to be deleted. Note: the page
@ -882,9 +894,12 @@ interface nsINavHistoryObserver : nsISupports
* The URI being deleted.
* @param aGUID
* The unique ID associated with the page.
* @param aReason
* Indicates the reason for the removal. See REASON_* constants.
*/
void onBeforeDeleteURI(in nsIURI aURI,
in ACString aGUID);
in ACString aGUID,
in unsigned short aReason);
/**
* This page and all of its visits are being deleted. Note: the page may not
@ -900,9 +915,12 @@ interface nsINavHistoryObserver : nsISupports
* The URI that was deleted.
* @param aGUID
* The unique ID associated with the page.
* @param aReason
* Indicates the reason for the removal. see REASON_* constants.
*/
void onDeleteURI(in nsIURI aURI,
in ACString aGUID);
in ACString aGUID,
in unsigned short aReason);
/**
* Notification that all of history is being deleted.
@ -910,20 +928,27 @@ interface nsINavHistoryObserver : nsISupports
void onClearHistory();
/**
* A page has had some attribute on it changed. Note that for TYPED and
* HIDDEN, the page may not necessarily have been added yet.
* onPageChanged attribute indicating that favicon has been updated.
* aNewValue parameter will be set to the new favicon URI string.
*/
const unsigned long ATTRIBUTE_FAVICON = 3;
/**
* An attribute of this page changed.
*
* @param aURI
* The URI of the page on which an attribute changed.
* @param aWhat
* The attribute whose value changed.
* @param aValue
* The attribute's new value.
* The URI of the page on which an attribute changed.
* @param aChangedAttribute
* The attribute whose value changed. See ATTRIBUTE_* constants.
* @param aNewValue
* The attribute's new value.
* @param aGUID
* The unique ID associated with the page.
*/
const unsigned long ATTRIBUTE_FAVICON = 3; // favicon updated, aString = favicon annotation URI
void onPageChanged(in nsIURI aURI,
in unsigned long aWhat,
in AString aValue);
in unsigned long aChangedAttribute,
in AString aNewValue,
in ACString aGUID);
/**
* Called when some visits of an history entry are expired.
@ -940,10 +965,13 @@ interface nsINavHistoryObserver : nsISupports
* is expired, you will only get an onDeleteURI notification. If a
* page entry is removed, then you can be sure that we don't have
* anymore visits for it.
* @param aReason
* Indicates the reason for the removal. see REASON_* constants.
*/
void onDeleteVisits(in nsIURI aURI,
in PRTime aVisitTime,
in ACString aGUID);
in ACString aGUID,
in unsigned short aReason);
};

Просмотреть файл

@ -967,11 +967,11 @@ nsNavBookmarks::InsertBookmark(PRInt64 aFolder,
mozStorageTransaction transaction(mDBConn, PR_FALSE);
PRInt64 placeId;
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
// If the URI is unknown, this will create a new entry.
nsresult rv = history->GetUrlIdFor(aURI, &placeId, PR_TRUE);
PRInt64 placeId;
nsCAutoString placeGuid;
nsresult rv = history->GetOrCreateIdForPage(aURI, &placeId, placeGuid);
NS_ENSURE_SUCCESS(rv, rv);
// Get the correct index for insertion. This also ensures the parent exists.
@ -2424,7 +2424,8 @@ nsNavBookmarks::GetBookmarkedURIFor(nsIURI* aURI, nsIURI** _retval)
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
PRInt64 placeId;
nsresult rv = history->GetUrlIdFor(aURI, &placeId, PR_FALSE);
nsCAutoString placeGuid;
nsresult rv = history->GetIdForPage(aURI, &placeId, placeGuid);
NS_ENSURE_SUCCESS(rv, rv);
if (!placeId) {
// This URI is unknown, just return null.
@ -2466,11 +2467,11 @@ nsNavBookmarks::ChangeBookmarkURI(PRInt64 aBookmarkId, nsIURI* aNewURI)
mozStorageTransaction transaction(mDBConn, PR_FALSE);
// This will create a new page if one doesn't exist.
PRInt64 newPlaceId;
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
rv = history->GetUrlIdFor(aNewURI, &newPlaceId, PR_TRUE);
PRInt64 newPlaceId;
nsCAutoString newPlaceGuid;
rv = history->GetOrCreateIdForPage(aNewURI, &newPlaceId, newPlaceGuid);
NS_ENSURE_SUCCESS(rv, rv);
if (!newPlaceId)
return NS_ERROR_INVALID_ARG;
@ -3064,20 +3065,25 @@ nsNavBookmarks::OnVisit(nsIURI* aURI, PRInt64 aVisitId, PRTime aTime,
NS_IMETHODIMP
nsNavBookmarks::OnBeforeDeleteURI(nsIURI* aURI, const nsACString& aGUID)
nsNavBookmarks::OnBeforeDeleteURI(nsIURI* aURI,
const nsACString& aGUID,
PRUint16 aReason)
{
return NS_OK;
}
NS_IMETHODIMP
nsNavBookmarks::OnDeleteURI(nsIURI* aURI, const nsACString& aGUID)
nsNavBookmarks::OnDeleteURI(nsIURI* aURI,
const nsACString& aGUID,
PRUint16 aReason)
{
#ifdef DEBUG
nsNavHistory* history = nsNavHistory::GetHistoryService();
PRInt64 placeId;
nsCAutoString placeGuid;
NS_ABORT_IF_FALSE(
history && NS_SUCCEEDED(history->GetUrlIdFor(aURI, &placeId, PR_FALSE)) && !placeId,
history && NS_SUCCEEDED(history->GetIdForPage(aURI, &placeId, placeGuid)) && !placeId,
"OnDeleteURI was notified for a page that still exists?"
);
#endif
@ -3094,7 +3100,9 @@ nsNavBookmarks::OnClearHistory()
NS_IMETHODIMP
nsNavBookmarks::OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle)
nsNavBookmarks::OnTitleChanged(nsIURI* aURI,
const nsAString& aPageTitle,
const nsACString& aGUID)
{
// NOOP. We don't consume page titles from moz_places anymore.
// Title-change notifications are sent from SetItemTitle.
@ -3103,17 +3111,19 @@ nsNavBookmarks::OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle)
NS_IMETHODIMP
nsNavBookmarks::OnPageChanged(nsIURI* aURI, PRUint32 aWhat,
const nsAString& aValue)
nsNavBookmarks::OnPageChanged(nsIURI* aURI,
PRUint32 aChangedAttribute,
const nsAString& aNewValue,
const nsACString& aGUID)
{
nsresult rv;
if (aWhat == nsINavHistoryObserver::ATTRIBUTE_FAVICON) {
if (aChangedAttribute == nsINavHistoryObserver::ATTRIBUTE_FAVICON) {
ItemChangeData changeData;
rv = aURI->GetSpec(changeData.bookmark.url);
NS_ENSURE_SUCCESS(rv, rv);
changeData.property = NS_LITERAL_CSTRING("favicon");
changeData.isAnnotation = PR_FALSE;
changeData.newValue = NS_ConvertUTF16toUTF8(aValue);
changeData.newValue = NS_ConvertUTF16toUTF8(aNewValue);
changeData.bookmark.lastModified = 0;
changeData.bookmark.type = TYPE_BOOKMARK;
@ -3150,7 +3160,8 @@ nsNavBookmarks::OnPageChanged(nsIURI* aURI, PRUint32 aWhat,
NS_IMETHODIMP
nsNavBookmarks::OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime,
const nsACString& aGUID)
const nsACString& aGUID,
PRUint16 aReason)
{
// Notify "cleartime" only if all visits to the page have been removed.
if (!aVisitTime) {

Просмотреть файл

@ -1691,48 +1691,50 @@ nsNavHistory::MigrateV11Up(mozIStorageConnection *aDBConn)
return NS_OK;
}
// nsNavHistory::GetUrlIdFor
//
// Called by the bookmarks and annotation services, this function returns the
// ID of the row for the given URL, optionally creating one if it doesn't
// exist. A newly created entry will have no visits.
//
// If aAutoCreate is false and the item doesn't exist, the entry ID will be
// zero.
//
// This DOES NOT check for bad URLs other than that they're nonempty.
nsresult
nsNavHistory::GetUrlIdFor(nsIURI* aURI, PRInt64* aEntryID,
PRBool aAutoCreate)
nsNavHistory::GetIdForPage(nsIURI* aURI,
PRInt64* _pageId,
nsCString& _GUID)
{
*aEntryID = 0;
{
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBGetURLPageInfo);
nsresult rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), aURI);
NS_ENSURE_SUCCESS(rv, rv);
*_pageId = 0;
PRBool hasEntry = PR_FALSE;
rv = stmt->ExecuteStep(&hasEntry);
NS_ENSURE_SUCCESS(rv, rv);
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBGetURLPageInfo);
nsresult rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), aURI);
NS_ENSURE_SUCCESS(rv, rv);
if (hasEntry)
return stmt->GetInt64(kGetInfoIndex_PageID, aEntryID);
PRBool hasEntry = PR_FALSE;
rv = stmt->ExecuteStep(&hasEntry);
NS_ENSURE_SUCCESS(rv, rv);
if (hasEntry) {
rv = stmt->GetInt64(kGetInfoIndex_PageID, _pageId);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->GetUTF8String(5, _GUID);
NS_ENSURE_SUCCESS(rv, rv);
}
if (aAutoCreate) {
// create a new hidden, untyped, unvisited entry
nsAutoString voidString;
voidString.SetIsVoid(PR_TRUE);
nsCAutoString guid;
return InternalAddNewPage(aURI, voidString, PR_TRUE, PR_FALSE, 0, PR_TRUE, aEntryID, guid);
}
// Doesn't exist: don't do anything, entry ID was already set to 0 above
return NS_OK;
}
nsresult
nsNavHistory::GetOrCreateIdForPage(nsIURI* aURI,
PRInt64* _pageId,
nsCString& _GUID)
{
nsresult rv = GetIdForPage(aURI, _pageId, _GUID);
NS_ENSURE_SUCCESS(rv, rv);
if (*_pageId == 0) {
// Create a new hidden, untyped and unvisited entry.
nsAutoString voidString;
voidString.SetIsVoid(PR_TRUE);
rv = InternalAddNewPage(aURI, voidString, PR_TRUE, PR_FALSE, 0, PR_TRUE,
_pageId, _GUID);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
// nsNavHistory::InternalAddNewPage
//
@ -2043,10 +2045,13 @@ nsNavHistory::NotifyOnVisit(nsIURI* aURI,
}
void
nsNavHistory::NotifyTitleChange(nsIURI* aURI, const nsString& aTitle)
nsNavHistory::NotifyTitleChange(nsIURI* aURI,
const nsString& aTitle,
const nsACString& aGUID)
{
MOZ_ASSERT(!aGUID.IsEmpty());
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
nsINavHistoryObserver, OnTitleChanged(aURI, aTitle));
nsINavHistoryObserver, OnTitleChanged(aURI, aTitle, aGUID));
}
PRInt32
@ -4216,13 +4221,15 @@ nsNavHistory::CleanupPlacesOnVisitsDelete(const nsCString& aPlaceIdsQueryString)
GUIDs.AppendElement(guid);
// Notify we are about to remove this uri.
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
nsINavHistoryObserver, OnBeforeDeleteURI(uri, guid));
nsINavHistoryObserver,
OnBeforeDeleteURI(uri, guid, nsINavHistoryObserver::REASON_DELETED));
}
else {
// Notify that we will delete all visits for this page, but not the page
// itself, since it's bookmarked or a place: query.
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
nsINavHistoryObserver, OnDeleteVisits(uri, 0, guid));
nsINavHistoryObserver,
OnDeleteVisits(uri, 0, guid, nsINavHistoryObserver::REASON_DELETED));
}
}
@ -4245,7 +4252,8 @@ nsNavHistory::CleanupPlacesOnVisitsDelete(const nsCString& aPlaceIdsQueryString)
// Finally notify about the removed URIs.
for (PRInt32 i = 0; i < URIs.Count(); ++i) {
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
nsINavHistoryObserver, OnDeleteURI(URIs[i], GUIDs[i]));
nsINavHistoryObserver,
OnDeleteURI(URIs[i], GUIDs[i], nsINavHistoryObserver::REASON_DELETED));
}
return NS_OK;
@ -4271,7 +4279,8 @@ nsNavHistory::RemovePages(nsIURI **aURIs, PRUint32 aLength, PRBool aDoBatchNotif
nsCString deletePlaceIdsQueryString;
for (PRUint32 i = 0; i < aLength; i++) {
PRInt64 placeId;
rv = GetUrlIdFor(aURIs[i], &placeId, PR_FALSE);
nsCAutoString guid;
rv = GetIdForPage(aURIs[i], &placeId, guid);
NS_ENSURE_SUCCESS(rv, rv);
if (placeId != 0) {
if (!deletePlaceIdsQueryString.IsEmpty())
@ -5368,7 +5377,8 @@ nsNavHistory::AsyncExecuteLegacyQueries(nsINavHistoryQuery** aQueries,
NS_IMETHODIMP
nsNavHistory::NotifyOnPageExpired(nsIURI *aURI, PRTime aVisitTime,
PRBool aWholeEntry, const nsACString& aGUID)
PRBool aWholeEntry, const nsACString& aGUID,
PRUint16 aReason)
{
// Invalidate the cached value for whether there's history or not.
mHasHistoryEntries = -1;
@ -5377,12 +5387,13 @@ nsNavHistory::NotifyOnPageExpired(nsIURI *aURI, PRTime aVisitTime,
if (aWholeEntry) {
// Notify our observers that the page has been removed.
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
nsINavHistoryObserver, OnDeleteURI(aURI, aGUID));
nsINavHistoryObserver, OnDeleteURI(aURI, aGUID, aReason));
}
else {
// Notify our observers that some visits for the page have been removed.
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
nsINavHistoryObserver, OnDeleteVisits(aURI, aVisitTime, aGUID));
nsINavHistoryObserver,
OnDeleteVisits(aURI, aVisitTime, aGUID, aReason));
}
return NS_OK;
@ -6665,11 +6676,15 @@ nsNavHistory::URIToResultNode(nsIURI* aURI,
}
void
nsNavHistory::SendPageChangedNotification(nsIURI* aURI, PRUint32 aWhat,
const nsAString& aValue)
nsNavHistory::SendPageChangedNotification(nsIURI* aURI,
PRUint32 aChangedAttribute,
const nsAString& aNewValue,
const nsACString& aGUID)
{
MOZ_ASSERT(!aGUID.IsEmpty());
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
nsINavHistoryObserver, OnPageChanged(aURI, aWhat, aValue));
nsINavHistoryObserver,
OnPageChanged(aURI, aChangedAttribute, aNewValue, aGUID));
}
// nsNavHistory::TitleForDomain
@ -6781,9 +6796,9 @@ nsNavHistory::SetPageTitleInternal(nsIURI* aURI, const nsAString& aTitle)
{
nsresult rv;
// first, make sure the page exists, and fetch the old title (we need the one
// that isn't changing to send notifications)
// Make sure the page exists by fetching its GUID and the old title.
nsAutoString title;
nsCAutoString guid;
{
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBGetURLPageInfo);
rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), aURI);
@ -6802,6 +6817,8 @@ nsNavHistory::SetPageTitleInternal(nsIURI* aURI, const nsAString& aTitle)
rv = stmt->GetString(kGetInfoIndex_Title, title);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->GetUTF8String(5, guid);
NS_ENSURE_SUCCESS(rv, rv);
}
// It is actually common to set the title to be the same thing it used to
@ -6825,8 +6842,9 @@ nsNavHistory::SetPageTitleInternal(nsIURI* aURI, const nsAString& aTitle)
rv = stmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(!guid.IsEmpty());
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
nsINavHistoryObserver, OnTitleChanged(aURI, aTitle));
nsINavHistoryObserver, OnTitleChanged(aURI, aTitle, guid));
return NS_OK;
}

Просмотреть файл

@ -236,11 +236,35 @@ public:
}
/**
* Returns the database ID for the given URI, or 0 if not found and autoCreate
* is false.
* Fetches the database id and the GUID associated to the given URI.
*
* @param aURI
* The page to look for.
* @param _pageId
* Will be set to the database id associated with the page.
* If the page doesn't exist, this will be zero.
* @param _GUID
* Will be set to the unique id associated with the page.
* If the page doesn't exist, this will be empty.
* @note This DOES NOT check for bad URLs other than that they're nonempty.
*/
nsresult GetUrlIdFor(nsIURI* aURI, PRInt64* aEntryID,
PRBool aAutoCreate);
nsresult GetIdForPage(nsIURI* aURI,
PRInt64* _pageId, nsCString& _GUID);
/**
* Fetches the database id and the GUID associated to the given URI, creating
* a new database entry if one doesn't exist yet.
*
* @param aURI
* The page to look for or create.
* @param _pageId
* Will be set to the database id associated with the page.
* @param _GUID
* Will be set to the unique id associated with the page.
* @note This DOES NOT check for bad URLs other than that they're nonempty.
*/
nsresult GetOrCreateIdForPage(nsIURI* aURI,
PRInt64* _pageId, nsCString& _GUID);
nsresult UpdateFrecency(PRInt64 aPlaceId);
@ -336,8 +360,9 @@ public:
// used by other places components to send history notifications (for example,
// when the favicon has changed)
void SendPageChangedNotification(nsIURI* aURI, PRUint32 aWhat,
const nsAString& aValue);
void SendPageChangedNotification(nsIURI* aURI, PRUint32 aChangedAttribute,
const nsAString& aValue,
const nsACString& aGUID);
/**
* Returns current number of days stored in history.
@ -602,7 +627,8 @@ public:
* Fires onTitleChanged event to nsINavHistoryService observers
*/
void NotifyTitleChange(nsIURI* aURI,
const nsString& title);
const nsString& title,
const nsACString& aGUID);
bool isBatching() {
return mBatchLevel > 0;

Просмотреть файл

@ -2995,7 +2995,8 @@ nsNavHistoryQueryResultNode::OnVisit(nsIURI* aURI, PRInt64 aVisitId,
*/
NS_IMETHODIMP
nsNavHistoryQueryResultNode::OnTitleChanged(nsIURI* aURI,
const nsAString& aPageTitle)
const nsAString& aPageTitle,
const nsACString& aGUID)
{
if (!mExpanded) {
// When we are not expanded, we don't update, just invalidate and unhook.
@ -3062,8 +3063,9 @@ nsNavHistoryQueryResultNode::OnTitleChanged(nsIURI* aURI,
NS_IMETHODIMP
nsNavHistoryQueryResultNode::OnBeforeDeleteURI(nsIURI *aURI,
const nsACString& aGUID)
nsNavHistoryQueryResultNode::OnBeforeDeleteURI(nsIURI* aURI,
const nsACString& aGUID,
PRUint16 aReason)
{
return NS_OK;
}
@ -3073,8 +3075,9 @@ nsNavHistoryQueryResultNode::OnBeforeDeleteURI(nsIURI *aURI,
* the given URI.
*/
NS_IMETHODIMP
nsNavHistoryQueryResultNode::OnDeleteURI(nsIURI *aURI,
const nsACString& aGUID)
nsNavHistoryQueryResultNode::OnDeleteURI(nsIURI* aURI,
const nsACString& aGUID,
PRUint16 aReason)
{
if (IsContainersQuery()) {
// Incremental updates of query returning queries are pretty much
@ -3141,22 +3144,23 @@ static nsresult setFaviconCallback(
NS_IMETHODIMP
nsNavHistoryQueryResultNode::OnPageChanged(nsIURI *aURI, PRUint32 aWhat,
const nsAString &aValue)
nsNavHistoryQueryResultNode::OnPageChanged(nsIURI* aURI,
PRUint32 aChangedAttribute,
const nsAString& aNewValue,
const nsACString& aGUID)
{
nsCAutoString spec;
nsresult rv = aURI->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
switch (aWhat) {
switch (aChangedAttribute) {
case nsINavHistoryObserver::ATTRIBUTE_FAVICON: {
NS_ConvertUTF16toUTF8 newFavicon(aValue);
PRBool onlyOneEntry = (mOptions->ResultType() ==
nsINavHistoryQueryOptions::RESULTS_AS_URI ||
mOptions->ResultType() ==
nsINavHistoryQueryOptions::RESULTS_AS_TAG_CONTENTS);
rv = UpdateURIs(PR_TRUE, onlyOneEntry, PR_FALSE, spec, setFaviconCallback,
&newFavicon);
&NS_ConvertUTF16toUTF8(aNewValue));
NS_ENSURE_SUCCESS(rv, rv);
break;
}
@ -3168,8 +3172,10 @@ nsNavHistoryQueryResultNode::OnPageChanged(nsIURI *aURI, PRUint32 aWhat,
NS_IMETHODIMP
nsNavHistoryQueryResultNode::OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime,
const nsACString& aGUID)
nsNavHistoryQueryResultNode::OnDeleteVisits(nsIURI* aURI,
PRTime aVisitTime,
const nsACString& aGUID,
PRUint16 aReason)
{
NS_PRECONDITION(mOptions->QueryType() == nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY,
"Bookmarks queries should not get a OnDeleteVisits notification");
@ -3177,7 +3183,7 @@ nsNavHistoryQueryResultNode::OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime,
// All visits for this uri have been removed, but the uri won't be removed
// from the databse, most likely because it's a bookmark. For a history
// query this is equivalent to a onDeleteURI notification.
nsresult rv = OnDeleteURI(aURI, aGUID);
nsresult rv = OnDeleteURI(aURI, aGUID, aReason);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -5128,24 +5134,30 @@ nsNavHistoryResult::OnVisit(nsIURI* aURI, PRInt64 aVisitId, PRTime aTime,
NS_IMETHODIMP
nsNavHistoryResult::OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle)
nsNavHistoryResult::OnTitleChanged(nsIURI* aURI,
const nsAString& aPageTitle,
const nsACString& aGUID)
{
ENUMERATE_HISTORY_OBSERVERS(OnTitleChanged(aURI, aPageTitle));
ENUMERATE_HISTORY_OBSERVERS(OnTitleChanged(aURI, aPageTitle, aGUID));
return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryResult::OnBeforeDeleteURI(nsIURI *aURI, const nsACString& aGUID)
nsNavHistoryResult::OnBeforeDeleteURI(nsIURI *aURI,
const nsACString& aGUID,
PRUint16 aReason)
{
return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryResult::OnDeleteURI(nsIURI *aURI, const nsACString& aGUID)
nsNavHistoryResult::OnDeleteURI(nsIURI *aURI,
const nsACString& aGUID,
PRUint16 aReason)
{
ENUMERATE_HISTORY_OBSERVERS(OnDeleteURI(aURI, aGUID));
ENUMERATE_HISTORY_OBSERVERS(OnDeleteURI(aURI, aGUID, aReason));
return NS_OK;
}
@ -5159,10 +5171,12 @@ nsNavHistoryResult::OnClearHistory()
NS_IMETHODIMP
nsNavHistoryResult::OnPageChanged(nsIURI *aURI,
PRUint32 aWhat, const nsAString &aValue)
nsNavHistoryResult::OnPageChanged(nsIURI* aURI,
PRUint32 aChangedAttribute,
const nsAString& aValue,
const nsACString& aGUID)
{
ENUMERATE_HISTORY_OBSERVERS(OnPageChanged(aURI, aWhat, aValue));
ENUMERATE_HISTORY_OBSERVERS(OnPageChanged(aURI, aChangedAttribute, aValue, aGUID));
return NS_OK;
}
@ -5171,9 +5185,11 @@ nsNavHistoryResult::OnPageChanged(nsIURI *aURI,
* Don't do anything when visits expire.
*/
NS_IMETHODIMP
nsNavHistoryResult::OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime,
const nsACString& aGUID)
nsNavHistoryResult::OnDeleteVisits(nsIURI* aURI,
PRTime aVisitTime,
const nsACString& aGUID,
PRUint16 aReason)
{
ENUMERATE_HISTORY_OBSERVERS(OnDeleteVisits(aURI, aVisitTime, aGUID));
ENUMERATE_HISTORY_OBSERVERS(OnDeleteVisits(aURI, aVisitTime, aGUID, aReason));
return NS_OK;
}

Просмотреть файл

@ -100,14 +100,18 @@ private:
PRInt64 aSessionId, PRInt64 aReferringId, \
PRUint32 aTransitionType, const nsACString& aGUID, \
PRUint32* aAdded); \
NS_IMETHOD OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle); \
NS_IMETHOD OnBeforeDeleteURI(nsIURI *aURI, const nsACString& aGUID); \
NS_IMETHOD OnDeleteURI(nsIURI *aURI, const nsACString& aGUID); \
NS_IMETHOD OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle, \
const nsACString& aGUID); \
NS_IMETHOD OnBeforeDeleteURI(nsIURI *aURI, const nsACString& aGUID, \
PRUint16 aReason); \
NS_IMETHOD OnDeleteURI(nsIURI *aURI, const nsACString& aGUID, \
PRUint16 aReason); \
NS_IMETHOD OnClearHistory(); \
NS_IMETHOD OnPageChanged(nsIURI *aURI, PRUint32 aWhat, \
const nsAString &aValue); \
NS_IMETHOD OnPageChanged(nsIURI *aURI, PRUint32 aChangedAttribute, \
const nsAString &aNewValue, \
const nsACString &aGUID); \
NS_IMETHOD OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime, \
const nsACString& aGUID);
const nsACString& aGUID, PRUint16 aReason);
// nsNavHistoryResult
//

Просмотреть файл

@ -49,7 +49,7 @@ interface nsIURI;
*
* @note See also: nsINavHistoryObserver
*/
[scriptable, uuid(eb2ec8a9-c764-4abe-b076-b122d7aa8a3b)]
[scriptable, uuid(3b0953cd-f483-4908-8d91-282b6bda0453)]
interface nsPIPlacesHistoryListenersNotifier : nsISupports
{
/**
@ -64,9 +64,13 @@ interface nsPIPlacesHistoryListenersNotifier : nsISupports
* Indicates if this is the last visit for this URI.
* @param aGUID
* The unique ID associated with the page.
* @param aReason
* Indicates the reason for the removal.
* See nsINavHistoryObserver::REASON_* constants.
*/
void notifyOnPageExpired(in nsIURI aURI,
in PRTime aVisitTime,
in boolean aWholeEntry,
in ACString aGUID);
in ACString aGUID,
in unsigned short aReason);
};

Просмотреть файл

@ -658,7 +658,8 @@ nsPlacesExpiration.prototype = {
let visitDate = row.getResultByName("visit_date");
let wholeEntry = row.getResultByName("whole_entry");
// Dispatch expiration notifications to history.
this._hsn.notifyOnPageExpired(uri, visitDate, wholeEntry, guid);
this._hsn.notifyOnPageExpired(uri, visitDate, wholeEntry, guid,
Ci.nsINavHistoryObserver.REASON_EXPIRED);
}
},

Просмотреть файл

@ -55,9 +55,9 @@ function test() {
// Create and add history observer.
var historyObserver = {
visitCount: Array(),
onBeginUpdateBatch: function() {},
onEndUpdateBatch: function() {},
onVisit: function(aURI, aVisitID, aTime, aSessionID, aReferringID,
onBeginUpdateBatch: function () {},
onEndUpdateBatch: function () {},
onVisit: function (aURI, aVisitID, aTime, aSessionID, aReferringID,
aTransitionType) {
info("Received onVisit: " + aURI.spec);
if (aURI.spec in this.visitCount)
@ -65,12 +65,12 @@ function test() {
else
this.visitCount[aURI.spec] = 1;
},
onTitleChanged: function(aURI, aPageTitle) {},
onBeforeDeleteURI: function(aURI) {},
onDeleteURI: function(aURI) {},
onClearHistory: function() {},
onPageChanged: function(aURI, aWhat, aValue) {},
onDeleteVisits: function() {},
onTitleChanged: function () {},
onBeforeDeleteURI: function () {},
onDeleteURI: function () {},
onClearHistory: function () {},
onPageChanged: function () {},
onDeleteVisits: function () {},
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
};
hs.addObserver(historyObserver, false);

Просмотреть файл

@ -79,8 +79,8 @@ function test()
onVisit: function(aURI, aVisitID, aTime, aSessionID, aReferringID,
aTransitionType) {
},
onTitleChanged: function(aURI, aPageTitle) {
this.data.push({ uri: aURI, title: aPageTitle });
onTitleChanged: function(aURI, aPageTitle, aGUID) {
this.data.push({ uri: aURI, title: aPageTitle, guid: aGUID });
// We only expect one title change.
//
@ -107,6 +107,7 @@ function test()
function confirmResults(data) {
is(data[0].uri.spec, "http://example.com/tests/toolkit/components/places/tests/browser/title2.html");
is(data[0].title, "Some title");
is(data[0].guid, getColumn("moz_places", "guid", "url", data[0].uri.spec));
data.forEach(function(item) {
var title = getColumn("moz_places", "title", "url", data[0].uri.spec);

Просмотреть файл

@ -123,10 +123,12 @@ function run_next_test() {
onVisit: function() {},
onTitleChanged: function() {},
onBeforeDeleteURI: function() {},
onDeleteURI: function(aURI) {
onDeleteURI: function(aURI, aGUID, aReason) {
gCurrentTest.receivedNotifications++;
// Check this uri was not bookmarked.
do_check_eq(gCurrentTest.bookmarks.indexOf(aURI.spec), -1);
do_check_valid_places_guid(aGUID);
do_check_eq(aReason, Ci.nsINavHistoryObserver.REASON_EXPIRED);
},
onPageChanged: function() {},
onDeleteVisits: function(aURI, aTime) { },

Просмотреть файл

@ -142,13 +142,17 @@ function run_next_test() {
onVisit: function() {},
onTitleChanged: function() {},
onBeforeDeleteURI: function() {},
onDeleteURI: function(aURI) {
onDeleteURI: function(aURI, aGUID, aReason) {
// Check this uri was not bookmarked.
do_check_eq(gCurrentTest.bookmarks.indexOf(aURI.spec), -1);
do_check_valid_places_guid(aGUID);
do_check_eq(aReason, Ci.nsINavHistoryObserver.REASON_EXPIRED);
},
onPageChanged: function() {},
onDeleteVisits: function(aURI, aTime) {
onDeleteVisits: function(aURI, aTime, aGUID, aReason) {
gCurrentTest.receivedNotifications++;
do_check_guid_for_uri(aURI, aGUID);
do_check_eq(aReason, Ci.nsINavHistoryObserver.REASON_EXPIRED);
},
};
hs.addObserver(historyObserver, false);

Просмотреть файл

@ -123,9 +123,7 @@
catch (exc) {}
try {
var str = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
str.data = "foo";
var str = PlacesUtils.toISupportsString("foo");
query = PlacesUtils.history.getNewQuery();
query.tags = str;
do_throw("Passing nsISupportsString to SetTags should fail");

Просмотреть файл

@ -48,19 +48,19 @@ function DummyObserver() {
DummyObserver.prototype = {
// history observer
onBeginUpdateBatch: function() {},
onEndUpdateBatch: function() {},
onVisit: function(aURI, aVisitID, aTime, aSessionID, aReferringID, aTransitionType) {
onBeginUpdateBatch: function () {},
onEndUpdateBatch: function () {},
onVisit: function (aURI, aVisitID, aTime, aSessionID, aReferringID, aTransitionType) {
let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
os.notifyObservers(null, "dummy-observer-visited", null);
},
onTitleChanged: function(aURI, aPageTitle) {},
onBeforeDeleteURI: function(aURI) {},
onDeleteURI: function(aURI) {},
onClearHistory: function() {},
onPageChanged: function(aURI, aWhat, aValue) {},
onDeleteVisits: function(aURI, aVisitTime) {},
onTitleChanged: function () {},
onBeforeDeleteURI: function () {},
onDeleteURI: function () {},
onClearHistory: function () {},
onPageChanged: function () {},
onDeleteVisits: function () {},
// bookmark observer
//onBeginUpdateBatch: function() {},

Просмотреть файл

@ -61,19 +61,15 @@ var observer = {
dump("onVisit: " + aURI.spec + "\n");
confirm_results();
},
onTitleChanged: function(aURI, aPageTitle) {},
onBeforeDeleteURI: function(aURI) {},
onDeleteURI: function(aURI) {},
onClearHistory: function() {},
onPageChanged: function(aURI, aWhat, aValue) {},
onDeleteVisits: function() {},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsINavHistoryObserver) ||
iid.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
}
onTitleChanged: function () {},
onBeforeDeleteURI: function () {},
onDeleteURI: function () {},
onClearHistory: function () {},
onPageChanged: function () {},
onDeleteVisits: function () {},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsINavHistoryObserver
])
};
histsvc.addObserver(observer, false);

Просмотреть файл

@ -86,13 +86,15 @@ function TitleChangedObserver(aURI,
TitleChangedObserver.prototype = {
__proto__: NavHistoryObserver.prototype,
onTitleChanged: function(aURI,
aTitle)
aTitle,
aGUID)
{
do_log_info("onTitleChanged(" + aURI.spec + ", " + aTitle + ")");
do_log_info("onTitleChanged(" + aURI.spec + ", " + aTitle + ", " + aGUID + ")");
if (!this.uri.equals(aURI)) {
return;
}
do_check_eq(aTitle, this.expectedTitle);
do_check_guid_for_uri(aURI, aGUID);
this.callback();
},
};

Просмотреть файл

@ -161,10 +161,12 @@ var historyObserver = {
onClearHistory: function() {},
onDeleteVisits: function() {},
onPageChanged: function historyObserver_onPageChanged(pageURI, what, value) {
onPageChanged: function historyObserver_onPageChanged(pageURI, what, value, guid) {
if (what != Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON)
return;
do_check_guid_for_uri(pageURI, guid);
if (pageURI.equals(tests[currentTestIndex].pageURI)) {
tests[currentTestIndex].check();
currentTestIndex++;

Просмотреть файл

@ -143,7 +143,7 @@ let historyObserver = {
onClearHistory: function() {},
onDeleteVisits: function() {},
onPageChanged: function historyObserver_onPageChanged(pageURI, what, value) {
onPageChanged: function historyObserver_onPageChanged(pageURI, what, value, guid) {
if (what != Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON)
return;
@ -151,6 +151,8 @@ let historyObserver = {
//dump_table("moz_places");
//dump_table("moz_favicons");
do_check_guid_for_uri(pageURI, guid);
// Ensure we have been called by the last test.
do_check_true(pageURI.equals(NetUtil.newURI("http://testfinal.bar/")));

Просмотреть файл

@ -67,9 +67,10 @@ add_test(function test_onVisit() {
});
add_test(function test_onBeforeDeleteURI() {
onNotify(function onBeforeDeleteURI(aURI, aGUID) {
onNotify(function onBeforeDeleteURI(aURI, aGUID, aReason) {
do_check_true(aURI.equals(testuri));
do_check_guid_for_uri(aURI, aGUID);
do_check_eq(aReason, Ci.nsINavHistoryObserver.REASON_DELETED);
run_next_test();
});
@ -78,10 +79,11 @@ add_test(function test_onBeforeDeleteURI() {
});
add_test(function test_onDeleteURI() {
onNotify(function onDeleteURI(aURI, aGUID) {
onNotify(function onDeleteURI(aURI, aGUID, aReason) {
do_check_true(aURI.equals(testuri));
// Can't use do_check_guid_for_uri() here because the visit is already gone.
do_check_eq(aGUID, testguid);
do_check_eq(aReason, Ci.nsINavHistoryObserver.REASON_DELETED);
run_next_test();
});
@ -89,3 +91,59 @@ add_test(function test_onDeleteURI() {
let testguid = do_get_guid_for_uri(testuri);
PlacesUtils.bhistory.removePage(testuri);
});
add_test(function test_onDeleteVisits() {
onNotify(function onDeleteVisits(aURI, aVisitTime, aGUID, aReason) {
do_check_true(aURI.equals(testuri));
// Can't use do_check_guid_for_uri() here because the visit is already gone.
do_check_eq(aGUID, testguid);
do_check_eq(aReason, Ci.nsINavHistoryObserver.REASON_DELETED);
do_check_eq(aVisitTime, 0); // All visits have been removed.
run_next_test();
});
let msecs24hrsAgo = Date.now() - (86400 * 1000);
let [testuri] = add_visit(undefined, msecs24hrsAgo * 1000);
// Add a bookmark so the page is not removed.
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
testuri,
PlacesUtils.bookmarks.DEFAULT_INDEX,
"test");
let testguid = do_get_guid_for_uri(testuri);
PlacesUtils.bhistory.removePage(testuri);
});
add_test(function test_onTitleChanged() {
onNotify(function onTitleChanged(aURI, aTitle, aGUID) {
do_check_true(aURI.equals(testuri));
do_check_eq(aTitle, title);
do_check_guid_for_uri(aURI, aGUID);
run_next_test();
});
let [testuri] = add_visit();
let title = "test-title";
PlacesUtils.history.setPageTitle(testuri, title);
});
add_test(function test_onPageChanged() {
onNotify(function onPageChanged(aURI, aChangedAttribute, aNewValue, aGUID) {
do_check_eq(aChangedAttribute, Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON);
do_check_true(aURI.equals(testuri));
do_check_eq(aNewValue, iconurl);
do_check_guid_for_uri(aURI, aGUID);
run_next_test();
});
let [testuri] = add_visit();
let iconurl = "file:///favicon-normal32.png";
let data = readFileData(do_get_file("favicon-normal32.png"));
PlacesUtils.favicons.setFaviconData(NetUtil.newURI(iconurl),
data, data.length, "image/png",
Number.MAX_VALUE);
PlacesUtils.favicons.setFaviconUrlForPage(testuri, NetUtil.newURI(iconurl));
});

Просмотреть файл

@ -100,25 +100,15 @@ var observer = {
if (this._visitCount == gVisits.length)
do_test_finished();
},
onTitleChanged: function(aURI, aPageTitle) {
},
onBeforeDeleteURI: function(aURI) {
},
onDeleteURI: function(aURI) {
},
onClearHistory: function() {
},
onPageChanged: function(aURI, aWhat, aValue) {
},
onDeleteVisits: function() {
},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsINavHistoryObserver) ||
iid.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
}
onTitleChanged: function () {},
onBeforeDeleteURI: function () {},
onDeleteURI: function () {},
onClearHistory: function () {},
onPageChanged: function () {},
onDeleteVisits: function () {},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsINavHistoryObserver
])
};
histsvc.addObserver(observer, false);

Просмотреть файл

@ -57,43 +57,28 @@ function Observer()
Observer.prototype =
{
checked: false,
onBeginUpdateBatch: function() {
},
onEndUpdateBatch: function() {
},
onVisit: function(aURI, aVisitID, aTime, aSessionId, aReferringId,
aTransitionType, _added)
{
},
onTitleChanged: function(aURI, aPageTable)
{
},
onBeforeDeleteURI: function(aURI, aGUID)
onBeginUpdateBatch: function () {},
onEndUpdateBatch: function () {},
onVisit: function () {},
onTitleChanged: function () {},
onBeforeDeleteURI: function (aURI, aGUID)
{
this.removedURI = aURI;
this.removedGUID = aGUID;
do_check_guid_for_uri(aURI, aGUID);
},
onDeleteURI: function(aURI, aGUID)
onDeleteURI: function (aURI, aGUID)
{
do_check_false(this.checked);
do_check_true(this.removedURI.equals(aURI));
do_check_eq(this.removedGUID, aGUID);
this.checked = true;
},
onPageChanged: function(aURI, aWhat, aValue)
{
},
onDeleteVisits: function()
{
},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsINavHistoryObserver) ||
iid.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
}
onPageChanged: function () {},
onDeleteVisits: function () {},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsINavHistoryObserver
])
};
////////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -77,6 +77,7 @@
#include "prprf.h"
#include "prnetdb.h"
#include "zlib.h"
#include "mozilla/Preferences.h"
// Needed to interpert mozIStorageConnection::GetLastError
#include <sqlite3.h>
@ -1798,7 +1799,6 @@ nsUrlClassifierDBServiceWorker::GetTables(nsIUrlClassifierCallback* c)
nsresult rv = OpenDb();
if (NS_FAILED(rv)) {
NS_ERROR("Unable to open database");
return NS_ERROR_FAILURE;
}
@ -2913,7 +2913,6 @@ nsUrlClassifierDBServiceWorker::BeginUpdate(nsIUrlClassifierUpdateObserver *obse
nsresult rv = OpenDb();
if (NS_FAILED(rv)) {
NS_ERROR("Unable to open database");
return NS_ERROR_FAILURE;
}
@ -3061,7 +3060,6 @@ nsUrlClassifierDBServiceWorker::UpdateStream(const nsACString& chunk)
LOG(("Update from Stream."));
nsresult rv = OpenDb();
if (NS_FAILED(rv)) {
NS_ERROR("Unable to open database");
return NS_ERROR_FAILURE;
}
@ -3367,6 +3365,15 @@ nsUrlClassifierDBServiceWorker::OpenDb()
if (mConnection)
return NS_OK;
// If we're turned off, refuse to open the DB
PRBool openDB =
Preferences::GetBool(CHECK_MALWARE_PREF, CHECK_MALWARE_DEFAULT) ||
Preferences::GetBool(CHECK_PHISHING_PREF, CHECK_PHISHING_DEFAULT);
if (!openDB) {
NS_WARNING("Not opening url-classifier DB");
return NS_ERROR_NOT_AVAILABLE;
}
LOG(("Opening db\n"));
nsresult rv;