Attachment #8845251: Bug 1286717 - Part 2: Add mochitests for persist/persisted functions for bug #1286717

View | Details | Raw Unified | Return to bug 1286717
Collapse All | Expand All

(-)a/dom/quota/moz.build (+4 lines)
Line     Link Here 
 Lines 2-17    Link Here 
2
# vim: set filetype=python:
2
# vim: set filetype=python:
3
# This Source Code Form is subject to the terms of the Mozilla Public
3
# This Source Code Form is subject to the terms of the Mozilla Public
4
# License, v. 2.0. If a copy of the MPL was not distributed with this
4
# License, v. 2.0. If a copy of the MPL was not distributed with this
5
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
6
7
with Files("**"):
7
with Files("**"):
8
    BUG_COMPONENT = ("Core", "DOM: Quota Manager")
8
    BUG_COMPONENT = ("Core", "DOM: Quota Manager")
9
9
10
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
11
12
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
13
10
XPCSHELL_TESTS_MANIFESTS += [
14
XPCSHELL_TESTS_MANIFESTS += [
11
    'test/unit/xpcshell.ini'
15
    'test/unit/xpcshell.ini'
12
]
16
]
13
17
14
XPIDL_SOURCES += [
18
XPIDL_SOURCES += [
15
    'nsIQuotaCallbacks.idl',
19
    'nsIQuotaCallbacks.idl',
16
    'nsIQuotaManagerService.idl',
20
    'nsIQuotaManagerService.idl',
17
    'nsIQuotaRequests.idl',
21
    'nsIQuotaRequests.idl',
(-)a/dom/quota/test/browser.ini (+9 lines)
Line     Link Here 
Line 0    Link Here 
1
[DEFAULT]
2
skip-if = (buildapp != "browser")
3
support-files =
4
  head.js
5
  browserHelpers.js
6
  browser_permissionsPrompt.html
7
8
[browser_permissionsPromptAllow.js]
9
[browser_permissionsPromptDeny.js]
(-)a/dom/quota/test/browserHelpers.js (+45 lines)
Line     Link Here 
Line 0    Link Here 
1
/**
2
 * Any copyright is dedicated to the Public Domain.
3
 * http://creativecommons.org/publicdomain/zero/1.0/
4
 */
5
6
var testGenerator = testSteps();
7
8
var testResult;
9
var testException;
10
11
function clearAllDatabases(callback) {
12
  let qms = SpecialPowers.Services.qms;
13
  let principal = SpecialPowers.wrap(document).nodePrincipal;
14
  let request = qms.clearStoragesForPrincipal(principal);
15
  let cb = SpecialPowers.wrapCallback(callback);
16
  request.callback = cb;
17
}
18
19
function runTest()
20
{
21
  testGenerator.next();
22
}
23
24
function continueToNextStep()
25
{
26
  SimpleTest.executeSoon(function() {
27
    testGenerator.next();
28
  });
29
}
30
31
function finishTestNow()
32
{
33
  if (testGenerator) {
34
    testGenerator.return();
35
    testGenerator = undefined;
36
  }
37
}
38
39
function finishTest()
40
{
41
  setTimeout(finishTestNow, 0);
42
  setTimeout(() => {
43
    window.parent.postMessage(testResult, "*");
44
  }, 0);
45
}
(-)a/dom/quota/test/browser_permissionsPrompt.html (+49 lines)
Line     Link Here 
Line 0    Link Here 
1
<!--
2
  Any copyright is dedicated to the Public Domain.
3
  http://creativecommons.org/publicdomain/zero/1.0/
4
-->
5
<html>
6
  <head>
7
    <meta charset=UTF-8>
8
    <title>Persistent-Storage Permission Prompt Test</title>
9
    <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
10
11
    <script type="text/javascript;version=1.7">
12
      function* testSteps()
13
      {
14
        SpecialPowers.pushPrefEnv({
15
          "set": [["dom.storageManager.enabled", true],
16
                  ["dom.storageManager.prompt.testing", false],
17
                  ["dom.storageManager.prompt.testing.allow", false]]
18
        }, continueToNextStep);
19
        yield undefined;
20
21
        clearAllDatabases(continueToNextStep);
22
        yield undefined;
23
24
        navigator.storage.persist().then(result => {
25
          testGenerator.next(result);
26
        });
27
        testResult  = yield undefined;
28
29
        info("Persist() result: " + testResult);
30
31
        navigator.storage.persisted().then(result => {
32
          testGenerator.next(result);
33
        });
34
        let persistedResult  = yield undefined;
35
36
        info("Persisted() result: " + persistedResult);
37
38
        is(testResult, persistedResult, "persist/persisted results shall be consistent");
39
40
        finishTest();
41
      }
42
    </script>
43
44
    <script type="text/javascript;version=1.7" src="browserHelpers.js"></script>
45
  </head>
46
47
  <body onload="runTest();" onunload="finishTestNow();"></body>
48
49
</html>
(-)a/dom/quota/test/browser_permissionsPromptAllow.js (+99 lines)
Line     Link Here 
Line 0    Link Here 
1
/**
2
 * Any copyright is dedicated to the Public Domain.
3
 * http://creativecommons.org/publicdomain/zero/1.0/
4
 */
5
6
const testPageURL = "https://example.com/browser/" +
7
  "dom/quota/test/browser_permissionsPrompt.html";
8
9
add_task(function* testPermissionAllow() {
10
  info("Creating tab");
11
  gBrowser.selectedTab = gBrowser.addTab();
12
13
  info("Loading test page: " + testPageURL);
14
  gBrowser.selectedBrowser.loadURI(testPageURL);
15
  yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
16
17
  registerPopupEventHandler("popupshowing", function () {
18
    ok(true, "prompt showing");
19
  });
20
  registerPopupEventHandler("popupshown", function () {
21
    ok(true, "prompt shown");
22
    triggerMainCommand(this);
23
  });
24
  registerPopupEventHandler("popuphidden", function () {
25
    ok(true, "prompt hidden");
26
  });
27
28
  yield promiseMessage(true, gBrowser);
29
30
  is(getPermission(testPageURL, "persistent-storage"),
31
     Components.interfaces.nsIPermissionManager.ALLOW_ACTION,
32
     "Correct permission set");
33
  gBrowser.removeCurrentTab();
34
  // Keep persistent-storage permission for the next test.
35
  unregisterAllPopupEventHandlers();
36
});
37
38
add_task(function* testPermissionAllowInPrivateWindow() {
39
  info("Creating private window");
40
  let win = yield BrowserTestUtils.openNewBrowserWindow({ private : true });
41
42
  info("Creating private tab");
43
  win.gBrowser.selectedTab = win.gBrowser.addTab();
44
45
  info("Loading test page: " + testPageURL);
46
  win.gBrowser.selectedBrowser.loadURI(testPageURL);
47
  yield BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
48
49
  // PermissionManager is not supposed to have any knowledge of private browsing,
50
  // Prompt shall not be displayed.
51
  registerPopupEventHandler("popupshowing", function () {
52
    ok(false, "Shouldn't show a popup this time");
53
  });
54
  registerPopupEventHandler("popupshown", function () {
55
    ok(false, "Shouldn't show a popup this time");
56
  });
57
  registerPopupEventHandler("popuphidden", function () {
58
    ok(false, "Shouldn't show a popup this time");
59
  });
60
61
  yield promiseMessage(true, win.gBrowser);
62
63
  is(getPermission(testPageURL, "persistent-storage"),
64
     Components.interfaces.nsIPermissionManager.ALLOW_ACTION,
65
     "Correct permission set");
66
  unregisterAllPopupEventHandlers();
67
  removePermission(testPageURL, "persistent-storage");
68
  win.gBrowser.removeCurrentTab();
69
  win.close();
70
});
71
72
add_task(function* testPermissionAllow() {
73
  info("Creating tab");
74
  gBrowser.selectedTab = gBrowser.addTab();
75
76
  info("Loading test page: " + testPageURL);
77
  gBrowser.selectedBrowser.loadURI(testPageURL);
78
  yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
79
80
  registerPopupEventHandler("popupshowing", function () {
81
    ok(true, "prompt showing");
82
  });
83
  registerPopupEventHandler("popupshown", function () {
84
    ok(true, "prompt shown");
85
    triggerMainCommand(this);
86
  });
87
  registerPopupEventHandler("popuphidden", function () {
88
    ok(true, "prompt hidden");
89
  });
90
91
  yield promiseMessage(true, gBrowser);
92
93
  is(getPermission(testPageURL, "persistent-storage"),
94
     Components.interfaces.nsIPermissionManager.ALLOW_ACTION,
95
     "Correct permission set");
96
  gBrowser.removeCurrentTab();
97
  unregisterAllPopupEventHandlers();
98
  removePermission(testPageURL, "persistent-storage");
99
});
(-)a/dom/quota/test/browser_permissionsPromptDeny.js (+97 lines)
Line     Link Here 
Line 0    Link Here 
1
/**
2
 * Any copyright is dedicated to the Public Domain.
3
 * http://creativecommons.org/publicdomain/zero/1.0/
4
 */
5
6
const testPageURL = "https://example.com/browser/" +
7
  "dom/quota/test/browser_permissionsPrompt.html";
8
9
add_task(function* testPermissionDenied() {
10
  info("Creating tab");
11
  gBrowser.selectedTab = gBrowser.addTab();
12
13
  info("Loading test page: " + testPageURL);
14
  gBrowser.selectedBrowser.loadURI(testPageURL);
15
  yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
16
17
  registerPopupEventHandler("popupshowing", function () {
18
    ok(true, "prompt showing");
19
  });
20
  registerPopupEventHandler("popupshown", function () {
21
    ok(true, "prompt shown");
22
    triggerSecondaryCommand(this);
23
  });
24
  registerPopupEventHandler("popuphidden", function () {
25
    ok(true, "prompt hidden");
26
  });
27
28
  yield promiseMessage(false, gBrowser);
29
30
  is(getPermission(testPageURL, "persistent-storage"),
31
     Components.interfaces.nsIPermissionManager.DENY_ACTION,
32
     "Correct permission set");
33
  gBrowser.removeCurrentTab();
34
  unregisterAllPopupEventHandlers();
35
});
36
37
add_task(function* testPermissionDeniedInPrivateWindow() {
38
  info("Creating private window");
39
  let win = yield BrowserTestUtils.openNewBrowserWindow({ private : true });
40
41
  info("Creating private tab");
42
  win.gBrowser.selectedTab = win.gBrowser.addTab();
43
44
  info("Loading test page: " + testPageURL);
45
  win.gBrowser.selectedBrowser.loadURI(testPageURL);
46
  yield BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
47
48
  // PermissionManager is not supposed to have any knowledge of private browsing,
49
  // Prompt shall not be displayed.
50
  registerPopupEventHandler("popupshowing", function () {
51
    ok(false, "Shouldn't show a popup this time");
52
  });
53
  registerPopupEventHandler("popupshown", function () {
54
    ok(false, "Shouldn't show a popup this time");
55
  });
56
  registerPopupEventHandler("popuphidden", function () {
57
    ok(false, "Shouldn't show a popup this time");
58
  });
59
  yield promiseMessage(false, win.gBrowser);
60
61
  is(getPermission(testPageURL, "persistent-storage"),
62
     Components.interfaces.nsIPermissionManager.DENY_ACTION,
63
     "Correct permission set");
64
  unregisterAllPopupEventHandlers();
65
  win.gBrowser.removeCurrentTab();
66
  win.close();
67
});
68
69
add_task(function* testPermissionDeniedDismiss() {
70
  info("Creating tab");
71
  gBrowser.selectedTab = gBrowser.addTab();
72
73
  info("Loading test page: " + testPageURL);
74
  gBrowser.selectedBrowser.loadURI(testPageURL);
75
  yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
76
77
  registerPopupEventHandler("popupshowing", function () {
78
    ok(true, "prompt showing");
79
  });
80
  registerPopupEventHandler("popupshown", function () {
81
    ok(true, "prompt shown");
82
    // Dismiss permission prompt.
83
    dismissNotification(this);
84
  });
85
  registerPopupEventHandler("popuphidden", function () {
86
    ok(true, "prompt hidden");
87
  });
88
89
  yield promiseMessage(false, gBrowser);
90
91
  is(getPermission(testPageURL, "persistent-storage"),
92
     Components.interfaces.nsIPermissionManager.DENY_ACTION,
93
     "Correct permission set");
94
  gBrowser.removeCurrentTab();
95
  unregisterAllPopupEventHandlers();
96
  removePermission(testPageURL, "persistent-storage");
97
});
(-)a/dom/quota/test/head.js (+126 lines)
Line     Link Here 
Line 0    Link Here 
1
/**
2
 * Any copyright is dedicated to the Public Domain.
3
 * http://creativecommons.org/publicdomain/zero/1.0/
4
 */
5
6
var gActiveListeners = {};
7
8
function registerPopupEventHandler(eventName, callback)
9
{
10
  gActiveListeners[eventName] = function (event) {
11
    if (event.target != PopupNotifications.panel)
12
      return;
13
    PopupNotifications.panel.removeEventListener(eventName,
14
                                                 gActiveListeners[eventName]);
15
    delete gActiveListeners[eventName];
16
17
    callback.call(PopupNotifications.panel);
18
  }
19
  PopupNotifications.panel.addEventListener(eventName,
20
                                            gActiveListeners[eventName]);
21
}
22
23
function unregisterPopupEventHandler(eventName)
24
{
25
  PopupNotifications.panel.removeEventListener(eventName,
26
                                               gActiveListeners[eventName]);
27
  delete gActiveListeners[eventName];
28
}
29
30
function unregisterAllPopupEventHandlers()
31
{
32
  for (let eventName in gActiveListeners) {
33
    PopupNotifications.panel.removeEventListener(eventName,
34
                                                 gActiveListeners[eventName]);
35
  }
36
  gActiveListeners = {};
37
}
38
39
function triggerMainCommand(popup)
40
{
41
  info("triggering main command");
42
  let notifications = popup.childNodes;
43
  ok(notifications.length > 0, "at least one notification displayed");
44
  let notification = notifications[0];
45
  info("triggering command: " + notification.getAttribute("buttonlabel"));
46
47
  EventUtils.synthesizeMouseAtCenter(notification.button, {});
48
}
49
50
function triggerSecondaryCommand(popup)
51
{
52
  info("triggering secondary command");
53
  let notifications = popup.childNodes;
54
  ok(notifications.length > 0, "at least one notification displayed");
55
  let notification = notifications[0];
56
  EventUtils.synthesizeMouseAtCenter(notification.secondaryButton, {});
57
}
58
59
function dismissNotification(popup)
60
{
61
  info("dismissing notification");
62
  executeSoon(function () {
63
    EventUtils.synthesizeKey("VK_ESCAPE", {});
64
  });
65
}
66
67
function setPermission(url, permission)
68
{
69
  const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
70
71
  let uri = Components.classes["@mozilla.org/network/io-service;1"]
72
                      .getService(Components.interfaces.nsIIOService)
73
                      .newURI(url);
74
  let ssm = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
75
                      .getService(Ci.nsIScriptSecurityManager);
76
  let principal = ssm.createCodebasePrincipal(uri, {});
77
78
  Components.classes["@mozilla.org/permissionmanager;1"]
79
            .getService(nsIPermissionManager)
80
            .addFromPrincipal(principal, permission,
81
                              nsIPermissionManager.ALLOW_ACTION);
82
}
83
84
function removePermission(url, permission)
85
{
86
  let uri = Components.classes["@mozilla.org/network/io-service;1"]
87
                      .getService(Components.interfaces.nsIIOService)
88
                      .newURI(url);
89
  let ssm = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
90
                      .getService(Ci.nsIScriptSecurityManager);
91
  let principal = ssm.createCodebasePrincipal(uri, {});
92
93
  Components.classes["@mozilla.org/permissionmanager;1"]
94
            .getService(Components.interfaces.nsIPermissionManager)
95
            .removeFromPrincipal(principal, permission);
96
}
97
98
function getPermission(url, permission)
99
{
100
  let uri = Components.classes["@mozilla.org/network/io-service;1"]
101
                      .getService(Components.interfaces.nsIIOService)
102
                      .newURI(url);
103
  let ssm = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
104
                      .getService(Ci.nsIScriptSecurityManager);
105
  let principal = ssm.createCodebasePrincipal(uri, {});
106
107
  return Components.classes["@mozilla.org/permissionmanager;1"]
108
                   .getService(Components.interfaces.nsIPermissionManager)
109
                   .testPermissionFromPrincipal(principal, permission);
110
}
111
112
function promiseMessage(aMessage, browser)
113
{
114
  return ContentTask.spawn(browser.selectedBrowser, aMessage, function* (aMessage) {
115
    yield new Promise((resolve, reject) => {
116
      content.addEventListener("message", function messageListener(event) {
117
        content.removeEventListener("message", messageListener);
118
        is(event.data, aMessage, "received " + aMessage);
119
        if (event.data == aMessage)
120
          resolve();
121
        else
122
          reject();
123
      });
124
    });
125
  });
126
}
(-)a/dom/quota/test/helpers.js (+431 lines)
Line     Link Here 
Line 0    Link Here 
1
/**
2
 * Any copyright is dedicated to the Public Domain.
3
 * http://creativecommons.org/publicdomain/zero/1.0/
4
 */
5
6
var testGenerator = testSteps();
7
8
// The test js is shared between xpcshell (which has no SpecialPowers object)
9
// and content mochitests (where the |Components| object is accessible only as
10
// SpecialPowers.Components). Expose Components if necessary here to make things
11
// work everywhere.
12
//
13
// Even if the real |Components| doesn't exist, we might shim in a simple JS
14
// placebo for compat. An easy way to differentiate this from the real thing
15
// is whether the property is read-only or not.
16
var c = Object.getOwnPropertyDescriptor(this, 'Components');
17
if ((!c.value || c.writable) && typeof SpecialPowers === 'object')
18
  Components = SpecialPowers.Components;
19
20
function executeSoon(aFun)
21
{
22
  let comp = SpecialPowers.wrap(Components);
23
24
  let thread = comp.classes["@mozilla.org/thread-manager;1"]
25
                   .getService(comp.interfaces.nsIThreadManager)
26
                   .mainThread;
27
28
  thread.dispatch({
29
    run: function() {
30
      aFun();
31
    }
32
  }, Components.interfaces.nsIThread.DISPATCH_NORMAL);
33
}
34
35
function clearAllDatabases(callback) {
36
  let qms = SpecialPowers.Services.qms;
37
  let principal = SpecialPowers.wrap(document).nodePrincipal;
38
  let request = qms.clearStoragesForPrincipal(principal);
39
  let cb = SpecialPowers.wrapCallback(callback);
40
  request.callback = cb;
41
}
42
43
var testHarnessGenerator = testHarnessSteps();
44
testHarnessGenerator.next();
45
46
function testHarnessSteps() {
47
  function nextTestHarnessStep(val) {
48
    testHarnessGenerator.next(val);
49
  }
50
51
  let testScriptPath;
52
  let testScriptFilename;
53
54
  let scripts = document.getElementsByTagName("script");
55
  for (let i = 0; i < scripts.length; i++) {
56
    let src = scripts[i].src;
57
    let match = src.match(/quota\/test\/(test_[^\/]+\.js)$/);
58
    if (match && match.length == 2) {
59
      testScriptPath = src;
60
      testScriptFilename = match[1];
61
      break;
62
    }
63
  }
64
65
  yield undefined;
66
67
  info("Clearing old databases");
68
69
  clearAllDatabases(nextTestHarnessStep);
70
  yield undefined;
71
72
  info("Running" +
73
       (testScriptFilename ? " '" + testScriptFilename + "'" : ""));
74
75
  if (testScriptFilename && !window.disableWorkerTest) {
76
    info("Running test in a worker");
77
78
    let workerScriptBlob =
79
      new Blob([ "(" + workerScript.toString() + ")();" ],
80
               { type: "text/javascript;version=1.7" });
81
    let workerScriptURL = URL.createObjectURL(workerScriptBlob);
82
83
    let worker = new Worker(workerScriptURL);
84
85
    worker._expectingUncaughtException = false;
86
    worker.onerror = function(event) {
87
      if (worker._expectingUncaughtException) {
88
        ok(true, "Worker had an expected error: " + event.message);
89
        worker._expectingUncaughtException = false;
90
        event.preventDefault();
91
        return;
92
      }
93
      ok(false, "Worker had an error: " + event.message);
94
      worker.terminate();
95
      nextTestHarnessStep();
96
    };
97
98
    worker.onmessage = function(event) {
99
      let message = event.data;
100
      switch (message.op) {
101
        case "ok":
102
          ok(message.condition, message.name, message.diag);
103
          break;
104
105
        case "todo":
106
          todo(message.condition, message.name, message.diag);
107
          break;
108
109
        case "info":
110
          info(message.msg);
111
          break;
112
113
        case "ready":
114
          worker.postMessage({ op: "load", files: [ testScriptPath ] });
115
          break;
116
117
        case "loaded":
118
          worker.postMessage({ op: "start" });
119
          break;
120
121
        case "done":
122
          ok(true, "Worker finished");
123
          nextTestHarnessStep();
124
          break;
125
126
        case "expectUncaughtException":
127
          worker._expectingUncaughtException = message.expecting;
128
          break;
129
130
	case "clearAllDatabases":
131
          clearAllDatabases(function(){
132
            worker.postMessage({ op: "clearAllDatabasesDone" });
133
          });
134
          break;
135
136
        default:
137
          ok(false,
138
             "Received a bad message from worker: " + JSON.stringify(message));
139
          nextTestHarnessStep();
140
      }
141
    };
142
143
    URL.revokeObjectURL(workerScriptURL);
144
145
    yield undefined;
146
147
    if (worker._expectingUncaughtException) {
148
      ok(false, "expectUncaughtException was called but no uncaught " +
149
                "exception was detected!");
150
    }
151
152
    worker.terminate();
153
    worker = null;
154
155
    clearAllDatabases(nextTestHarnessStep);
156
    yield undefined;
157
  } else if (testScriptFilename) {
158
    todo(false,
159
         "Skipping test in a worker because it is explicitly disabled: " +
160
         disableWorkerTest);
161
  } else {
162
    todo(false,
163
         "Skipping test in a worker because it's not structured properly");
164
  }
165
166
  info("Running test in main thread");
167
168
  // Now run the test script in the main thread.
169
  testGenerator.next();
170
171
  yield undefined;
172
}
173
174
if (!window.runTest) {
175
  window.runTest = function()
176
  {
177
    SimpleTest.waitForExplicitFinish();
178
    testHarnessGenerator.next();
179
  }
180
}
181
182
function finishTest()
183
{
184
  SpecialPowers.notifyObserversInParentProcess(null,
185
                                               "disk-space-watcher",
186
                                               "free");
187
188
  SimpleTest.executeSoon(function() {
189
    clearAllDatabases(function() { SimpleTest.finish(); });
190
  });
191
}
192
193
function continueToNextStep()
194
{
195
  SimpleTest.executeSoon(function() {
196
    testGenerator.next();
197
  });
198
}
199
200
function continueToNextStepSync()
201
{
202
  testGenerator.next();
203
}
204
205
function errorHandler(event)
206
{
207
  ok(false, "error, '" + event.target.error.name + "'");
208
  finishTest();
209
}
210
211
function expectUncaughtException(expecting)
212
{
213
  SimpleTest.expectUncaughtException(expecting);
214
}
215
216
function unexpectedSuccessHandler()
217
{
218
  ok(false, "Got success, but did not expect it!");
219
  finishTest();
220
}
221
222
function expectedErrorHandler(name)
223
{
224
  return function(event) {
225
    is(event.type, "error", "Got an error event");
226
    is(event.target.error.name, name, "Expected error was thrown.");
227
    event.preventDefault();
228
    grabEventAndContinueHandler(event);
229
  };
230
}
231
232
function ExpectError(name, preventDefault)
233
{
234
  this._name = name;
235
  this._preventDefault = preventDefault;
236
}
237
ExpectError.prototype = {
238
  handleEvent: function(event)
239
  {
240
    is(event.type, "error", "Got an error event");
241
    is(event.target.error.name, this._name, "Expected error was thrown.");
242
    if (this._preventDefault) {
243
      event.preventDefault();
244
      event.stopPropagation();
245
    }
246
    grabEventAndContinueHandler(event);
247
  }
248
};
249
250
function workerScript() {
251
  "use strict";
252
253
  self.repr = function(_thing_) {
254
    if (typeof(_thing_) == "undefined") {
255
      return "undefined";
256
    }
257
258
    let str;
259
260
    try {
261
      str = _thing_ + "";
262
    } catch (e) {
263
      return "[" + typeof(_thing_) + "]";
264
    }
265
266
    if (typeof(_thing_) == "function") {
267
      str = str.replace(/^\s+/, "");
268
      let idx = str.indexOf("{");
269
      if (idx != -1) {
270
        str = str.substr(0, idx) + "{...}";
271
      }
272
    }
273
274
    return str;
275
  };
276
277
  self.ok = function(_condition_, _name_, _diag_) {
278
    self.postMessage({ op: "ok",
279
                       condition: !!_condition_,
280
                       name: _name_,
281
                       diag: _diag_ });
282
  };
283
284
  self.is = function(_a_, _b_, _name_) {
285
    let pass = (_a_ == _b_);
286
    let diag = pass ? "" : "got " + repr(_a_) + ", expected " + repr(_b_);
287
    ok(pass, _name_, diag);
288
  };
289
290
  self.isnot = function(_a_, _b_, _name_) {
291
    let pass = (_a_ != _b_);
292
    let diag = pass ? "" : "didn't expect " + repr(_a_) + ", but got it";
293
    ok(pass, _name_, diag);
294
  };
295
296
  self.todo = function(_condition_, _name_, _diag_) {
297
    self.postMessage({ op: "todo",
298
                       condition: !!_condition_,
299
                       name: _name_,
300
                       diag: _diag_ });
301
  };
302
303
  self.info = function(_msg_) {
304
    self.postMessage({ op: "info", msg: _msg_ });
305
  };
306
307
  self.executeSoon = function(_fun_) {
308
    var channel = new MessageChannel();
309
    channel.port1.postMessage("");
310
    channel.port2.onmessage = function(event) { _fun_(); };
311
  };
312
313
  self.finishTest = function() {
314
    if (self._expectingUncaughtException) {
315
      self.ok(false, "expectUncaughtException was called but no uncaught "
316
                     + "exception was detected!");
317
    }
318
    self.postMessage({ op: "done" });
319
  };
320
321
  self.grabEventAndContinueHandler = function(_event_) {
322
    testGenerator.next(_event_);
323
  };
324
325
  self.continueToNextStep = function() {
326
    executeSoon(function() {
327
      testGenerator.next();
328
    });
329
  };
330
331
  self.continueToNextStepSync = function() {
332
    testGenerator.next();
333
  };
334
335
  self.errorHandler = function(_event_) {
336
    ok(false, "error, '" + _event_.target.error.name + "'");
337
    finishTest();
338
  };
339
340
  self.unexpectedSuccessHandler = function()
341
  {
342
    ok(false, "Got success, but did not expect it!");
343
    finishTest();
344
  };
345
346
  self.expectedErrorHandler = function(_name_)
347
  {
348
    return function(_event_) {
349
      is(_event_.type, "error", "Got an error event");
350
      is(_event_.target.error.name, _name_, "Expected error was thrown.");
351
      _event_.preventDefault();
352
      grabEventAndContinueHandler(_event_);
353
    };
354
  };
355
356
  self.ExpectError = function(_name_, _preventDefault_)
357
  {
358
    this._name = _name_;
359
    this._preventDefault = _preventDefault_;
360
  }
361
  self.ExpectError.prototype = {
362
    handleEvent: function(_event_)
363
    {
364
      is(_event_.type, "error", "Got an error event");
365
      is(_event_.target.error.name, this._name, "Expected error was thrown.");
366
      if (this._preventDefault) {
367
        _event_.preventDefault();
368
        _event_.stopPropagation();
369
      }
370
      grabEventAndContinueHandler(_event_);
371
    }
372
  };
373
374
  self._expectingUncaughtException = false;
375
  self.expectUncaughtException = function(_expecting_) {
376
    self._expectingUncaughtException = !!_expecting_;
377
    self.postMessage({ op: "expectUncaughtException", expecting: !!_expecting_ });
378
  };
379
380
  self._clearAllDatabasesCallback = undefined;
381
  self.clearAllDatabases = function(_callback_) {
382
    self._clearAllDatabasesCallback = _callback_;
383
    self.postMessage({ op: "clearAllDatabases" });
384
  }
385
386
  self.onerror = function(_message_, _file_, _line_) {
387
    if (self._expectingUncaughtException) {
388
      self._expectingUncaughtException = false;
389
      ok(true, "Worker: expected exception [" + _file_ + ":" + _line_ + "]: '" +
390
         _message_ + "'");
391
      return;
392
    }
393
    ok(false,
394
       "Worker: uncaught exception [" + _file_ + ":" + _line_ + "]: '" +
395
         _message_ + "'");
396
    self.finishTest();
397
    self.close();
398
    return true;
399
  };
400
401
  self.onmessage = function(_event_) {
402
    let message = _event_.data;
403
    switch (message.op) {
404
      case "load":
405
        info("Worker: loading " + JSON.stringify(message.files));
406
        self.importScripts(message.files);
407
        self.postMessage({ op: "loaded" });
408
        break;
409
410
      case "start":
411
        executeSoon(function() {
412
          info("Worker: starting tests");
413
          testGenerator.next();
414
        });
415
        break;
416
417
      case "clearAllDatabasesDone":
418
        info("Worker: all databases are cleared");
419
        if (self._clearAllDatabasesCallback) {
420
          self._clearAllDatabasesCallback();
421
        }
422
        break;
423
424
      default:
425
        throw new Error("Received a bad message from parent: " +
426
                        JSON.stringify(message));
427
    }
428
  };
429
430
  self.postMessage({ op: "ready" });
431
}
(-)a/dom/quota/test/mochitest.ini (+14 lines)
Line     Link Here 
Line 0    Link Here 
1
# This Source Code Form is subject to the terms of the Mozilla Public
2
# License, v. 2.0. If a copy of the MPL was not distributed with this
3
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5
[DEFAULT]
6
support-files =
7
  helpers.js
8
  test_storage_manager_persist_allow.js
9
  test_storage_manager_persist_deny.js
10
11
[test_storage_manager_persist_allow.html]
12
scheme=https
13
[test_storage_manager_persist_deny.html]
14
scheme=https
(-)a/dom/quota/test/test_storage_manager_persist_allow.html (+19 lines)
Line     Link Here 
Line 0    Link Here 
1
<!--
2
  Any copyright is dedicated to the Public Domain.
3
  http://creativecommons.org/publicdomain/zero/1.0/
4
-->
5
<html>
6
<head>
7
  <title>Allow Persist Prompt for StorageManager</title>
8
9
  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
10
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
11
12
  <script type="text/javascript;version=1.7" src="test_storage_manager_persist_allow.js"></script>
13
  <script type="text/javascript;version=1.7" src="helpers.js"></script>
14
15
</head>
16
17
<body onload="runTest();"></body>
18
19
</html>
(-)a/dom/quota/test/test_storage_manager_persist_allow.js (+28 lines)
Line     Link Here 
Line 0    Link Here 
1
var disableWorkerTest = "Persist doesn't work in workers";
2
var testGenerator = testSteps();
3
4
function* testSteps()
5
{
6
  SpecialPowers.pushPrefEnv({
7
    "set": [["dom.storageManager.enabled", true],
8
            ["dom.storageManager.prompt.testing", true],
9
            ["dom.storageManager.prompt.testing.allow", true]]
10
  }, continueToNextStep);
11
  yield undefined;
12
13
  navigator.storage.persist().then(result => {
14
    testGenerator.next(result);
15
  });
16
  let persistResult  = yield undefined;
17
18
  is(persistResult, true, "persist successfully");
19
20
  navigator.storage.persisted().then(result => {
21
    testGenerator.next(result);
22
  });
23
  let persistedResult  = yield undefined;
24
25
  is(persistResult, persistedResult, "persist/persisted results shall be consistent");
26
27
  finishTest();
28
}
(-)a/dom/quota/test/test_storage_manager_persist_deny.html (+19 lines)
Line     Link Here 
Line 0    Link Here 
1
<!--
2
  Any copyright is dedicated to the Public Domain.
3
  http://creativecommons.org/publicdomain/zero/1.0/
4
-->
5
<html>
6
<head>
7
  <title>Deny Persist Prompt for StorageManager</title>
8
9
  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
10
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
11
12
  <script type="text/javascript;version=1.7" src="test_storage_manager_persist_deny.js"></script>
13
  <script type="text/javascript;version=1.7" src="helpers.js"></script>
14
15
</head>
16
17
<body onload="runTest();"></body>
18
19
</html>
(-)a/dom/quota/test/test_storage_manager_persist_deny.js (+28 lines)
Line     Link Here 
Line 0    Link Here 
1
var disableWorkerTest = "Persist doesn't work in workers";
2
var testGenerator = testSteps();
3
4
function* testSteps()
5
{
6
  SpecialPowers.pushPrefEnv({
7
    "set": [["dom.storageManager.enabled", true],
8
            ["dom.storageManager.prompt.testing", true],
9
            ["dom.storageManager.prompt.testing.allow", false]]
10
  }, continueToNextStep);
11
  yield undefined;
12
13
  navigator.storage.persist().then(result => {
14
    testGenerator.next(result);
15
  });
16
  let persistResult  = yield undefined;
17
18
  is(persistResult, false, "Cancel the persist prompt and resolve a promise with false");
19
20
  navigator.storage.persisted().then(result => {
21
    testGenerator.next(result);
22
  });
23
  let persistedResult  = yield undefined;
24
25
  is(persistResult, persistedResult, "persist/persisted results shall be consistent");
26
27
  finishTest();
28
}
(-)a/modules/libpref/init/all.js (+3 lines)
Line     Link Here 
 Lines 5612-5627   pref ("security.data_uri.inherit_securit Link Here 
5612
5612
5613
// Disable Storage api in release builds.
5613
// Disable Storage api in release builds.
5614
#if defined(NIGHTLY_BUILD) && !defined(MOZ_WIDGET_ANDROID)
5614
#if defined(NIGHTLY_BUILD) && !defined(MOZ_WIDGET_ANDROID)
5615
pref("dom.storageManager.enabled", true);
5615
pref("dom.storageManager.enabled", true);
5616
#else
5616
#else
5617
pref("dom.storageManager.enabled", false);
5617
pref("dom.storageManager.enabled", false);
5618
#endif
5618
#endif
5619
5619
5620
pref("dom.storageManager.prompt.testing", false);
5621
pref("dom.storageManager.prompt.testing.allow", false);
5622
5620
// When a user cancels this number of authentication dialogs coming from
5623
// When a user cancels this number of authentication dialogs coming from
5621
// a single web page in a row, all following authentication dialogs will
5624
// a single web page in a row, all following authentication dialogs will
5622
// be blocked (automatically canceled) for that page. The counter resets
5625
// be blocked (automatically canceled) for that page. The counter resets
5623
// when the page is reloaded. To turn this feature off, just set the limit to 0.
5626
// when the page is reloaded. To turn this feature off, just set the limit to 0.
5624
pref("prompts.authentication_dialog_abuse_limit", 3);
5627
pref("prompts.authentication_dialog_abuse_limit", 3);
5625
5628
5626
// Enable the Storage management in about:preferences and persistent-storage permission request
5629
// Enable the Storage management in about:preferences and persistent-storage permission request
5627
// To enable the DOM implementation, turn on "dom.storageManager.enabled"
5630
// To enable the DOM implementation, turn on "dom.storageManager.enabled"

Return to bug 1286717