Merge mozilla-central to Places.

This commit is contained in:
Shawn Wilsher
2010-10-27 12:28:31 -07:00
1920 changed files with 30896 additions and 15287 deletions

View File

@@ -259,7 +259,7 @@ FeedWriter.prototype = {
},
/**
* Calls doCommand for a the given XUL element within the context of the
* Calls doCommand for a given XUL element within the context of the
* content document.
*
* @param aElement

View File

@@ -1161,7 +1161,8 @@ var gEditItemOverlay = {
this._folderMenuList.selectedItem = folderItem;
},
onItemAdded: function EIO_onItemAdded(aItemId, aFolder, aIndex, aItemType) {
onItemAdded: function EIO_onItemAdded(aItemId, aFolder, aIndex, aItemType,
aURI) {
this._lastNewItem = aItemId;
},

View File

@@ -46,8 +46,6 @@
<?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
<!DOCTYPE page [
<!ENTITY % historyDTD SYSTEM "chrome://browser/locale/history/history.dtd">
%historyDTD;
<!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
%placesDTD;
]>

View File

@@ -391,7 +391,7 @@
<vbox id="defaultView" flex="1">
<vbox id="searchModifiers" hidden="true">
<toolbar id="organizerScopeBar" class="chromeclass-toolbar" align="center">
<label id="scopeBarTitle" value="&search.label;"/>
<label id="scopeBarTitle" value="&search.in.label;"/>
<toolbarbutton id="scopeBarAll" type="radio" group="scopeBar"
oncommand="PlacesQueryBuilder.onScopeSelected(this);"
label="&search.scopeBookmarks.label;"

View File

@@ -1381,7 +1381,7 @@ XPCOMUtils.defineLazyGetter(PlacesUIUtils, "ptm", function() {
},
/**
* Transaction for editing a the description of a bookmark or a folder.
* Transaction for editing the description of a bookmark or a folder.
*
* @param aItemId
* id of the item to edit.

View File

@@ -58,12 +58,11 @@ var dragDirections = { LEFT: 0, UP: 1, RIGHT: 2, DOWN: 3 };
* @param aDirection
* Direction for the dragging gesture, see dragDirections helper object.
*/
function synthesizeDragWithDirection(aElement, aExpectedDragData, aDirection) {
var trapped = false;
function synthesizeDragWithDirection(aElement, aExpectedDragData, aDirection, aCallback) {
// Dragstart listener function.
var trapDrag = function(event) {
trapped = true;
gBookmarksToolbar.addEventListener("dragstart", function(event)
{
info("A dragstart event has been trapped.");
var dataTransfer = event.dataTransfer;
is(dataTransfer.mozItemCount, aExpectedDragData.length,
"Number of dragged items should be the same.");
@@ -88,7 +87,23 @@ function synthesizeDragWithDirection(aElement, aExpectedDragData, aDirection) {
event.preventDefault();
event.stopPropagation();
}
gBookmarksToolbar.removeEventListener("dragstart", arguments.callee, false);
// This is likely to cause a click event, and, in case we are dragging a
// bookmark, an unwanted page visit. Prevent the click event.
aElement.addEventListener("click", prevent, false);
EventUtils.synthesizeMouse(aElement,
startingPoint.x + xIncrement * 9,
startingPoint.y + yIncrement * 9,
{ type: "mouseup" });
aElement.removeEventListener("click", prevent, false);
// Cleanup eventually opened menus.
if (aElement.localName == "menu" && aElement.open)
aElement.open = false;
aCallback()
}, false);
var prevent = function(aEvent) {aEvent.preventDefault();}
@@ -122,26 +137,10 @@ function synthesizeDragWithDirection(aElement, aExpectedDragData, aDirection) {
startingPoint.x + xIncrement * 1,
startingPoint.y + yIncrement * 1,
{ type: "mousemove" });
gBookmarksToolbar.addEventListener("dragstart", trapDrag, false);
EventUtils.synthesizeMouse(aElement,
startingPoint.x + xIncrement * 9,
startingPoint.y + yIncrement * 9,
{ type: "mousemove" });
ok(trapped, "A dragstart event has been trapped.");
gBookmarksToolbar.removeEventListener("dragstart", trapDrag, false);
// This is likely to cause a click event, and, in case we are dragging a
// bookmark, an unwanted page visit. Prevent the click event.
aElement.addEventListener("click", prevent, false);
EventUtils.synthesizeMouse(aElement,
startingPoint.x + xIncrement * 9,
startingPoint.y + yIncrement * 9,
{ type: "mouseup" });
aElement.removeEventListener("click", prevent, false);
// Cleanup eventually opened menus.
if (aElement.localName == "menu" && aElement.open)
aElement.open = false;
}
function getToolbarNodeForItemId(aItemId) {
@@ -190,17 +189,28 @@ var gTests = [
isnot(element._placesNode, null, "Toolbar node has an associated Places node.");
var expectedData = getExpectedDataForPlacesNode(element._placesNode);
ok(true, "Dragging left");
synthesizeDragWithDirection(element, expectedData, dragDirections.LEFT);
ok(true, "Dragging right");
synthesizeDragWithDirection(element, expectedData, dragDirections.RIGHT);
ok(true, "Dragging up");
synthesizeDragWithDirection(element, expectedData, dragDirections.UP);
ok(true, "Dragging down");
synthesizeDragWithDirection(element, new Array(), dragDirections.DOWN);
// Cleanup.
PlacesUtils.bookmarks.removeItem(folderId);
info("Dragging left");
synthesizeDragWithDirection(element, expectedData, dragDirections.LEFT,
function ()
{
info("Dragging right");
synthesizeDragWithDirection(element, expectedData, dragDirections.RIGHT,
function ()
{
info("Dragging up");
synthesizeDragWithDirection(element, expectedData, dragDirections.UP,
function ()
{
info("Dragging down");
synthesizeDragWithDirection(element, new Array(), dragDirections.DOWN,
function () {
// Cleanup.
PlacesUtils.bookmarks.removeItem(folderId);
nextTest();
});
});
});
});
}
},
@@ -221,17 +231,28 @@ var gTests = [
isnot(element._placesNode, null, "Toolbar node has an associated Places node.");
var expectedData = getExpectedDataForPlacesNode(element._placesNode);
ok(true, "Dragging left");
synthesizeDragWithDirection(element, expectedData, dragDirections.LEFT);
ok(true, "Dragging right");
synthesizeDragWithDirection(element, expectedData, dragDirections.RIGHT);
ok(true, "Dragging up");
synthesizeDragWithDirection(element, expectedData, dragDirections.UP);
ok(true, "Dragging down");
synthesizeDragWithDirection(element, expectedData, dragDirections.DOWN);
// Cleanup.
PlacesUtils.bookmarks.removeItem(itemId);
info("Dragging left");
synthesizeDragWithDirection(element, expectedData, dragDirections.LEFT,
function ()
{
info("Dragging right");
synthesizeDragWithDirection(element, expectedData, dragDirections.RIGHT,
function ()
{
info("Dragging up");
synthesizeDragWithDirection(element, expectedData, dragDirections.UP,
function ()
{
info("Dragging down");
synthesizeDragWithDirection(element, expectedData, dragDirections.DOWN,
function () {
// Cleanup.
PlacesUtils.bookmarks.removeItem(folderId);
nextTest();
});
});
});
});
}
},
];
@@ -242,7 +263,7 @@ function nextTest() {
info("Start of test: " + test.desc);
test.run();
setTimeout(nextTest, 0);
waitForFocus(nextTest);
}
else {
// Collapse the personal toolbar if needed.
@@ -256,11 +277,12 @@ let toolbar = document.getElementById("PersonalToolbar");
let wasCollapsed = toolbar.collapsed;
function test() {
waitForExplicitFinish();
// Uncollapse the personal toolbar if needed.
if (wasCollapsed)
setToolbarVisibility(toolbar, true);
waitForExplicitFinish();
nextTest();
waitForFocus(nextTest);
}

View File

@@ -38,6 +38,24 @@
// This test makes sure that the Forget This Site command is hidden for multiple
// selections.
/**
* Clears history invoking callback when done.
*/
function waitForClearHistory(aCallback) {
const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
let observer = {
observe: function(aSubject, aTopic, aData) {
Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
aCallback();
}
};
Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService);
hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
}
function test() {
// initialization
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
@@ -61,6 +79,7 @@ function test() {
ww.unregisterNotification(observer);
let organizer = aSubject.QueryInterface(Ci.nsIDOMWindow);
SimpleTest.waitForFocus(function() {
executeSoon(function() {
// Select History in the left pane.
organizer.PlacesOrganizer.selectLeftPaneQuery('History');
let PO = organizer.PlacesOrganizer;
@@ -78,7 +97,7 @@ function test() {
// Open the context menu
let contextmenu = doc.getElementById("placesContext");
contextmenu.addEventListener("popupshown", function() {
contextmenu.removeEventListener("popupshown", arguments.callee, false);
contextmenu.removeEventListener("popupshown", arguments.callee, true);
let forgetThisSite = doc.getElementById("placesContext_deleteHost");
let hideForgetThisSite = (selectionCount != 1);
is(forgetThisSite.hidden, hideForgetThisSite,
@@ -86,17 +105,27 @@ function test() {
"be hidden with " + selectionCount + " items selected");
// Close the context menu
contextmenu.hidePopup();
// Wait for the Organizer window to actually be closed
function closeObserver(aSubject, aTopic, aData) {
if (aTopic != "domwindowclosed")
return;
ww.unregisterNotification(closeObserver);
SimpleTest.waitForFocus(function() {
// Proceed
funcNext();
});
}
ww.registerNotification(closeObserver);
// Close Library window.
organizer.close();
// Proceed
funcNext();
}, false);
}, true);
// Get cell coordinates
var x = {}, y = {}, width = {}, height = {};
tree.treeBoxObject.getCoordsForCellItem(0, tree.columns[0], "text",
x, y, width, height);
// Initiate a context menu for the selected cell
EventUtils.synthesizeMouse(tree.body, x + 4, y + 4, {type: "contextmenu"}, organizer);
EventUtils.synthesizeMouse(tree.body, x.value + width.value / 2, y.value + height.value / 2, {type: "contextmenu"}, organizer);
});
}, organizer);
}
@@ -111,9 +140,7 @@ function test() {
testForgetThisSiteVisibility(1, function() {
testForgetThisSiteVisibility(2, function() {
// Cleanup
history.QueryInterface(Ci.nsIBrowserHistory)
.removeAllPages();
finish();
waitForClearHistory(finish);
});
});
}

View File

@@ -204,7 +204,7 @@ var bookmarksObserver = {
},
// nsINavBookmarkObserver
onItemAdded: function PSB_onItemAdded(aItemId, aFolderId, aIndex) {
onItemAdded: function PSB_onItemAdded(aItemId, aFolderId, aIndex, aURI) {
var node = null;
var index = null;
[node, index] = getNodeForTreeItem(aItemId, gLibrary.PlacesOrganizer._places);

View File

@@ -223,7 +223,7 @@ var bookmarksObserver = {
// nsINavBookmarkObserver
onItemAdded: function PSB_onItemAdded(aItemId, aFolderId, aIndex,
aItemType) {
aItemType, aURI) {
var views = getViewsForFolder(aFolderId);
ok(views.length > 0, "Found affected views (" + views.length + "): " + views);

View File

@@ -53,7 +53,7 @@ var observer = {
onEndUpdateBatch: function() {
this._endUpdateBatch = true;
},
onItemAdded: function(id, folder, index, itemType) {
onItemAdded: function(id, folder, index, itemType, uri) {
this._itemAddedId = id;
this._itemAddedParent = folder;
this._itemAddedIndex = index;

View File

@@ -762,6 +762,19 @@ var gCookiesWindow = {
this._view._filterSet.reverse();
}
// Adjust the Sort Indicator
var domainCol = document.getElementById("domainCol");
var nameCol = document.getElementById("nameCol");
var sortOrderString = ascending ? "ascending" : "descending";
if (aProperty == "rawHost") {
domainCol.setAttribute("sortDirection", sortOrderString);
nameCol.removeAttribute("sortDirection");
}
else {
nameCol.setAttribute("sortDirection", sortOrderString);
domainCol.removeAttribute("sortDirection");
}
this._view._invalidateCache(0);
this._view.selection.clearSelection();
this._view.selection.select(0);

View File

@@ -79,10 +79,10 @@
hidecolumnpicker="true" seltype="single">
<treecols>
<treecol id="domainCol" label="&cookiedomain.label;" flex="2" primary="true"
class="sortDirectionIndicator" persist="width" onclick="gCookiesWindow.sort('rawHost');" />
persist="width" onclick="gCookiesWindow.sort('rawHost');"/>
<splitter class="tree-splitter"/>
<treecol id="nameCol" label="&cookiename.label;" flex="1"
class="sortDirectionIndicator" persist="width"
persist="width"
onclick="gCookiesWindow.sort('name');"/>
</treecols>
<treechildren id="cookiesChildren"/>

View File

@@ -38,6 +38,24 @@
// This test makes sure that the Forget This Site command is hidden in private
// browsing mode.
/**
* Clears history invoking callback when done.
*/
function waitForClearHistory(aCallback) {
const TOPIC_EXPIRATION_FINISHED = "places-expiration-finished";
let observer = {
observe: function(aSubject, aTopic, aData) {
Services.obs.removeObserver(this, TOPIC_EXPIRATION_FINISHED);
aCallback();
}
};
Services.obs.addObserver(observer, TOPIC_EXPIRATION_FINISHED, false);
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService);
hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
}
function test() {
// initialization
let pb = Cc["@mozilla.org/privatebrowsing;1"].
@@ -60,6 +78,7 @@ function test() {
Services.ww.unregisterNotification(observer);
let organizer = aSubject.QueryInterface(Ci.nsIDOMWindow);
SimpleTest.waitForFocus(function() {
executeSoon(function() {
// Select History in the left pane.
let PO = organizer.PlacesOrganizer;
PO.selectLeftPaneQuery('History');
@@ -76,7 +95,7 @@ function test() {
// Open the context menu
let contextmenu = doc.getElementById("placesContext");
contextmenu.addEventListener("popupshown", function() {
contextmenu.removeEventListener("popupshown", arguments.callee, false);
contextmenu.removeEventListener("popupshown", arguments.callee, true);
let forgetThisSite = doc.getElementById("placesContext_deleteHost");
is(forgetThisSite.hidden, !expected,
"The Forget This Site menu item should " + (expected ? "not " : "") + "be hidden");
@@ -85,17 +104,27 @@ function test() {
"The Forget This Site command should " + (expected ? "not " : "") + "be disabled");
// Close the context menu
contextmenu.hidePopup();
// Wait for the Organizer window to actually be closed
function closeObserver(aSubject, aTopic, aData) {
if (aTopic != "domwindowclosed")
return;
Services.ww.unregisterNotification(closeObserver);
SimpleTest.waitForFocus(function() {
// Proceed
funcNext();
});
}
Services.ww.registerNotification(closeObserver);
// Close Library window.
organizer.close();
// Proceed
funcNext();
}, false);
}, true);
// Get cell coordinates
var x = {}, y = {}, width = {}, height = {};
tree.treeBoxObject.getCoordsForCellItem(0, tree.columns[0], "text",
x, y, width, height);
// Initiate a context menu for the selected cell
EventUtils.synthesizeMouse(tree.body, x + 4, y + 4, {type: "contextmenu"}, organizer);
EventUtils.synthesizeMouse(tree.body, x.value + width.value / 2, y.value + height.value / 2, {type: "contextmenu"}, organizer);
});
}, organizer);
}
@@ -115,9 +144,7 @@ function test() {
pb.privateBrowsingEnabled = false;
testForgetThisSiteVisibility(true, function() {
// Cleanup
history.QueryInterface(Ci.nsIBrowserHistory)
.removeAllPages();
finish();
waitForClearHistory(finish);
});
});
});

View File

@@ -35,7 +35,7 @@
*
* ***** END LICENSE BLOCK ***** */
// This test makes sure that browsingmode attribute of the window is correctly
// This test makes sure that privatebrowsingmode attribute of the window is correctly
// switched with private browsing mode changes.
function test() {
@@ -45,20 +45,20 @@ function test() {
getService(Ci.nsIPrivateBrowsingService);
let docRoot = document.documentElement;
is(docRoot.getAttribute("browsingmode"), "normal",
"browsingmode should be \"normal\" initially");
ok(!docRoot.hasAttribute("privatebrowsingmode"),
"privatebrowsingmode should not be present in normal mode");
// enter private browsing mode
pb.privateBrowsingEnabled = true;
is(docRoot.getAttribute("browsingmode"), "private",
"browsingmode should be \"private\" inside the private browsing mode");
is(docRoot.getAttribute("privatebrowsingmode"), "temporary",
"privatebrowsingmode should be \"temporary\" inside the private browsing mode");
// leave private browsing mode
pb.privateBrowsingEnabled = false;
is(docRoot.getAttribute("browsingmode"), "normal",
"browsingmode should be \"normal\" outside the private browsing mode");
ok(!docRoot.hasAttribute("privatebrowsingmode"),
"privatebrowsingmode should not be present in normal mode");
// cleanup
gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session");

View File

@@ -604,7 +604,8 @@
label = this._stringBundle.getString("cmd_pasteAndSearch");
element.setAttribute("label", label);
element.setAttribute("anonid", "paste-and-search");
element.setAttribute("oncommand", "goDoCommand('cmd_paste'); document.getElementById('searchbar').handleSearchCommand();");
element.setAttribute("oncommand",
"BrowserSearch.searchBar.value = ''; goDoCommand('cmd_paste'); BrowserSearch.searchBar.handleSearchCommand();");
cxmenu.insertBefore(element, insertLocation.nextSibling);
pasteAndSearch = element;
}

View File

@@ -45,8 +45,9 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_BROWSER_TEST_FILES = browser_405664.js \
browser_415700.js \
browser_addEngine.js \
testEngine.xml \
testEngine.src \
browser_426329.js \
426329.xml \
browser_483086.js \

View File

@@ -1,85 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ryan Flint <rflint@dslr.net> (Original Author)
*
* 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
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var gSS = Services.search;
function observers(aSubject, aTopic, aData) {
switch (aData) {
case "engine-added":
test2();
break;
case "engine-current":
test3();
break;
case "engine-removed":
test4();
break;
}
}
function test() {
waitForExplicitFinish();
Services.obs.addObserver(observers, "browser-search-engine-modified", false);
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
Ci.nsISearchEngine.DATA_XML, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
false);
}
function test2() {
var engine = gSS.getEngineByName("Foo");
ok(engine, "Engine was added.");
var aEngine = gSS.getEngineByAlias("fooalias");
ok(!aEngine, "Alias was not parsed from engine description");
gSS.currentEngine = engine;
}
function test3() {
var engine = gSS.currentEngine;
is(engine.name, "Foo", "Current engine was changed successfully");
gSS.removeEngine(engine);
}
function test4() {
var engine = gSS.currentEngine;
ok(engine, "An engine is present.");
isnot(engine.name, "Foo", "Current engine reset after removal");
Services.obs.removeObserver(observers, "browser-search-engine-modified");
finish();
}

View File

@@ -0,0 +1,168 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ryan Flint <rflint@dslr.net> (Original Author)
*
* 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
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var gSS = Services.search;
function observer(aSubject, aTopic, aData) {
if (!gCurrentTest) {
info("Observer called with no test active");
return;
}
let engine = aSubject.QueryInterface(Ci.nsISearchEngine);
info("Observer: " + aData + " for " + engine.name);
let method;
switch (aData) {
case "engine-added":
if (gCurrentTest.added)
method = "added"
break;
case "engine-current":
if (gCurrentTest.current)
method = "current";
break;
case "engine-removed":
if (gCurrentTest.removed)
method = "removed";
break;
}
if (method)
gCurrentTest[method](engine);
}
function checkEngine(checkObj, engineObj) {
info("Checking engine");
for (var prop in checkObj)
is(checkObj[prop], engineObj[prop], prop + " is correct");
}
var gTests = [
{
name: "opensearch install",
engine: {
name: "Foo",
alias: null,
description: "Foo Search",
searchForm: "http://mochi.test:8888/browser/browser/components/search/test/",
type: Ci.nsISearchEngine.TYPE_OPENSEARCH
},
run: function () {
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
Ci.nsISearchEngine.DATA_XML, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
false);
},
added: function (engine) {
ok(engine, "engine was added.");
checkEngine(this.engine, engine);
let engineFromSS = gSS.getEngineByName(this.engine.name);
is(engine, engineFromSS, "engine is obtainable via getEngineByName");
let aEngine = gSS.getEngineByAlias("fooalias");
ok(!aEngine, "Alias was not parsed from engine description");
gSS.currentEngine = engine;
},
current: function (engine) {
let currentEngine = gSS.currentEngine;
is(engine, currentEngine, "engine is current");
is(engine.name, this.engine.name, "current engine was changed successfully");
gSS.removeEngine(engine);
},
removed: function (engine) {
let currentEngine = gSS.currentEngine;
ok(currentEngine, "An engine is present.");
isnot(currentEngine.name, this.engine.name, "Current engine reset after removal");
nextTest();
}
},
{
name: "sherlock install",
engine: {
name: "Test Sherlock",
alias: null,
description: "Test Description",
searchForm: "http://example.com/searchform",
type: Ci.nsISearchEngine.TYPE_SHERLOCK
},
run: function () {
gSS.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.src",
Ci.nsISearchEngine.DATA_TEXT, "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC",
false);
},
added: function (engine) {
ok(engine, "engine was added.");
checkEngine(this.engine, engine);
let engineFromSS = gSS.getEngineByName(this.engine.name);
is(engineFromSS, engine, "engine is obtainable via getEngineByName");
gSS.removeEngine(engine);
},
removed: function (engine) {
let currentEngine = gSS.currentEngine;
ok(currentEngine, "An engine is present.");
isnot(currentEngine.name, this.engine.name, "Current engine reset after removal");
nextTest();
}
}
];
var gCurrentTest = null;
function nextTest() {
if (gTests.length) {
gCurrentTest = gTests.shift();
info("Running " + gCurrentTest.name);
gCurrentTest.run();
} else
executeSoon(finish);
}
function test() {
waitForExplicitFinish();
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
registerCleanupFunction(cleanup);
nextTest();
}
function cleanup() {
Services.obs.removeObserver(observer, "browser-search-engine-modified");
}

View File

@@ -0,0 +1,11 @@
<search
name="Test Sherlock"
description="Test Description"
method="GET"
searchform="http://example.com/searchform"
action="http://example.com/action"
queryCharset="UTF-8"
>
<input name="userParam" user>
<input name="param" value="value">
</search>

View File

@@ -36,6 +36,7 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
var gStateObject;
var gTreeData;
@@ -54,13 +55,26 @@ window.onload = function() {
return;
}
}
// remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
if (sessionData.value.charAt(0) == '(')
sessionData.value = sessionData.value.slice(1, -1);
try {
gStateObject = JSON.parse(sessionData.value);
}
catch (exJSON) {
var s = new Cu.Sandbox("about:blank");
gStateObject = Cu.evalInSandbox("(" + sessionData.value + ")", s);
// If we couldn't parse the string with JSON.parse originally, make sure
// that the value in the textbox will be parsable.
sessionData.value = JSON.stringify(gStateObject);
}
// make sure the data is tracked to be restored in case of a subsequent crash
var event = document.createEvent("UIEvents");
event.initUIEvent("input", true, true, window, 0);
sessionData.dispatchEvent(event);
gStateObject = JSON.parse(sessionData.value);
initTreeView();
document.getElementById("errorTryAgain").focus();

View File

@@ -1268,15 +1268,32 @@ SessionStoreService.prototype = {
},
getTabValue: function sss_getTabValue(aTab, aKey) {
var data = aTab.__SS_extdata || {};
let data = {};
if (aTab.__SS_extdata) {
data = aTab.__SS_extdata;
}
else if (aTab.linkedBrowser.__SS_data && aTab.linkedBrowser.__SS_data.extData) {
// If the tab hasn't been fully restored, get the data from the to-be-restored data
data = aTab.linkedBrowser.__SS_data.extData;
}
return data[aKey] || "";
},
setTabValue: function sss_setTabValue(aTab, aKey, aStringValue) {
if (!aTab.__SS_extdata) {
aTab.__SS_extdata = {};
// If the tab hasn't been restored, then set the data there, otherwise we
// could lose newly added data.
let saveTo;
if (aTab.__SS_extdata) {
saveTo = aTab.__SS_extdata;
}
aTab.__SS_extdata[aKey] = aStringValue;
else if (aTab.linkedBrowser.__SS_data && aTab.linkedBrowser.__SS_data.extData) {
saveTo = aTab.linkedBrowser.__SS_data.extData;
}
else {
aTab.__SS_extdata = {};
saveTo = aTab.__SS_extdata;
}
saveTo[aKey] = aStringValue;
this.saveStateDelayed(aTab.ownerDocument.defaultView);
},
@@ -1400,9 +1417,22 @@ SessionStoreService.prototype = {
if (!browser || !browser.currentURI)
// can happen when calling this function right after .addTab()
return tabData;
else if (browser.__SS_data && browser.__SS_data._tabStillLoading)
else if (browser.__SS_data && browser.__SS_data._tabStillLoading) {
// use the data to be restored when the tab hasn't been completely loaded
return browser.__SS_data;
tabData = browser.__SS_data;
if (aTab.pinned)
tabData.pinned = true;
else
delete tabData.pinned;
if (browser.userTypedValue) {
tabData.userTypedValue = browser.userTypedValue;
tabData.userTypedClear = browser.userTypedClear;
} else {
delete tabData.userTypedValue;
delete tabData.userTypedClear;
}
return tabData;
}
var history = null;
try {
@@ -1443,10 +1473,15 @@ SessionStoreService.prototype = {
if (browser.userTypedValue) {
tabData.userTypedValue = browser.userTypedValue;
tabData.userTypedClear = browser.userTypedClear;
} else {
delete tabData.userTypedValue;
delete tabData.userTypedClear;
}
if (aTab.pinned)
tabData.pinned = true;
else
delete tabData.pinned;
tabData.hidden = aTab.hidden;
var disallow = [];

View File

@@ -114,10 +114,13 @@ _BROWSER_TEST_FILES = \
browser_522545.js \
browser_524745.js \
browser_528776.js \
browser_579868.js \
browser_579879.js \
browser_580512.js \
browser_581593.js \
browser_586147.js \
browser_586068-cascaded_restore.js \
browser_590268.js \
browser_600545.js \
$(NULL)

View File

@@ -0,0 +1,71 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is bug 579868 test.
*
* The Initial Developer of the Original Code is
* Sindre Dammann <sindrebugzilla@gmail.com>
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* 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
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
function test() {
let tab1 = gBrowser.addTab("about:robots");
let tab2 = gBrowser.addTab("about:credits");
tab1.addEventListener("load", mainPart, true);
waitForExplicitFinish();
function mainPart() {
// Tell the session storer that the tab is pinned
// and that userTypedValue is "Hello World!"
let newTabState = '{"entries":[{"url":"about:robots"}],"pinned":true,"userTypedValue":"Hello World!"}';
let ss = Cc["@mozilla.org/browser/sessionstore;1"]
.getService(Ci.nsISessionStore);
ss.setTabState(tab1, newTabState);
// Undo pinning and userTypedValue
gBrowser.unpinTab(tab1);
tab1.linkedBrowser.userTypedValue = null;
is(tab1.linkedBrowser.__SS_data._tabStillLoading, true,
"_tabStillLoading should be true.");
// Close and restore tab
gBrowser.removeTab(tab1);
let savedState = JSON.parse(ss.getClosedTabData(window))[0].state;
isnot(savedState.pinned, true, "Pinned should not be true");
isnot(savedState.userTypedValue, "Hello World!",
"userTypedValue should not be Hello World!");
tab1 = ss.undoCloseTab(window, 0);
isnot(tab1.pinned, true, "Should not be pinned");
gBrowser.removeTab(tab1);
gBrowser.removeTab(tab2);
finish();
}
}

View File

@@ -0,0 +1,90 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is sessionstore test code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Paul OShannessy <paul@oshannessy.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
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
Cu.import("resource://gre/modules/Services.jsm");
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
let stateBackup = ss.getBrowserState();
function test() {
/** Test for bug 581593 **/
waitForExplicitFinish();
let oldState = { windows: [{ tabs: [{ entries: [{ url: "example.com" }] }] }]};
let pageData = {
url: "about:sessionrestore",
formdata: { "#sessionData": "(" + JSON.stringify(oldState) + ")" }
};
let state = { windows: [{ tabs: [{ entries: [pageData] }] }] };
// The form data will be restored before SSTabRestored, so we want to listen
// for that on the currently selected tab (it will be reused)
gBrowser.selectedTab.addEventListener("SSTabRestored", onSSTabRestored, true);
ss.setBrowserState(JSON.stringify(state));
}
function onSSTabRestored(aEvent) {
info("SSTabRestored event");
gBrowser.selectedTab.removeEventListener("SSTabRestored", onSSTabRestored, true);
gBrowser.selectedBrowser.addEventListener("input", onInput, true);
}
function onInput(aEvent) {
info("input event");
gBrowser.selectedBrowser.removeEventListener("input", onInput, true);
// This is an ok way to check this because we will make sure that the text
// field is parsable.
let val = gBrowser.selectedBrowser.contentDocument.getElementById("sessionData").value;
try {
JSON.parse(val);
ok(true, "JSON.parse succeeded");
}
catch (e) {
ok(false, "JSON.parse failed");
}
cleanup();
}
function cleanup() {
ss.setBrowserState(stateBackup);
executeSoon(finish);
}

View File

@@ -0,0 +1,148 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is sessionstore test code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Paul OShannessy <paul@oshannessy.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
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
const NUM_TABS = 12;
Cu.import("resource://gre/modules/Services.jsm");
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore);
let stateBackup = ss.getBrowserState();
function test() {
/** Test for Bug 590268 - Provide access to sessionstore tab data sooner **/
waitForExplicitFinish();
let startedTest = false;
// wasLoaded will be used to keep track of tabs that have already had SSTabRestoring
// fired for them.
let wasLoaded = { };
let restoringTabsCount = 0;
let uniq2 = { };
let uniq2Count = 0;
let state = { windows: [{ tabs: [] }] };
// We're going to put a bunch of tabs into this state
for (let i = 0; i < NUM_TABS; i++) {
let uniq = r();
let tabData = {
entries: [{ url: "http://example.com/#" + i }],
extData: { "uniq": uniq }
};
state.windows[0].tabs.push(tabData);
wasLoaded[uniq] = false;
}
function onSSTabRestoring(aEvent) {
restoringTabsCount++;
let uniq = ss.getTabValue(aEvent.originalTarget, "uniq");
wasLoaded[uniq] = true;
// On the first SSTabRestoring we're going to run the the real test.
// We'll keep this listener around so we can keep marking tabs as restored.
if (restoringTabsCount == 1)
onFirstSSTabRestoring();
else if (restoringTabsCount == NUM_TABS)
onLastSSTabRestoring();
}
// This does the actual testing. SSTabRestoring should be firing on tabs from
// left to right, so we're going to start with the rightmost tab.
function onFirstSSTabRestoring() {
info("onFirstSSTabRestoring...");
for (let i = gBrowser.tabs.length - 1; i >= 0; i--) {
let tab = gBrowser.tabs[i];
let actualUniq = ss.getTabValue(tab, "uniq");
let expectedUniq = state.windows[0].tabs[i].extData["uniq"];
if (wasLoaded[actualUniq]) {
info("tab " + i + ": already restored");
continue;
}
is(actualUniq, expectedUniq, "tab " + i + ": extData was correct");
// Now we're going to set a piece of data back on the tab so it can be read
// to test setting a value "early".
uniq2[actualUniq] = r();
ss.setTabValue(tab, "uniq2", uniq2[actualUniq]);
// This will be used in the final comparison to make sure we checked the
// same number as we set.
uniq2Count++;
}
}
function onLastSSTabRestoring() {
let checked = 0;
for (let i = 0; i < gBrowser.tabs.length; i++) {
let tab = gBrowser.tabs[i];
let uniq = ss.getTabValue(tab, "uniq");
// Look to see if we set a uniq2 value for this uniq value
if (uniq in uniq2) {
is(ss.getTabValue(tab, "uniq2"), uniq2[uniq], "tab " + i + " has correct uniq2 value");
checked++;
}
}
is(checked, uniq2Count, "checked the same number of uniq2 as we set");
cleanup();
}
function cleanup() {
// remove the event listener and clean up before finishing
gBrowser.tabContainer.removeEventListener("SSTabRestoring", onSSTabRestoring, false);
// Put this in an executeSoon because we still haven't called restoreNextTab
// in sessionstore for the last tab (we'll call it after this). We end up
// trying to restore the tab (since we then add a closed tab to the array).
executeSoon(function() {
ss.setBrowserState(stateBackup);
executeSoon(finish);
});
}
// Add the event listener
gBrowser.tabContainer.addEventListener("SSTabRestoring", onSSTabRestoring, false);
// Restore state
ss.setBrowserState(JSON.stringify(state));
}
// Helper function to create a random value
function r() {
return "" + Date.now() + Math.random();
}