Bug 1175850 - Enable storage inspector tests after upgrading for E10S r=pbrosset

This commit is contained in:
Michael Ratcliffe 2015-08-20 11:52:04 +01:00
parent be7b575586
commit 84fea53d30
23 changed files with 698 additions and 543 deletions

View File

@ -20,11 +20,6 @@ function performChecks(target) {
for (let index = 0; index < toolIds.length; index++) {
let toolId = toolIds[index];
// FIXME Bug 1175850 - Enable storage inspector tests after upgrading for E10S
if (toolId === "storage") {
continue;
}
info("About to open " + index + "/" + toolId);
toolbox = yield gDevTools.showToolbox(target, toolId);
ok(toolbox, "toolbox exists for " + toolId);

View File

@ -49,11 +49,6 @@ function runTools(target) {
for (let index = 0; index < toolIds.length; index++) {
let toolId = toolIds[index];
// FIXME Bug 1175850 - Enable storage inspector tests after upgrading for E10S
if (toolId === "storage") {
continue;
}
info("About to open " + index + "/" + toolId);
toolbox = yield gDevTools.showToolbox(target, toolId, "window");
ok(toolbox, "toolbox exists for " + toolId);

View File

@ -45,12 +45,6 @@ function testShortcuts(aToolbox, aIndex) {
toolbox = aToolbox;
info("Toolbox fired a `ready` event");
// FIXME Bug 1175850 - Enable storage inspector tests after upgrading for E10S
if (toolIDs[aIndex] === "storage") {
testShortcuts(toolbox, aIndex + 1);
return;
}
toolbox.once("select", selectCB);
let key = gDevTools._tools.get(toolIDs[aIndex]).key;

View File

@ -20,7 +20,8 @@ loader.lazyGetter(this, "StorageFront",
loader.lazyGetter(this, "StorageUI",
() => require("devtools/storage/ui").StorageUI);
this.StoragePanel = function StoragePanel(panelWin, toolbox) {
let StoragePanel = this.StoragePanel =
function StoragePanel(panelWin, toolbox) {
EventEmitter.decorate(this);
this._toolbox = toolbox;
@ -60,8 +61,9 @@ StoragePanel.prototype = {
this.UI = new StorageUI(this._front, this._target, this._panelWin);
this.isReady = true;
this.emit("ready");
return this;
}, console.error);
}).catch(this.destroy);
},
/**
@ -70,14 +72,17 @@ StoragePanel.prototype = {
destroy: function() {
if (!this._destroyed) {
this.UI.destroy();
this.UI = null;
// Destroy front to ensure packet handler is removed from client
this._front.destroy();
this._front = null;
this._destroyed = true;
this._target.off("close", this.destroy);
this._target = null;
this._toolbox = null;
this._panelDoc = null;
this._panelWin = null;
}
return Promise.resolve(null);

View File

@ -1,8 +1,5 @@
[DEFAULT]
tags = devtools
# Bug 1049888 - storage actors do not work in e10s for now
# Bug 1105803 - permafailing on debug release builds since devedition landed
skip-if = e10s || debug
subsuite = devtools
support-files =
storage-complex-values.html

View File

@ -17,10 +17,10 @@
// These entries are formed by the cookies, local storage, session storage and
// indexedDB entries created in storage-listings.html,
// storage-secured-iframe.html and storage-unsecured-iframe.html
const storeItems = [
"use strict";
const testCases = [
[["cookies", "test1.example.org"],
["c1", "cs2", "c3", "uc1"]],
[["cookies", "sectest1.example.org"],
@ -68,7 +68,7 @@ const storeItems = [
*/
function testTree() {
let doc = gPanelWindow.document;
for (let item of storeItems) {
for (let item of testCases) {
ok(doc.querySelector("[data-id='" + JSON.stringify(item[0]) + "']"),
"Tree item " + item[0] + " should be present in the storage tree");
}
@ -77,21 +77,20 @@ function testTree() {
/**
* Test that correct table entries are shown for each of the tree item
*/
let testTables = Task.async(function*() {
function* testTables() {
let doc = gPanelWindow.document;
// Expand all nodes so that the synthesized click event actually works
gUI.tree.expandAll();
// First tree item is already selected so no clicking and waiting for update
for (let id of storeItems[0][1]) {
for (let id of testCases[0][1]) {
ok(doc.querySelector(".table-widget-cell[data-id='" + id + "']"),
"Table item " + id + " should be present");
}
// Click rest of the tree items and wait for the table to be updated
for (let item of storeItems.slice(1)) {
selectTreeItem(item[0]);
yield gUI.once("store-objects-updated");
for (let item of testCases.slice(1)) {
yield selectTreeItem(item[0]);
// Check whether correct number of items are present in the table
is(doc.querySelectorAll(
@ -104,14 +103,13 @@ let testTables = Task.async(function*() {
"Table item " + id + " should be present");
}
}
});
}
add_task(function*() {
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html");
let startTest = Task.async(function*() {
testTree();
yield testTables();
finishTests();
});
function test() {
openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html").then(startTest);
}
yield finishTests();
});

View File

@ -2,9 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
let testUpdates = Task.async(function*() {
"use strict";
add_task(function*() {
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-updates.html");
let $ = id => gPanelWindow.document.querySelector(id);
let $$ = sel => gPanelWindow.document.querySelectorAll(sel);
@ -12,8 +13,7 @@ let testUpdates = Task.async(function*() {
gUI.tree.expandAll();
ok(gUI.sidebar.hidden, "Sidebar is initially hidden");
selectTableItem("c1");
yield gUI.once("sidebar-updated");
yield selectTableItem("c1");
// test that value is something initially
let initialValue = [[
@ -49,7 +49,7 @@ let testUpdates = Task.async(function*() {
ok($("#value [data-id='c1'].table-widget-cell"),
"cell is present after update");
is($("#value [data-id='c1'].table-widget-cell").value, '{"foo": 4,"bar":6}',
"correct final value in table");
"correct final value in table");
// Add a new entry
is($$("#value .table-widget-cell").length, 2,
@ -119,8 +119,7 @@ let testUpdates = Task.async(function*() {
ok(gUI.sidebar.hidden, "Sidebar is hidden when no rows");
// Testing in local storage
selectTreeItem(["localStorage", "http://test1.example.org"]);
yield gUI.once("store-objects-updated");
yield selectTreeItem(["localStorage", "http://test1.example.org"]);
is($$("#value .table-widget-cell").length, 7,
"Correct number of rows after delete update 7");
@ -156,9 +155,7 @@ let testUpdates = Task.async(function*() {
"Value got updated for local storage");
// Testing in session storage
selectTreeItem(["sessionStorage", "http://test1.example.org"]);
yield gUI.once("store-objects-updated");
yield selectTreeItem(["sessionStorage", "http://test1.example.org"]);
is($$("#value .table-widget-cell").length, 3,
"Correct number of rows for session storage");
@ -184,9 +181,7 @@ let testUpdates = Task.async(function*() {
is($$("#value .table-widget-cell").length, 2,
"Correct number of rows after removing items from session storage");
selectTableItem("ss2");
yield gUI.once("sidebar-updated");
yield selectTableItem("ss2");
ok(!gUI.sidebar.hidden, "sidebar is visible");
@ -202,13 +197,5 @@ let testUpdates = Task.async(function*() {
yield findVariableViewProperties([{name: "ss2", value: "changed=ss2"}]);
yield finishTests();
});
let startTest = Task.async(function*() {
yield testUpdates();
finishTests();
});
function test() {
openTabAndSetupStorage(MAIN_DOMAIN + "storage-updates.html").then(startTest);
}

View File

@ -15,56 +15,111 @@
"use strict";
const testCases = [
[["cookies", "sectest1.example.org"], 0, 0],
["cs2", 1, 1],
[null, 0, 0],
["cs2", 1, 1],
["uc1", 1, 1],
["uc1", 0, 1],
[["localStorage", "http://sectest1.example.org"], 0, 0],
["iframe-u-ls1", 1, 1],
["iframe-u-ls1", 0, 1],
[null, 0, 0],
[["sessionStorage", "http://test1.example.org"], 0, 0],
["ss1", 1, 1],
[null, 0, 0],
[["indexedDB", "http://test1.example.org"], 0, 0],
["idb2", 1, 1],
[["indexedDB", "http://test1.example.org", "idb2", "obj3"], 0, 0],
[["indexedDB", "https://sectest1.example.org", "idb-s2"], 0, 0],
["obj-s2", 1, 1],
[null, 0, 0],
[null, 0, 0],
["obj-s2", 1, 1],
[null, 0, 0],
{
location: ["cookies", "sectest1.example.org"],
sidebarHidden: true
},
{
location: "cs2",
sidebarHidden: false
},
{
sendEscape: true
},
{
location: "cs2",
sidebarHidden: false
},
{
location: "uc1",
sidebarHidden: false
},
{
location: "uc1",
sidebarHidden: false
},
{
location: ["localStorage", "http://sectest1.example.org"],
sidebarHidden: true
},
{
location: "iframe-u-ls1",
sidebarHidden: false
},
{
location: "iframe-u-ls1",
sidebarHidden: false
},
{
sendEscape: true
},
{
location: ["sessionStorage", "http://test1.example.org"],
sidebarHidden: true
},
{
location: "ss1",
sidebarHidden: false
},
{
sendEscape: true
},
{
location: ["indexedDB", "http://test1.example.org"],
sidebarHidden: true
},
{
location: "idb2",
sidebarHidden: false
},
{
location: ["indexedDB", "http://test1.example.org", "idb2", "obj3"],
sidebarHidden: true
},
{
location: ["indexedDB", "https://sectest1.example.org", "idb-s2"],
sidebarHidden: true
},
{
location: "obj-s2",
sidebarHidden: false
},
{
sendEscape: true
}, {
location: "obj-s2",
sidebarHidden: false
}
];
let testSidebar = Task.async(function*() {
let doc = gPanelWindow.document;
for (let item of testCases) {
info("clicking for item " + item);
if (Array.isArray(item[0])) {
selectTreeItem(item[0]);
yield gUI.once("store-objects-updated");
add_task(function*() {
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html");
for (let test of testCases) {
let { location, sidebarHidden, sendEscape } = test;
info("running " + JSON.stringify(test));
if (Array.isArray(location)) {
yield selectTreeItem(location);
} else if (location) {
yield selectTableItem(location);
}
else if (item[0]) {
selectTableItem(item[0]);
}
else {
if (sendEscape) {
EventUtils.sendKey("ESCAPE", gPanelWindow);
} else {
is(gUI.sidebar.hidden, sidebarHidden,
"correct visibility state of sidebar.");
}
if (item[1]) {
yield gUI.once("sidebar-updated");
}
is(!item[2], gUI.sidebar.hidden, "Correct visibility state of sidebar");
info("-".repeat(80));
}
});
let startTest = Task.async(function*() {
yield testSidebar();
finishTests();
yield finishTests();
});
function test() {
openTabAndSetupStorage(MAIN_DOMAIN + "storage-listings.html").then(startTest);
}

View File

@ -116,31 +116,23 @@ const testCases = [
], true]
];
let testValues = Task.async(function*() {
add_task(function*() {
yield openTabAndSetupStorage(MAIN_DOMAIN + "storage-complex-values.html");
gUI.tree.expandAll();
let doc = gPanelWindow.document;
for (let item of testCases) {
info("clicking for item " + item);
if (Array.isArray(item[0])) {
selectTreeItem(item[0]);
yield gUI.once("store-objects-updated");
yield selectTreeItem(item[0]);
continue;
} else if (item[0]) {
yield selectTableItem(item[0]);
}
else if (item[0]) {
selectTableItem(item[0]);
}
if (item[0] && item[1]) {
yield gUI.once("sidebar-updated");
}
yield findVariableViewProperties(item[1], item[2]);
}
});
let startTest = Task.async(function*() {
yield testValues();
finishTests();
yield finishTests();
});
function test() {
openTabAndSetupStorage(MAIN_DOMAIN + "storage-complex-values.html").then(startTest);
}

View File

@ -10,6 +10,8 @@ let { console } = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
const SPLIT_CONSOLE_PREF = "devtools.toolbox.splitconsoleEnabled";
const STORAGE_PREF = "devtools.storage.enabled";
const DUMPEMIT_PREF = "devtools.dump.emit";
const DEBUGGERLOG_PREF = "devtools.debugger.log";
const PATH = "browser/browser/devtools/storage/test/";
const MAIN_DOMAIN = "http://test1.example.org/" + PATH;
const ALT_DOMAIN = "http://sectest1.example.org/" + PATH;
@ -22,12 +24,17 @@ waitForExplicitFinish();
let gToolbox, gPanelWindow, gWindow, gUI;
// Services.prefs.setBoolPref(DUMPEMIT_PREF, true);
// Services.prefs.setBoolPref(DEBUGGERLOG_PREF, true);
Services.prefs.setBoolPref(STORAGE_PREF, true);
DevToolsUtils.testing = true;
registerCleanupFunction(() => {
gToolbox = gPanelWindow = gWindow = gUI = null;
Services.prefs.clearUserPref(STORAGE_PREF);
Services.prefs.clearUserPref(SPLIT_CONSOLE_PREF);
Services.prefs.clearUserPref(DUMPEMIT_PREF);
Services.prefs.clearUserPref(DEBUGGERLOG_PREF);
DevToolsUtils.testing = false;
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
@ -66,15 +73,16 @@ function addTab(url) {
}
/**
* Opens the given url in a new tab, then sets up the page by waiting for
* all cookies, indexedDB items etc. to be created; Then opens the storage
* inspector and waits for the storage tree and table to be populated
* This generator function opens the given url in a new tab, then sets up the
* page by waiting for all cookies, indexedDB items etc. to be created; Then
* opens the storage inspector and waits for the storage tree and table to be
* populated.
*
* @param url {String} The url to be opened in the new tab
*
* @return {Promise} A promise that resolves after storage inspector is ready
*/
let openTabAndSetupStorage = Task.async(function*(url) {
function* openTabAndSetupStorage(url) {
/**
* This method iterates over iframes in a window and setups the indexed db
* required for this test.
@ -107,7 +115,7 @@ let openTabAndSetupStorage = Task.async(function*(url) {
// open storage inspector
return yield openStoragePanel();
});
}
/**
* Open the toolbox, with the storage tool visible.
@ -193,42 +201,59 @@ function forceCollections() {
}
/**
* Cleans up and finishes the test
* Get all windows including frames recursively.
*
* @param {Window} [baseWindow]
* The base window at which to start looking for child windows
* (optional).
* @return {Set}
* A set of windows.
*/
function finishTests() {
// Cleanup so that indexed db created from this test do not interfere next ones
function getAllWindows(baseWindow=gWindow) {
let windows = new Set();
/**
* This method iterates over iframes in a window and clears the indexed db
* created by this test.
*/
let clearIDB = (w, i, c) => {
if (w[i] && w[i].clear) {
w[i].clearIterator = w[i].clear(() => clearIDB(w, i + 1, c));
w[i].clearIterator.next();
}
else if (w[i] && w[i + 1]) {
clearIDB(w, i + 1, c);
}
else {
c();
let _getAllWindows = function(win) {
windows.add(win);
for (let i = 0; i < win.length; i++) {
_getAllWindows(win[i]);
}
};
_getAllWindows(baseWindow);
gWindow.clearIterator = gWindow.clear(() => {
clearIDB(gWindow, 0, () => {
// Forcing GC/CC to get rid of docshells and windows created by this test.
forceCollections();
finish();
});
});
gWindow.clearIterator.next();
return windows;
}
/**
* Cleans up and finishes the test
*/
function* finishTests() {
for (let win of getAllWindows()) {
if (win.clear) {
console.log("Clearing cookies, localStorage and indexedDBs from " +
win.document.location);
yield win.clear();
}
}
forceCollections();
finish();
}
// Sends a click event on the passed DOM node in an async manner
function click(node) {
function* click(node) {
let def = promise.defer();
node.scrollIntoView();
executeSoon(() => EventUtils.synthesizeMouseAtCenter(node, {}, gPanelWindow));
// We need setTimeout here to allow any scrolling to complete before clicking
// the node.
setTimeout(() => {
node.click();
def.resolve();
}, 200);
return def;
}
/**
@ -463,39 +488,18 @@ function matchVariablesViewProperty(aProp, aRule) {
* @param {[String]} ids
* The array id of the item in the tree
*/
function selectTreeItem(ids) {
function* selectTreeItem(ids) {
// Expand tree as some/all items could be collapsed leading to click on an
// incorrect tree item
gUI.tree.expandAll();
let target = gPanelWindow.document.querySelector(
"[data-id='" + JSON.stringify(ids) + "'] > .tree-widget-item");
// Look for an animating list
//
// If the list is still expanding we won't be able to click the requested
// item. We detect if a list (or one of its ancestor lists) is animating
// by checking if max-height is set. If the animation effect in
// widgets.inc.css changes this will likely break but until the Web
// Animations API is available (specifically, bug 1074630 and bug 1112422)
// there is no reliable way to detect if animations are running, particularly
// in the face of interactions that can cancel an animation without triggering
// an animationend event.
let animatingList = target.nextElementSibling;
while (animatingList) {
if (window.getComputedStyle(animatingList).maxHeight != "none") {
break;
}
animatingList = animatingList.parentNode.closest(".tree-widget-item + ul");
}
let selector = "[data-id='" + JSON.stringify(ids) + "'] > .tree-widget-item";
let target = gPanelWindow.document.querySelector(selector);
if (animatingList) {
animatingList.addEventListener("animationend", function animationend() {
animatingList.removeEventListener("animationend", animationend);
click(target);
});
} else {
click(target);
}
let updated = gUI.once("store-objects-updated");
yield click(target);
yield updated;
}
/**
@ -504,7 +508,40 @@ function selectTreeItem(ids) {
* @param {String} id
* The id of the row in the table widget
*/
function selectTableItem(id) {
click(gPanelWindow.document.querySelector(".table-widget-cell[data-id='" +
id + "']"));
function* selectTableItem(id) {
let selector = ".table-widget-cell[data-id='" + id + "']";
let target = gPanelWindow.document.querySelector(selector);
yield click(target);
yield gUI.once("sidebar-updated");
}
/**
* Wait for eventName on target.
* @param {Object} target An observable object that either supports on/off or
* addEventListener/removeEventListener
* @param {String} eventName
* @param {Boolean} [useCapture] for addEventListener/removeEventListener
* @return A promise that resolves when the event has been handled
*/
function once(target, eventName, useCapture=false) {
info("Waiting for event: '" + eventName + "' on " + target + ".");
let deferred = promise.defer();
for (let [add, remove] of [
["addEventListener", "removeEventListener"],
["addListener", "removeListener"],
["on", "off"]
]) {
if ((add in target) && (remove in target)) {
target[add](eventName, function onEvent(...aArgs) {
target[remove](eventName, onEvent, useCapture);
deferred.resolve.apply(deferred, aArgs);
}, useCapture);
break;
}
}
return deferred.promise;
}

View File

@ -81,24 +81,28 @@ window.idbGenerator = function*(callback) {
db2.close();
console.log("added cookies and stuff from main page");
callback();
};
function deleteDB(dbName) {
return new Promise(resolve => {
dump("removing database " + dbName + " from " + document.location + "\n");
indexedDB.deleteDatabase(dbName).onsuccess = resolve;
});
}
function successClear(event) {
clearIterator.next(event);
}
window.clear = function*(callback) {
window.clear = function*() {
document.cookie = "c1=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/browser";
document.cookie = "cs2=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
localStorage.clear();
sessionStorage.clear();
indexedDB.deleteDatabase("idb1").onsuccess = successClear;
yield undefined;
indexedDB.deleteDatabase("idb2").onsuccess = successClear;
yield undefined;
console.log("removed cookies and stuff from main page");
callback();
}
yield deleteDB("idb1");
yield deleteDB("idb2");
dump("removed cookies, localStorage, sessionStorage and indexedDB data " +
"from " + document.location + "\n");
};
</script>
</body>
</html>

View File

@ -26,7 +26,7 @@ localStorage.setItem("ls1", "foobar");
localStorage.setItem("ls2", "foobar-2");
// ... and finally some session storage items too
sessionStorage.setItem("ss1", "foobar-3");
console.log("added cookies and stuff from main page");
dump("added cookies and stuff from main page\n");
function success(event) {
setupIDB.next(event);
@ -73,27 +73,34 @@ window.idbGenerator = function*(callback) {
yield undefined;
db2.close();
console.log("added cookies and stuff from main page");
dump("added cookies and stuff from main page\n");
callback();
};
function deleteDB(dbName) {
return new Promise(resolve => {
dump("removing database " + dbName + " from " + document.location + "\n");
indexedDB.deleteDatabase(dbName).onsuccess = resolve;
});
}
function successClear(event) {
clearIterator.next(event);
}
window.clear = function*(callback) {
window.clear = function*() {
document.cookie = "c1=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/browser";
document.cookie = "c3=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; secure=true";
document.cookie = "cs2=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=" + partialHostname;
document.cookie =
"c3=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; secure=true";
document.cookie =
"cs2=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=" +
partialHostname;
localStorage.clear();
sessionStorage.clear();
indexedDB.deleteDatabase("idb1").onsuccess = successClear;
yield undefined;
indexedDB.deleteDatabase("idb2").onsuccess = successClear;
yield undefined;
console.log("removed cookies and stuff from main page");
callback();
}
yield deleteDB("idb1");
yield deleteDB("idb2");
dump("removed cookies, localStorage, sessionStorage and indexedDB data " +
"from " + document.location + "\n");
};
</script>
</body>
</html>

View File

@ -50,25 +50,29 @@ window.idbGenerator = function*(callback) {
yield undefined;
db2.close();
console.log("added cookies and stuff from secured iframe");
dump("added cookies and stuff from secured iframe\n");
callback();
};
function deleteDB(dbName) {
return new Promise(resolve => {
dump("removing database " + dbName + " from " + document.location + "\n");
indexedDB.deleteDatabase(dbName).onsuccess = resolve;
});
}
function successClear(event) {
clearIterator.next(event);
}
window.clear = function*(callback) {
window.clear = function*() {
document.cookie = "sc1=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
localStorage.clear();
sessionStorage.clear();
indexedDB.deleteDatabase("idb-s1").onsuccess = successClear;
yield undefined;
indexedDB.deleteDatabase("idb-s2").onsuccess = successClear;
yield undefined;
console.log("removed cookies and stuff from secured iframe");
callback();
}
yield deleteDB("idb-s1");
yield deleteDB("idb-s2");
dump("removed cookies, localStorage, sessionStorage and indexedDB data " +
"from " + document.location + "\n");
};
</script>
</body>
</html>

View File

@ -15,13 +15,16 @@ sessionStorage.setItem("iframe-u-ss1", "foobar1");
sessionStorage.setItem("iframe-u-ss2", "foobar2");
console.log("added cookies and stuff from unsecured iframe");
window.clear = function*(callback) {
document.cookie = "uc1=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.example.org; secure=true";
window.clear = function*() {
document.cookie = "uc1=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; " +
"domain=.example.org; secure=true";
localStorage.clear();
sessionStorage.clear();
console.log("removed cookies and stuff from unsecured iframe");
callback();
}
dump("removed cookies, localStorage and sessionStorage from " +
document.location + "\n");
};
</script>
</body>
</html>

View File

@ -38,10 +38,13 @@ window.clear = function*() {
removeCookie(cookie.split("=")[0]);
removeCookie(cookie.split("=")[0], "/browser");
}
localStorage.clear();
sessionStorage.clear();
callback();
}
dump("removed cookies, localStorage and sessionStorage from " +
document.location + "\n");
};
window.onload = function() {
addCookie("c1", "1.2.3.4.5.6.7", "/browser");

View File

@ -82,7 +82,7 @@ let StorageUI = this.StorageUI = function StorageUI(front, target, panelWin) {
this.front.listStores().then(storageTypes => {
this.populateStorageTree(storageTypes);
}).then(null, Cu.reportError);
}).then(null, console.error);
this.onUpdate = this.onUpdate.bind(this);
this.front.on("stores-update", this.onUpdate);
@ -305,6 +305,10 @@ StorageUI.prototype = {
populateStorageTree: function(storageTypes) {
this.storageTypes = {};
for (let type in storageTypes) {
if (type === "from") {
continue;
}
let typeLabel = L10N.getStr("tree.labels." + type);
this.tree.add([{id: type, label: typeLabel, type: "store"}]);
if (storageTypes[type].hosts) {

View File

@ -7,12 +7,6 @@
const {Cc, Ci} = require("chrome");
const events = require("sdk/event/core");
const protocol = require("devtools/server/protocol");
try {
const { indexedDB } = require("sdk/indexed-db");
} catch (e) {
// In xpcshell tests, we can't actually have indexedDB, which is OK:
// we don't use it there anyway.
}
const {async} = require("devtools/async-utils");
const {Arg, method, RetVal, types} = protocol;
const {LongStringActor} = require("devtools/server/actors/string");
@ -20,6 +14,7 @@ const {DebuggerServer} = require("devtools/server/main");
const Services = require("Services");
const promise = require("promise");
const LayoutHelpers = require("devtools/toolkit/layout-helpers");
const { setTimeout, clearTimeout } = require("sdk/timers");
loader.lazyImporter(this, "OS", "resource://gre/modules/osfile.jsm");
loader.lazyImporter(this, "Sqlite", "resource://gre/modules/Sqlite.jsm");
@ -29,9 +24,9 @@ let gTrackedMessageManager = new Map();
// Maximum number of cookies/local storage key-value-pairs that can be sent
// over the wire to the client in one request.
const MAX_STORE_OBJECT_COUNT = 50;
// Interval for the batch job that sends the accumilated update packets to the
// Delay for the batch job that sends the accumulated update packets to the
// client (ms).
const UPDATE_INTERVAL = 500;
const BATCH_DELAY = 200;
// A RegExp for characters that cannot appear in a file/directory name. This is
// used to sanitize the host name for indexed db to lookup whether the file is
@ -65,19 +60,16 @@ function getRegisteredTypes() {
* An async method equivalent to setTimeout but using Promises
*
* @param {number} time
* The wait Ttme in milliseconds.
* The wait time in milliseconds.
*/
function sleep(time) {
let wait = promise.defer();
let updateTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
updateTimer.initWithCallback({
notify: function() {
updateTimer.cancel();
updateTimer = null;
wait.resolve(null);
}
}, time, Ci.nsITimer.TYPE_ONE_SHOT);
return wait.promise;
let deferred = promise.defer();
setTimeout(() => {
deferred.resolve(null);
}, time);
return deferred.promise;
}
// Cookies store object
@ -227,6 +219,8 @@ StorageActors.defaults = function(typeName, observationTopic, storeObjectType) {
}
events.off(this.storageActor, "window-ready", this.onWindowReady);
events.off(this.storageActor, "window-destroyed", this.onWindowDestroyed);
this.storageActor = null;
},
getNamesForHost: function(host) {
@ -482,19 +476,17 @@ StorageActors.createActor({
destroy: function() {
this.hostVsStores = null;
this.removeCookieObservers();
// prevents multiple subscriptions on the same messagemanager
let oldMM = gTrackedMessageManager.get("cookies");
if (oldMM) {
gTrackedMessageManager.delete("cookies");
oldMM.removeMessageListener("storage:storage-cookie-request-parent",
cookieHelpers.handleChildRequest);
// We need to remove the cookie listeners early in E10S mode so we need to
// use a conditional here to ensure that we only attempt to remove them in
// single process mode.
if (!DebuggerServer.isInChildProcess) {
this.removeCookieObservers();
}
events.off(this.storageActor, "window-ready", this.onWindowReady);
events.off(this.storageActor, "window-destroyed", this.onWindowDestroyed);
this._pendingResponse = this.storageActor = null;
},
/**
@ -584,7 +576,9 @@ StorageActors.createActor({
* cookie change in the "cookie-change" topic.
*/
onCookieChanged: function(subject, topic, action) {
if (topic != "cookie-changed" || !this.storageActor.windows) {
if (topic !== "cookie-changed" ||
!this.storageActor ||
!this.storageActor.windows) {
return null;
}
@ -674,10 +668,8 @@ StorageActors.createActor({
if (reply.length === 0) {
console.error("ERR_DIRECTOR_CHILD_NO_REPLY from " + methodName);
throw Error("ERR_DIRECTOR_CHILD_NO_REPLY from " + methodName);
} else if (reply.length > 1) {
console.error("ERR_DIRECTOR_CHILD_MULTIPLE_REPLIES from " + methodName);
throw Error("ERR_DIRECTOR_CHILD_MULTIPLE_REPLIES from " + methodName);
}
let result = reply[0];
@ -746,7 +738,6 @@ let cookieHelpers = {
return JSON.stringify(cookies);
case "addCookieObservers":
return cookieHelpers.addCookieObservers();
break;
case "removeCookieObservers":
return cookieHelpers.removeCookieObservers();
default:
@ -775,10 +766,16 @@ exports.setupParentProcessForCookies = function({mm, prefix}) {
function handleMessageManagerDisconnected(evt, { mm: disconnected_mm }) {
// filter out not subscribed message managers
if (disconnected_mm !== mm || !gTrackedMessageManager.has(mm)) {
if (disconnected_mm !== mm || !gTrackedMessageManager.has("cookies")) {
return;
}
// Although "disconnected-from-child" implies that the child is already
// disconnected this is not the case. The disconnection takes place after
// this method has finished. This gives us chance to clean up items within
// the parent process e.g. observers.
cookieHelpers.removeCookieObservers();
gTrackedMessageManager.delete("cookies");
// unregister for director-script requests handlers from the parent process
@ -791,10 +788,16 @@ exports.setupParentProcessForCookies = function({mm, prefix}) {
if (methodName === "onCookieChanged") {
args[0] = JSON.stringify(args[0]);
}
let reply = mm.sendAsyncMessage("storage:storage-cookie-request-child", {
method: methodName,
args: args
});
try {
mm.sendAsyncMessage("storage:storage-cookie-request-child", {
method: methodName,
args: args
});
} catch(e) {
// We may receive a NS_ERROR_NOT_INITIALIZED if the target window has
// been closed. This can legitimately happen in between test runs.
}
}
};
@ -1055,15 +1058,6 @@ StorageActors.createActor({
this.hostVsStores = null;
this.objectsSize = null;
// prevents multiple subscriptions on the same messagemanager
let oldMM = gTrackedMessageManager.get("indexedDB");
if (oldMM) {
gTrackedMessageManager.delete("indexedDB");
oldMM.removeMessageListener("storage:storage-cookie-request-parent",
indexedDBHelpers.handleChildRequest);
}
events.off(this.storageActor, "window-ready", this.onWindowReady);
events.off(this.storageActor, "window-destroyed", this.onWindowDestroyed);
},
@ -1616,7 +1610,7 @@ exports.setupParentProcessForIndexedDB = function({mm, prefix}) {
function handleMessageManagerDisconnected(evt, { mm: disconnected_mm }) {
// filter out not subscribed message managers
if (disconnected_mm !== mm || !gTrackedMessageManager.has(mm)) {
if (disconnected_mm !== mm || !gTrackedMessageManager.has("indexedDB")) {
return;
}
@ -1699,11 +1693,6 @@ let StorageActor = exports.StorageActor = protocol.ActorClass({
this.destroyed = false;
this.boundUpdate = {};
// The time which periodically flushes and transfers the updated store
// objects.
this.updateTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this.updateTimer.initWithCallback(this, UPDATE_INTERVAL,
Ci.nsITimer.TYPE_REPEATING_PRECISE_CAN_SKIP);
// Layout helper for window.parent and window.top helper methods that work
// accross devices.
@ -1711,8 +1700,8 @@ let StorageActor = exports.StorageActor = protocol.ActorClass({
},
destroy: function() {
this.updateTimer.cancel();
this.updateTimer = null;
clearTimeout(this.batchTimer);
this.batchTimer = null;
this.layoutHelper = null;
// Remove observers
Services.obs.removeObserver(this, "content-document-global-created", false);
@ -1730,7 +1719,9 @@ let StorageActor = exports.StorageActor = protocol.ActorClass({
}
this.childActorPool.clear();
this.childWindowPool.clear();
this.childWindowPool = this.childActorPool = null;
this.childWindowPool = this.childActorPool = this.__poolMap = this.conn =
this.parentActor = this.boundUpdate = this.registeredPool =
this._pendingResponse = null;
},
/**
@ -1853,24 +1844,10 @@ let StorageActor = exports.StorageActor = protocol.ActorClass({
response: RetVal(types.addDictType("storelist", getRegisteredTypes()))
}),
/**
* Notifies the client front with the updates in stores at regular intervals.
*/
notify: function() {
if (!this.updatePending || this.updatingUpdateObject) {
return null;
}
events.emit(this, "stores-update", this.boundUpdate);
this.boundUpdate = {};
this.updatePending = false;
return null;
},
/**
* This method is called by the registered storage types so as to tell the
* Storage Actor that there are some changes in the stores. Storage Actor then
* notifies the client front about these changes at regular (UPDATE_INTERVAL)
* notifies the client front about these changes at regular (BATCH_DELAY)
* interval.
*
* @param {string} action
@ -1897,14 +1874,15 @@ let StorageActor = exports.StorageActor = protocol.ActorClass({
return null;
}
this.updatingUpdateObject = true;
if (this.batchTimer) {
clearTimeout(this.batchTimer);
}
if (!this.boundUpdate[action]) {
this.boundUpdate[action] = {};
}
if (!this.boundUpdate[action][storeType]) {
this.boundUpdate[action][storeType] = {};
}
this.updatePending = true;
for (let host in data) {
if (!this.boundUpdate[action][storeType][host] || action == "deleted") {
this.boundUpdate[action][storeType][host] = data[host];
@ -1942,7 +1920,13 @@ let StorageActor = exports.StorageActor = protocol.ActorClass({
}
}
}
this.updatingUpdateObject = false;
this.batchTimer = setTimeout(() => {
clearTimeout(this.batchTimer);
events.emit(this, "stores-update", this.boundUpdate);
this.boundUpdate = {};
}, BATCH_DELAY);
return null;
},

View File

@ -1,6 +1,5 @@
[DEFAULT]
tags = devtools
skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
subsuite = devtools
support-files =
head.js
@ -22,7 +21,9 @@ support-files =
[browser_animation_actors_02.js]
[browser_animation_actors_03.js]
[browser_animation_actors_04.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_animation_actors_05.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_animation_actors_06.js]
[browser_animation_actors_07.js]
[browser_animation_actors_08.js]
@ -35,21 +36,34 @@ support-files =
[browser_animation_actors_15.js]
[browser_animation_actors_16.js]
[browser_canvasframe_helper_01.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_canvasframe_helper_02.js]
[browser_canvasframe_helper_03.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_canvasframe_helper_04.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_canvasframe_helper_05.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_canvasframe_helper_06.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_navigateEvents.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_perf-legacy-front-01.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_perf-legacy-front-02.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_perf-legacy-front-03.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_perf-profiler-01.js]
[browser_perf-profiler-02.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_perf-profiler-03.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_perf-realtime-markers.js]
[browser_perf-recording-actor-01.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_perf-recording-actor-02.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_perf-samples-01.js]
[browser_perf-samples-02.js]
#[browser_perf-front-profiler-01.js] bug 1077464
@ -66,5 +80,8 @@ skip-if = buildapp == 'mulet'
[browser_timeline_iframes.js]
skip-if = buildapp == 'mulet'
[browser_directorscript_actors_exports.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_directorscript_actors_error_events.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_directorscript_actors.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S

View File

@ -68,8 +68,11 @@ function finishTests(client) {
function testStores(data, client) {
testWindowsBeforeReload(data);
testReload().then(() =>
testAddIframe()).then(() =>
// FIXME: Bug 1183581 - browser_storage_dynamic_windows.js IsSafeToRunScript
// errors when testing reload in E10S mode
// testReload().then(() =>
testAddIframe().then(() =>
testRemoveIframe()).then(() =>
finishTests(client));
}
@ -92,7 +95,7 @@ function markOutMatched(toBeEmptied, data, deleted) {
return;
}
ok(Object.keys(data).length,
"Atleast some storage types should be present in deleted");
"At least one storage type should be present");
for (let storageType in toBeEmptied) {
if (!data[storageType]) {
continue;
@ -121,54 +124,53 @@ function markOutMatched(toBeEmptied, data, deleted) {
}
}
function testReload() {
info("Testing if reload works properly");
// function testReload() {
// info("Testing if reload works properly");
let shouldBeEmptyFirst = Cu.cloneInto(beforeReload, {});
let shouldBeEmptyLast = Cu.cloneInto(beforeReload, {});
return new Promise(resolve => {
// let shouldBeEmptyFirst = Cu.cloneInto(beforeReload, {});
// let shouldBeEmptyLast = Cu.cloneInto(beforeReload, {});
// return new Promise(resolve => {
let onStoresUpdate = data => {
info("in stores update of testReload");
// This might be second time stores update is happening, in which case,
// data.deleted will be null.
// OR.. This might be the first time on a super slow machine where both
// data.deleted and data.added is missing in the first update.
if (data.deleted) {
markOutMatched(shouldBeEmptyFirst, data.deleted, true);
}
// let onStoresUpdate = data => {
// info("in stores update of testReload");
// // This might be second time stores update is happening, in which case,
// // data.deleted will be null.
// // OR.. This might be the first time on a super slow machine where both
// // data.deleted and data.added is missing in the first update.
// if (data.deleted) {
// markOutMatched(shouldBeEmptyFirst, data.deleted, true);
// }
if (!Object.keys(shouldBeEmptyFirst).length) {
info("shouldBeEmptyFirst is empty now");
}
// if (!Object.keys(shouldBeEmptyFirst).length) {
// info("shouldBeEmptyFirst is empty now");
// }
// stores-update call might not have data.added for the first time on slow
// machines, in which case, data.added will be null
if (data.added) {
markOutMatched(shouldBeEmptyLast, data.added);
}
// // stores-update call might not have data.added for the first time on
// // slow machines, in which case, data.added will be null
// if (data.added) {
// markOutMatched(shouldBeEmptyLast, data.added);
// }
if (!Object.keys(shouldBeEmptyLast).length) {
info("Everything to be received is received.");
endTestReloaded();
}
};
// if (!Object.keys(shouldBeEmptyLast).length) {
// info("Everything to be received is received.");
// endTestReloaded();
// }
// };
let endTestReloaded = () => {
gFront.off("stores-update", onStoresUpdate);
resolve();
};
// let endTestReloaded = () => {
// gFront.off("stores-update", onStoresUpdate);
// resolve();
// };
gFront.on("stores-update", onStoresUpdate);
// gFront.on("stores-update", onStoresUpdate);
content.location.reload();
});
}
// content.location.reload();
// });
// }
function testAddIframe() {
info("Testing if new iframe addition works properly");
return new Promise(resolve => {
let shouldBeEmpty = {
localStorage: {
"https://sectest1.example.org": ["iframe-s-ls1"]
@ -239,7 +241,6 @@ function testAddIframe() {
function testRemoveIframe() {
info("Testing if iframe removal works properly");
return new Promise(resolve => {
let shouldBeEmpty = {
localStorage: {
"http://sectest1.example.org": []

View File

@ -5,35 +5,173 @@
"use strict";
const {StorageFront} = require("devtools/server/actors/storage");
let gTests;
let gExpected;
let index = 0;
const beforeReload = {
cookies: ["test1.example.org", "sectest1.example.org"],
localStorage: ["http://test1.example.org", "http://sectest1.example.org"],
sessionStorage: ["http://test1.example.org", "http://sectest1.example.org"],
};
function finishTests(client) {
// Forcing GC/CC to get rid of docshells and windows created by this test.
forceCollections();
client.close(() => {
forceCollections();
DebuggerServer.destroy();
forceCollections();
gTests = null;
finish();
});
}
const TESTS = [
// index 0
{
action: function(win) {
info('win.addCookie("c1", "foobar1")');
win.addCookie("c1", "foobar1");
function markOutMatched(toBeEmptied, data, deleted) {
info('win.addCookie("c2", "foobar2")');
win.addCookie("c2", "foobar2");
info('win.localStorage.setItem("l1", "foobar1")');
win.localStorage.setItem("l1", "foobar1");
},
expected: {
added: {
cookies: {
"test1.example.org": ["c1", "c2"]
},
localStorage: {
"http://test1.example.org": ["l1"]
}
}
}
},
// index 1
{
action: function(win) {
info('win.addCookie("c1", "new_foobar1")');
win.addCookie("c1", "new_foobar1");
info('win.localStorage.setItem("l2", "foobar2")');
win.localStorage.setItem("l2", "foobar2");
},
expected: {
changed: {
cookies: {
"test1.example.org": ["c1"]
}
},
added: {
localStorage: {
"http://test1.example.org": ["l2"]
}
}
}
},
// index 2
{
action: function(win) {
info('win.removeCookie("c2")');
win.removeCookie("c2");
info('win.localStorage.removeItem("l1")');
win.localStorage.removeItem("l1");
info('win.localStorage.setItem("l3", "foobar3")');
win.localStorage.setItem("l3", "foobar3");
},
expected: {
deleted: {
cookies: {
"test1.example.org": ["c2"]
},
localStorage: {
"http://test1.example.org": ["l1"]
}
},
added: {
localStorage: {
"http://test1.example.org": ["l3"]
}
}
}
},
// index 3
{
action: function(win) {
info('win.removeCookie("c1")');
win.removeCookie("c1");
info('win.addCookie("c3", "foobar3")');
win.addCookie("c3", "foobar3");
info('win.localStorage.removeItem("l2")');
win.localStorage.removeItem("l2");
info('win.sessionStorage.setItem("s1", "foobar1")');
win.sessionStorage.setItem("s1", "foobar1");
info('win.sessionStorage.setItem("s2", "foobar2")');
win.sessionStorage.setItem("s2", "foobar2");
info('win.localStorage.setItem("l3", "new_foobar3")');
win.localStorage.setItem("l3", "new_foobar3");
},
expected: {
added: {
cookies: {
"test1.example.org": ["c3"]
},
sessionStorage: {
"http://test1.example.org": ["s1", "s2"]
}
},
changed: {
localStorage: {
"http://test1.example.org": ["l3"]
}
},
deleted: {
cookies: {
"test1.example.org": ["c1"]
},
localStorage: {
"http://test1.example.org": ["l2"]
}
}
}
},
// index 4
{
action: function(win) {
info('win.sessionStorage.removeItem("s1")');
win.sessionStorage.removeItem("s1");
},
expected: {
deleted: {
sessionStorage: {
"http://test1.example.org": ["s1"]
}
}
}
},
// index 5
{
action: function(win) {
info("win.clearCookies()");
win.clearCookies();
},
expected: {
deleted: {
cookies: {
"test1.example.org": ["c3"]
}
}
}
}
];
function markOutMatched(toBeEmptied, data) {
if (!Object.keys(toBeEmptied).length) {
info("Object empty");
return;
}
ok(Object.keys(data).length,
"Atleast some storage types should be present in deleted");
ok(Object.keys(data).length, "At least one storage type should be present");
for (let storageType in toBeEmptied) {
if (!data[storageType]) {
continue;
@ -59,185 +197,107 @@ function markOutMatched(toBeEmptied, data, deleted) {
}
}
function onStoresCleared(data) {
function onStoresUpdate(expected, {added, changed, deleted}, index) {
info("inside stores update for index " + index);
// Here, added, changed and deleted might be null even if they are required as
// per expected. This is fine as they might come in the next stores-update
// call or have already come in the previous one.
if (added) {
info("matching added object for index " + index);
markOutMatched(expected.added, added);
}
if (changed) {
info("matching changed object for index " + index);
markOutMatched(expected.changed, changed);
}
if (deleted) {
info("matching deleted object for index " + index);
markOutMatched(expected.deleted, deleted);
}
if ((!expected.added || !Object.keys(expected.added).length) &&
(!expected.changed || !Object.keys(expected.changed).length) &&
(!expected.deleted || !Object.keys(expected.deleted).length)) {
info("Everything expected has been received for index " + index);
} else {
info("Still some updates pending for index " + index);
}
}
function runTest({action, expected}, front, win, index) {
return new Promise(resolve => {
front.once("stores-update", function(addedChangedDeleted) {
onStoresUpdate(expected, addedChangedDeleted, index);
resolve();
});
info("Running test at index " + index);
action(win);
});
}
function* testClearLocalAndSessionStores(front, win) {
return new Promise(resolve => {
// We need to wait until we have received stores-cleared for both local and
// session storage.
let localStorage = false;
let sessionStorage = false;
front.on("stores-cleared", function onStoresCleared(data) {
storesCleared(data);
if (data.localStorage) {
localStorage = true;
}
if (data.sessionStorage) {
sessionStorage = true;
}
if (localStorage && sessionStorage) {
front.off("stores-cleared", onStoresCleared);
resolve();
}
});
win.clearLocalAndSessionStores();
});
}
function storesCleared(data) {
if (data.sessionStorage || data.localStorage) {
let hosts = data.sessionStorage || data.localStorage;
info("Stores cleared required for session storage");
is(hosts.length, 1, "number of hosts is 1");
is(hosts[0], "http://test1.example.org",
"host matches for " + Object.keys(data)[0]);
gTests.next();
}
else {
ok(false, "Stores cleared should only be for local and sesion storage");
}
}
function onStoresUpdate({added, changed, deleted}) {
info("inside stores update for index " + index);
// Here, added, changed and deleted might be null even if they are required as
// per gExpected. This is fine as they might come in the next stores-update
// call or have already come in the previous one.
if (added) {
info("matching added object for index " + index);
markOutMatched(gExpected.added, added);
}
if (changed) {
info("matching changed object for index " + index);
markOutMatched(gExpected.changed, changed);
}
if (deleted) {
info("matching deleted object for index " + index);
markOutMatched(gExpected.deleted, deleted);
}
if ((!gExpected.added || !Object.keys(gExpected.added).length) &&
(!gExpected.changed || !Object.keys(gExpected.changed).length) &&
(!gExpected.deleted || !Object.keys(gExpected.deleted).length)) {
info("Everything expected has been received for index " + index);
index++;
gTests.next();
}
else {
info("Still some updates pending for index " + index);
} else {
ok(false, "Stores cleared should only be for local and session storage");
}
}
function* UpdateTests(front, win, client) {
front.on("stores-update", onStoresUpdate);
// index 0
gExpected = {
added: {
cookies: {
"test1.example.org": ["c1", "c2"]
},
localStorage: {
"http://test1.example.org": ["l1"]
}
}
};
win.addCookie("c1", "foobar1");
win.addCookie("c2", "foobar2");
win.localStorage.setItem("l1", "foobar1");
yield undefined;
// index 1
gExpected = {
changed: {
cookies: {
"test1.example.org": ["c1"]
}
},
added: {
localStorage: {
"http://test1.example.org": ["l2"]
}
}
};
win.addCookie("c1", "new_foobar1");
win.localStorage.setItem("l2", "foobar2");
yield undefined;
// index 2
gExpected = {
deleted: {
cookies: {
"test1.example.org": ["c2"]
},
localStorage: {
"http://test1.example.org": ["l1"]
}
},
added: {
localStorage: {
"http://test1.example.org": ["l3"]
}
}
};
win.removeCookie("c2");
win.localStorage.removeItem("l1");
win.localStorage.setItem("l3", "foobar3");
yield undefined;
// index 3
gExpected = {
added: {
cookies: {
"test1.example.org": ["c3"]
},
sessionStorage: {
"http://test1.example.org": ["s1", "s2"]
}
},
changed: {
localStorage: {
"http://test1.example.org": ["l3"]
}
},
deleted: {
cookies: {
"test1.example.org": ["c1"]
},
localStorage: {
"http://test1.example.org": ["l2"]
}
}
};
win.removeCookie("c1");
win.addCookie("c3", "foobar3");
win.localStorage.removeItem("l2");
win.sessionStorage.setItem("s1", "foobar1");
win.sessionStorage.setItem("s2", "foobar2");
win.localStorage.setItem("l3", "new_foobar3");
yield undefined;
// index 4
gExpected = {
deleted: {
sessionStorage: {
"http://test1.example.org": ["s1"]
}
}
};
win.sessionStorage.removeItem("s1");
yield undefined;
// index 5
gExpected = {
deleted: {
cookies: {
"test1.example.org": ["c3"]
}
}
};
front.on("stores-cleared", onStoresCleared);
win.clear();
yield undefined;
// Another 2 more yield undefined s so as to wait for the "stores-cleared" to
// fire. One for Local Storage and other for Session Storage
yield undefined;
yield undefined;
front.off("stores-cleared", onStoresCleared);
front.off("stores-update", onStoresUpdate);
finishTests(client);
function* finishTests(client) {
yield client.close();
DebuggerServer.destroy();
finish();
}
add_task(function*() {
let doc = yield addTab(MAIN_DOMAIN + "storage-updates.html");
function test() {
addTab(MAIN_DOMAIN + "storage-updates.html").then(function(doc) {
initDebuggerServer();
initDebuggerServer();
let client = new DebuggerClient(DebuggerServer.connectPipe());
connectDebuggerClient(client).then(form => {
let front = StorageFront(client, form);
gTests = UpdateTests(front, doc.defaultView.wrappedJSObject,
client);
// Make an initial call to initialize the actor
front.listStores().then(() => gTests.next());
});
})
}
let client = new DebuggerClient(DebuggerServer.connectPipe());
let form = yield connectDebuggerClient(client);
let front = StorageFront(client, form);
let win = doc.defaultView.wrappedJSObject;
yield front.listStores();
for (let i = 0; i < TESTS.length; i++) {
let test = TESTS[i];
yield runTest(test, front, win, i);
}
yield testClearLocalAndSessionStores(front, win);
yield finishTests(client);
});

View File

@ -82,12 +82,15 @@ window.clear = function*(callback) {
document.cookie = "c1=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
document.cookie = "c3=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
document.cookie = "cs2=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
localStorage.clear();
indexedDB.deleteDatabase("idb1").onsuccess = successClear;
yield undefined;
indexedDB.deleteDatabase("idb2").onsuccess = successClear;
yield undefined;
console.log("removed cookies and stuff from main page");
dump("removed cookies, localStorage and indexedDB data from " +
document.location + "\n");
callback();
};
</script>

View File

@ -70,9 +70,10 @@ window.idbGenerator = function*(callback) {
let db2 = event.target.result;
let store3 = db2.createObjectStore("obj3", { keyPath: "id3" });
store3.createIndex("name2", "name2", { unique: true });
yield undefined;
db2.close();
console.log("added cookies and stuff from main page");
dump("added cookies and stuff from main page\n");
callback();
};
@ -81,10 +82,16 @@ function successClear(event) {
}
window.clear = function*(callback) {
document.cookie = "c1=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
document.cookie = "c3=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
document.cookie = "cs2=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
document.cookie = "c1=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/browser";
document.cookie =
"c3=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; secure=true";
document.cookie =
"cs2=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=" +
partialHostname;
localStorage.clear();
sessionStorage.clear();
indexedDB.deleteDatabase("idb1").onsuccess = successClear;
yield undefined;
indexedDB.deleteDatabase("idb2").onsuccess = successClear;

View File

@ -31,14 +31,17 @@ window.removeCookie = function(name) {
document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT";
};
window.clear = function() {
var cookies = document.cookie;
for (var cookie of cookies.split(";")) {
removeCookie(cookie.split("=")[0]);
}
window.clearLocalAndSessionStores = function() {
localStorage.clear();
sessionStorage.clear();
};
window.clearCookies = function() {
let cookies = document.cookie;
for (let cookie of cookies.split(";")) {
removeCookie(cookie.split("=")[0]);
}
};
</script>
</body>
</html>