mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
commit
5f1ac1afb3
@ -3,7 +3,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
chrome.jar:
|
||||
% content branding %content/branding/
|
||||
% content branding %content/branding/ contentaccessible=yes
|
||||
content/branding/about.png (about.png)
|
||||
content/branding/logoWordmark.png (logoWordmark.png)
|
||||
content/branding/logo.png (logo.png)
|
||||
|
@ -3,7 +3,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
chrome.jar:
|
||||
% content branding %content/branding/
|
||||
% content branding %content/branding/ contentaccessible=yes
|
||||
content/branding/about.png (about.png)
|
||||
content/branding/logoWordmark.png (logoWordmark.png)
|
||||
content/branding/logo.png (logo.png)
|
||||
|
@ -3,7 +3,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
chrome.jar:
|
||||
% content branding %content/branding/
|
||||
% content branding %content/branding/ contentaccessible=yes
|
||||
content/branding/about.png (about.png)
|
||||
content/branding/logoWordmark.png (logoWordmark.png)
|
||||
content/branding/logo.png (logo.png)
|
||||
|
@ -3,7 +3,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
chrome.jar:
|
||||
% content branding %content/branding/
|
||||
% content branding %content/branding/ contentaccessible=yes
|
||||
content/branding/about.png (about.png)
|
||||
content/branding/logoWordmark.png (logoWordmark.png)
|
||||
content/branding/logo.png (logo.png)
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
|
||||
chrome.jar:
|
||||
% content branding %content/branding/
|
||||
% content branding %content/branding/ contentaccessible=yes
|
||||
% content b2g %content/
|
||||
|
||||
content/arrow.svg (content/arrow.svg)
|
||||
|
@ -32,6 +32,7 @@ externalProtocolLaunchBtn=Launch application
|
||||
malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
|
||||
unwantedBlocked=The site at %S has been reported as serving unwanted software and has been blocked based on your security preferences.
|
||||
phishingBlocked=The website at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
|
||||
forbiddenBlocked=The site at %S has been blocked by your browser configuration.
|
||||
cspBlocked=This page has a content security policy that prevents it from being loaded in this way.
|
||||
corruptedContentError=The page you are trying to view cannot be shown because an error in the data transmission was detected.
|
||||
remoteXUL=This page uses an unsupported technology that is no longer available by default in Firefox.
|
||||
|
@ -423,6 +423,7 @@
|
||||
<h1 id="et_nssBadCert">&nssBadCert.title;</h1>
|
||||
<h1 id="et_malwareBlocked">&malwareBlocked.title;</h1>
|
||||
<h1 id="et_unwantedBlocked">&unwantedBlocked.title;</h1>
|
||||
<h1 id="et_forbiddenBlocked">&forbiddenBlocked.title;</h1>
|
||||
<h1 id="et_cspBlocked">&cspBlocked.title;</h1>
|
||||
<h1 id="et_remoteXUL">&remoteXUL.title;</h1>
|
||||
<h1 id="et_corruptedContentError">&corruptedContentError.title;</h1>
|
||||
@ -452,6 +453,7 @@
|
||||
<div id="ed_nssBadCert">&nssBadCert.longDesc2;</div>
|
||||
<div id="ed_malwareBlocked">&malwareBlocked.longDesc;</div>
|
||||
<div id="ed_unwantedBlocked">&unwantedBlocked.longDesc;</div>
|
||||
<div id="ed_forbiddenBlocked">&forbiddenBlocked.longDesc;</div>
|
||||
<div id="ed_cspBlocked">&cspBlocked.longDesc;</div>
|
||||
<div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
|
||||
<div id="ed_corruptedContentError">&corruptedContentError.longDesc;</div>
|
||||
|
@ -68,111 +68,76 @@
|
||||
return getURL();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function initPage()
|
||||
{
|
||||
// Handoff to the appropriate initializer, based on error code
|
||||
var error = "";
|
||||
switch (getErrorCode()) {
|
||||
case "malwareBlocked" :
|
||||
initPage_malware();
|
||||
error = "malware";
|
||||
break;
|
||||
case "phishingBlocked" :
|
||||
initPage_phishing();
|
||||
error = "phishing";
|
||||
break;
|
||||
case "unwantedBlocked" :
|
||||
initPage_unwanted();
|
||||
error = "unwanted";
|
||||
break;
|
||||
case "forbiddenBlocked" :
|
||||
error = "forbidden";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize custom strings and functionality for blocked malware case
|
||||
*/
|
||||
function initPage_malware()
|
||||
{
|
||||
// Remove phishing and unwanted strings
|
||||
var el = document.getElementById("errorTitleText_phishing");
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
el = document.getElementById("errorShortDescText_phishing");
|
||||
el.parentNode.removeChild(el);
|
||||
var el;
|
||||
|
||||
el = document.getElementById("errorLongDescText_phishing");
|
||||
el.parentNode.removeChild(el);
|
||||
if (error !== "malware") {
|
||||
el = document.getElementById("errorTitleText_malware");
|
||||
el.parentNode.removeChild(el);
|
||||
el = document.getElementById("errorShortDescText_malware");
|
||||
el.parentNode.removeChild(el);
|
||||
el = document.getElementById("errorLongDescText_malware");
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
|
||||
el = document.getElementById("errorTitleText_unwanted");
|
||||
el.parentNode.removeChild(el);
|
||||
if (error !== "phishing") {
|
||||
el = document.getElementById("errorTitleText_phishing");
|
||||
el.parentNode.removeChild(el);
|
||||
el = document.getElementById("errorShortDescText_phishing");
|
||||
el.parentNode.removeChild(el);
|
||||
el = document.getElementById("errorLongDescText_phishing");
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
|
||||
el = document.getElementById("errorShortDescText_unwanted");
|
||||
el.parentNode.removeChild(el);
|
||||
if (error !== "unwanted") {
|
||||
el = document.getElementById("errorTitleText_unwanted");
|
||||
el.parentNode.removeChild(el);
|
||||
el = document.getElementById("errorShortDescText_unwanted");
|
||||
el.parentNode.removeChild(el);
|
||||
el = document.getElementById("errorLongDescText_unwanted");
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
|
||||
el = document.getElementById("errorLongDescText_unwanted");
|
||||
el.parentNode.removeChild(el);
|
||||
if (error !== "forbidden") {
|
||||
el = document.getElementById("errorTitleText_forbidden");
|
||||
el.parentNode.removeChild(el);
|
||||
el = document.getElementById("errorShortDescText_forbidden");
|
||||
el.parentNode.removeChild(el);
|
||||
} else {
|
||||
el = document.getElementById("ignoreWarningButton");
|
||||
el.parentNode.removeChild(el);
|
||||
el = document.getElementById("reportButton");
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
|
||||
// Set sitename
|
||||
document.getElementById("malware_sitename").textContent = getHostString();
|
||||
document.title = document.getElementById("errorTitleText_malware")
|
||||
document.getElementById(error + "_sitename").textContent = getHostString();
|
||||
document.title = document.getElementById("errorTitleText_" + error)
|
||||
.innerHTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize custom strings and functionality for blocked malware case
|
||||
*/
|
||||
function initPage_unwanted()
|
||||
{
|
||||
// Remove phishing and malware strings
|
||||
var el = document.getElementById("errorTitleText_phishing");
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
el = document.getElementById("errorShortDescText_phishing");
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
el = document.getElementById("errorLongDescText_phishing");
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
el = document.getElementById("errorTitleText_malware");
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
el = document.getElementById("errorShortDescText_malware");
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
el = document.getElementById("errorLongDescText_malware");
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
// Set sitename
|
||||
document.getElementById("unwanted_sitename").textContent = getHostString();
|
||||
document.title = document.getElementById("errorTitleText_unwanted")
|
||||
.innerHTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize custom strings and functionality for blocked phishing case
|
||||
*/
|
||||
function initPage_phishing()
|
||||
{
|
||||
// Remove malware and unwanted strings
|
||||
var el = document.getElementById("errorTitleText_malware");
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
el = document.getElementById("errorShortDescText_malware");
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
el = document.getElementById("errorLongDescText_malware");
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
el = document.getElementById("errorTitleText_unwanted");
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
el = document.getElementById("errorShortDescText_unwanted");
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
el = document.getElementById("errorLongDescText_unwanted");
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
// Set sitename
|
||||
document.getElementById("phishing_sitename").textContent = getHostString();
|
||||
document.title = document.getElementById("errorTitleText_phishing")
|
||||
.innerHTML;
|
||||
// Inform the test harness that we're done loading the page
|
||||
var event = new CustomEvent("AboutBlockedLoaded");
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
]]></script>
|
||||
<style type="text/css">
|
||||
@ -213,6 +178,7 @@
|
||||
<h1 id="errorTitleText_phishing">&safeb.blocked.phishingPage.title;</h1>
|
||||
<h1 id="errorTitleText_malware">&safeb.blocked.malwarePage.title;</h1>
|
||||
<h1 id="errorTitleText_unwanted">&safeb.blocked.unwantedPage.title;</h1>
|
||||
<h1 id="errorTitleText_forbidden">&safeb.blocked.forbiddenPage.title;</h1>
|
||||
</div>
|
||||
|
||||
<div id="errorLongContent">
|
||||
@ -222,6 +188,7 @@
|
||||
<p id="errorShortDescText_phishing">&safeb.blocked.phishingPage.shortDesc;</p>
|
||||
<p id="errorShortDescText_malware">&safeb.blocked.malwarePage.shortDesc;</p>
|
||||
<p id="errorShortDescText_unwanted">&safeb.blocked.unwantedPage.shortDesc;</p>
|
||||
<p id="errorShortDescText_forbidden">&safeb.blocked.forbiddenPage.shortDesc;</p>
|
||||
</div>
|
||||
|
||||
<!-- Long Description -->
|
||||
|
@ -2958,10 +2958,16 @@ var BrowserOnClick = {
|
||||
onAboutBlocked: function (elementId, reason, isTopFrame, location) {
|
||||
// Depending on what page we are displaying here (malware/phishing/unwanted)
|
||||
// use the right strings and links for each.
|
||||
let bucketName = "WARNING_PHISHING_PAGE_";
|
||||
let bucketName = "";
|
||||
let sendTelemetry = false;
|
||||
if (reason === 'malware') {
|
||||
sendTelemetry = true;
|
||||
bucketName = "WARNING_MALWARE_PAGE_";
|
||||
} else if (reason === 'phishing') {
|
||||
sendTelemetry = true;
|
||||
bucketName = "WARNING_PHISHING_PAGE_";
|
||||
} else if (reason === 'unwanted') {
|
||||
sendTelemetry = true;
|
||||
bucketName = "WARNING_UNWANTED_PAGE_";
|
||||
}
|
||||
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
|
||||
@ -2969,7 +2975,9 @@ var BrowserOnClick = {
|
||||
bucketName += isTopFrame ? "TOP_" : "FRAME_";
|
||||
switch (elementId) {
|
||||
case "getMeOutButton":
|
||||
secHistogram.add(nsISecTel[bucketName + "GET_ME_OUT_OF_HERE"]);
|
||||
if (sendTelemetry) {
|
||||
secHistogram.add(nsISecTel[bucketName + "GET_ME_OUT_OF_HERE"]);
|
||||
}
|
||||
getMeOutOfHere();
|
||||
break;
|
||||
|
||||
@ -2979,13 +2987,16 @@ var BrowserOnClick = {
|
||||
|
||||
// We log even if malware/phishing/unwanted info URL couldn't be found:
|
||||
// the measurement is for how many users clicked the WHY BLOCKED button
|
||||
secHistogram.add(nsISecTel[bucketName + "WHY_BLOCKED"]);
|
||||
|
||||
if (sendTelemetry) {
|
||||
secHistogram.add(nsISecTel[bucketName + "WHY_BLOCKED"]);
|
||||
}
|
||||
openHelpLink("phishing-malware", false, "current");
|
||||
break;
|
||||
|
||||
case "ignoreWarningButton":
|
||||
secHistogram.add(nsISecTel[bucketName + "IGNORE_WARNING"]);
|
||||
if (sendTelemetry) {
|
||||
secHistogram.add(nsISecTel[bucketName + "IGNORE_WARNING"]);
|
||||
}
|
||||
this.ignoreWarningButton(reason);
|
||||
break;
|
||||
}
|
||||
@ -3054,6 +3065,8 @@ var BrowserOnClick = {
|
||||
title = gNavigatorBundle.getString("safebrowsing.reportedUnwantedSite");
|
||||
// There is no button for reporting errors since Google doesn't currently
|
||||
// provide a URL endpoint for these reports.
|
||||
} else {
|
||||
return; // no notifications for forbidden sites
|
||||
}
|
||||
|
||||
let notificationBox = gBrowser.getNotificationBox();
|
||||
|
@ -460,6 +460,8 @@ var ClickEventHandler = {
|
||||
reason = 'malware';
|
||||
} else if (/e=unwantedBlocked/.test(ownerDoc.documentURI)) {
|
||||
reason = 'unwanted';
|
||||
} else if (/e=forbiddenBlocked/.test(ownerDoc.documentURI)) {
|
||||
reason = 'forbidden';
|
||||
}
|
||||
sendAsyncMessage("Browser:SiteBlockedError", {
|
||||
location: ownerDoc.location.href,
|
||||
|
@ -5,7 +5,7 @@
|
||||
Components.utils.import("resource:///modules/SitePermissions.jsm");
|
||||
Components.utils.import("resource://gre/modules/BrowserUtils.jsm");
|
||||
|
||||
const nsIQuotaManager = Components.interfaces.nsIQuotaManager;
|
||||
const nsIQuotaManagerService = Components.interfaces.nsIQuotaManagerService;
|
||||
|
||||
var gPermURI;
|
||||
var gUsageRequest;
|
||||
@ -186,13 +186,15 @@ function initIndexedDBRow()
|
||||
|
||||
row.appendChild(extras);
|
||||
|
||||
var quotaManager = Components.classes["@mozilla.org/dom/quota/manager;1"]
|
||||
.getService(nsIQuotaManager);
|
||||
var quotaManagerService =
|
||||
Components.classes["@mozilla.org/dom/quota-manager-service;1"]
|
||||
.getService(nsIQuotaManagerService);
|
||||
let principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(Components.interfaces.nsIScriptSecurityManager)
|
||||
.createCodebasePrincipal(gPermURI, {});
|
||||
gUsageRequest =
|
||||
quotaManager.getUsageForPrincipal(principal, onIndexedDBUsageCallback);
|
||||
quotaManagerService.getUsageForPrincipal(principal,
|
||||
onIndexedDBUsageCallback);
|
||||
|
||||
var status = document.getElementById("indexedDBStatus");
|
||||
var button = document.getElementById("indexedDBClear");
|
||||
@ -208,8 +210,8 @@ function onIndexedDBClear()
|
||||
.getService(Components.interfaces.nsIScriptSecurityManager)
|
||||
.createCodebasePrincipal(gPermURI, {});
|
||||
|
||||
Components.classes["@mozilla.org/dom/quota/manager;1"]
|
||||
.getService(nsIQuotaManager)
|
||||
Components.classes["@mozilla.org/dom/quota-manager-service;1"]
|
||||
.getService(nsIQuotaManagerService)
|
||||
.clearStoragesForPrincipal(principal);
|
||||
|
||||
Components.classes["@mozilla.org/serviceworkers/manager;1"]
|
||||
@ -220,14 +222,14 @@ function onIndexedDBClear()
|
||||
initIndexedDBRow();
|
||||
}
|
||||
|
||||
function onIndexedDBUsageCallback(principal, usage, fileUsage)
|
||||
function onIndexedDBUsageCallback(request)
|
||||
{
|
||||
let uri = principal.URI;
|
||||
let uri = request.principal.URI;
|
||||
if (!uri.equals(gPermURI)) {
|
||||
throw new Error("Callback received for bad URI: " + uri);
|
||||
}
|
||||
|
||||
if (usage) {
|
||||
if (request.usage) {
|
||||
if (!("DownloadUtils" in window)) {
|
||||
Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
|
||||
}
|
||||
@ -237,7 +239,7 @@ function onIndexedDBUsageCallback(principal, usage, fileUsage)
|
||||
|
||||
status.value =
|
||||
gBundle.getFormattedString("indexedDBUsage",
|
||||
DownloadUtils.convertByteUnits(usage));
|
||||
DownloadUtils.convertByteUnits(request.usage));
|
||||
status.removeAttribute("hidden");
|
||||
button.removeAttribute("hidden");
|
||||
}
|
||||
|
@ -360,6 +360,10 @@ var gTests = [
|
||||
EventUtils.synthesizeKey("a", { accelKey: true });
|
||||
EventUtils.synthesizeKey("VK_DELETE", {});
|
||||
ok(table.hidden, "Search suggestion table hidden");
|
||||
|
||||
try {
|
||||
Services.search.removeEngine(engine);
|
||||
} catch (ex) { }
|
||||
});
|
||||
}
|
||||
},
|
||||
@ -369,6 +373,12 @@ var gTests = [
|
||||
run: function()
|
||||
{
|
||||
return Task.spawn(function* () {
|
||||
// Add a test engine that provides suggestions and switch to it.
|
||||
let engine = yield promiseNewEngine("searchSuggestionEngine.xml");
|
||||
let p = promiseContentSearchChange(engine.name);
|
||||
Services.search.currentEngine = engine;
|
||||
yield p;
|
||||
|
||||
// Start composition and type "x"
|
||||
let input = gBrowser.contentDocument.getElementById("searchText");
|
||||
input.focus();
|
||||
|
5
browser/base/content/test/general/bug_1182546.xml
Normal file
5
browser/base/content/test/general/bug_1182546.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % passwordManagerDTD SYSTEM "chrome://passwordmgr/locale/passwordManager.dtd">
|
||||
%passwordManagerDTD;
|
||||
]>
|
||||
<window>&savedLogins.title;</window>
|
@ -25,6 +25,7 @@ support-files =
|
||||
offlineEvent.html
|
||||
subtst_contextmenu.html
|
||||
video.ogg
|
||||
bug_1182546.xml
|
||||
|
||||
[test_bug364677.html]
|
||||
[test_bug395533.html]
|
||||
@ -38,3 +39,4 @@ skip-if = e10s
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug 1066070 - I don't think either popup notifications nor addon install stuff works?
|
||||
[test_offline_gzip.html]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug 1066070 - I don't think either popup notifications nor addon install stuff works?
|
||||
[test_bug1182546.html]
|
||||
|
35
browser/base/content/test/general/test_bug1182546.html
Normal file
35
browser/base/content/test/general/test_bug1182546.html
Normal file
@ -0,0 +1,35 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1182546
|
||||
-->
|
||||
<head>
|
||||
<title>Bug 1182546 - Test block loading DTD from random page</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="testframe" src="bug_1182546.xml"></iframe>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
addLoadEvent(function() {
|
||||
// make sure the DTD loader (nsExpatDriver) prevents accessing chrome: from random pages
|
||||
var childNodes = testframe.contentDocument.documentElement.childNodes;
|
||||
|
||||
// make sure '&savedLogins.title;' from bug_1182546.xml does not translate into 'Saved Logins'
|
||||
// the URL 'chrome://passwordmgr/locale/passwordManager.dtd' should not be accessible from content
|
||||
var nodeValue = childNodes[0].nodeValue;
|
||||
isnot(nodeValue, "Saved Logins",
|
||||
"expatDriver should prevent accessing &savedLogins.title;");
|
||||
ok(nodeValue.startsWith("XML Parsing Error: undefined entity"),
|
||||
"expatDriver should not allow accessing chrome:");
|
||||
});
|
||||
|
||||
addLoadEvent(SimpleTest.finish);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -28,11 +28,6 @@ add_task(function* () {
|
||||
// Migrate unencrypted cookies.
|
||||
yield promiseMigration(migrator, MigrationUtils.resourceTypes.COOKIES, PROFILE);
|
||||
|
||||
do_register_cleanup(() => {
|
||||
ForgetAboutSite.removeDataFromDomain(COOKIE.host);
|
||||
Assert.equal(Services.cookies.countCookiesFromHost(COOKIE.host), 0,
|
||||
"There are no cookies after cleanup");
|
||||
});
|
||||
Assert.equal(Services.cookies.countCookiesFromHost(COOKIE.host), 1,
|
||||
"Migrated the expected number of unencrypted cookies");
|
||||
Assert.equal(Services.cookies.countCookiesFromHost("encryptedcookie.invalid"), 0,
|
||||
@ -46,4 +41,10 @@ add_task(function* () {
|
||||
for (let prop of Object.keys(COOKIE)) {
|
||||
Assert.equal(foundCookie[prop], COOKIE[prop], "Check cookie " + prop);
|
||||
}
|
||||
|
||||
// Cleanup.
|
||||
ForgetAboutSite.removeDataFromDomain(COOKIE.host);
|
||||
Assert.equal(Services.cookies.countCookiesFromHost(COOKIE.host), 0,
|
||||
"There are no cookies after cleanup");
|
||||
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
[DEFAULT]
|
||||
support-files = head.js
|
||||
|
||||
[browser_forbidden.js]
|
||||
[browser_bug400731.js]
|
||||
skip-if = e10s
|
||||
[browser_bug415846.js]
|
||||
|
@ -0,0 +1,40 @@
|
||||
/* Ensure that pages in the forbidden list are blocked. */
|
||||
|
||||
const PREF_FORBIDDEN_ENABLED = "browser.safebrowsing.forbiddenURIs.enabled";
|
||||
const BENIGN_PAGE = "http://example.com/";
|
||||
const FORBIDDEN_PAGE = "http://www.itisatrap.org/firefox/forbidden.html";
|
||||
var tabbrowser = null;
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
tabbrowser = null;
|
||||
Services.prefs.clearUserPref(PREF_FORBIDDEN_ENABLED);
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
});
|
||||
|
||||
function testBenignPage(window) {
|
||||
info("Non-forbidden content must not be blocked");
|
||||
var getmeout_button = window.document.getElementById("getMeOutButton");
|
||||
var ignorewarning_button = window.document.getElementById("ignoreWarningButton");
|
||||
ok(!getmeout_button, "GetMeOut button not present");
|
||||
ok(!ignorewarning_button, "IgnoreWarning button not present");
|
||||
}
|
||||
|
||||
function testForbiddenPage(window) {
|
||||
info("Forbidden content must be blocked");
|
||||
ok(true, "about:blocked was shown");
|
||||
}
|
||||
|
||||
add_task(function* testNormalBrowsing() {
|
||||
tabbrowser = gBrowser;
|
||||
let tab = tabbrowser.selectedTab = tabbrowser.addTab();
|
||||
|
||||
info("Load a test page that's not forbidden");
|
||||
yield promiseTabLoadEvent(tab, BENIGN_PAGE, "load");
|
||||
testBenignPage(tab.ownerDocument.defaultView);
|
||||
|
||||
info("Load a test page that is forbidden");
|
||||
yield promiseTabLoadEvent(tab, FORBIDDEN_PAGE, "AboutBlockedLoaded");
|
||||
testForbiddenPage(tab.ownerDocument.defaultView);
|
||||
});
|
@ -1,5 +1,57 @@
|
||||
// Force SafeBrowsing to be initialized for the tests
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/Promise.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
|
||||
/**
|
||||
* Waits for a load (or custom) event to finish in a given tab. If provided
|
||||
* load an uri into the tab.
|
||||
*
|
||||
* @param tab
|
||||
* The tab to load into.
|
||||
* @param [optional] url
|
||||
* The url to load, or the current url.
|
||||
* @param [optional] event
|
||||
* The load event type to wait for. Defaults to "load".
|
||||
* @return {Promise} resolved when the event is handled.
|
||||
* @resolves to the received event
|
||||
* @rejects if a valid load event is not received within a meaningful interval
|
||||
*/
|
||||
function promiseTabLoadEvent(tab, url, eventType="load")
|
||||
{
|
||||
let deferred = Promise.defer();
|
||||
info("Wait tab event: " + eventType);
|
||||
|
||||
function handle(event) {
|
||||
if (event.originalTarget != tab.linkedBrowser.contentDocument ||
|
||||
event.target.location.href == "about:blank" ||
|
||||
(url && event.target.location.href != url)) {
|
||||
info("Skipping spurious '" + eventType + "'' event" +
|
||||
" for " + event.target.location.href);
|
||||
return;
|
||||
}
|
||||
clearTimeout(timeout);
|
||||
tab.linkedBrowser.removeEventListener(eventType, handle, true);
|
||||
info("Tab event received: " + eventType);
|
||||
deferred.resolve(event);
|
||||
}
|
||||
|
||||
let timeout = setTimeout(() => {
|
||||
tab.linkedBrowser.removeEventListener(eventType, handle, true);
|
||||
deferred.reject(new Error("Timed out while waiting for a '" + eventType + "'' event"));
|
||||
}, 30000);
|
||||
|
||||
tab.linkedBrowser.addEventListener(eventType, handle, true, true);
|
||||
if (url) {
|
||||
tab.linkedBrowser.loadURI(url);
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
Services.prefs.setCharPref("urlclassifier.forbiddenTable", "test-forbid-simple");
|
||||
Services.prefs.setCharPref("urlclassifier.malwareTable", "test-malware-simple,test-unwanted-simple");
|
||||
Services.prefs.setCharPref("urlclassifier.phishTable", "test-phish-simple");
|
||||
Services.prefs.setBoolPref("browser.safebrowsing.forbiddenURIs.enabled", true);
|
||||
SafeBrowsing.init();
|
||||
|
||||
|
@ -7,5 +7,5 @@
|
||||
DEFINES['APP_VERSION'] = CONFIG['FIREFOX_VERSION']
|
||||
|
||||
DEFINES['MOZ_APP_NAME'] = CONFIG['MOZ_APP_NAME']
|
||||
DEFINES['MOZ_APP_DISPLAYNAME'] = "'%s'" % CONFIG['MOZ_APP_DISPLAYNAME']
|
||||
DEFINES['MOZ_APP_DISPLAYNAME'] = CONFIG['MOZ_APP_DISPLAYNAME']
|
||||
DEFINES['MOZILLA_VERSION'] = CONFIG['MOZILLA_VERSION']
|
||||
|
@ -8,16 +8,21 @@
|
||||
<!ENTITY safeb.palm.reportPage.label "Why was this page blocked?">
|
||||
|
||||
<!ENTITY safeb.blocked.malwarePage.title "Reported Attack Page!">
|
||||
<!-- Localization note (safeb.blocked.malware.shortDesc) - Please don't translate the contents of the <span id="malware_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
|
||||
<!-- Localization note (safeb.blocked.malwarePage.shortDesc) - Please don't translate the contents of the <span id="malware_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
|
||||
<!ENTITY safeb.blocked.malwarePage.shortDesc "This web page at <span id='malware_sitename'/> has been reported as an attack page and has been blocked based on your security preferences.">
|
||||
<!ENTITY safeb.blocked.malwarePage.longDesc "<p>Attack pages try to install programs that steal private information, use your computer to attack others, or damage your system.</p><p>Some attack pages intentionally distribute harmful software, but many are compromised without the knowledge or permission of their owners.</p>">
|
||||
|
||||
<!ENTITY safeb.blocked.unwantedPage.title "Reported Unwanted Software Page!">
|
||||
<!-- Localization note (safeb.blocked.malware.shortDesc) - Please don't translate the contents of the <span id="unwanted_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
|
||||
<!-- Localization note (safeb.blocked.unwantedPage.shortDesc) - Please don't translate the contents of the <span id="unwanted_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
|
||||
<!ENTITY safeb.blocked.unwantedPage.shortDesc "This web page at <span id='unwanted_sitename'/> has been reported to contain unwanted software and has been blocked based on your security preferences.">
|
||||
<!ENTITY safeb.blocked.unwantedPage.longDesc "<p>Unwanted software pages try to install software that can be deceptive and affect your system in unexpected ways.</p>">
|
||||
|
||||
<!ENTITY safeb.blocked.phishingPage.title "Reported Web Forgery!">
|
||||
<!-- Localization note (safeb.blocked.phishing.shortDesc) - Please don't translate the contents of the <span id="phishing_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
|
||||
<!-- Localization note (safeb.blocked.phishingPage.shortDesc) - Please don't translate the contents of the <span id="phishing_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
|
||||
<!ENTITY safeb.blocked.phishingPage.shortDesc "This web page at <span id='phishing_sitename'/> has been reported as a web forgery and has been blocked based on your security preferences.">
|
||||
<!ENTITY safeb.blocked.phishingPage.longDesc "<p>Web forgeries are designed to trick you into revealing personal or financial information by imitating sources you may trust.</p><p>Entering any information on this web page may result in identity theft or other fraud.</p>">
|
||||
|
||||
<!ENTITY safeb.blocked.forbiddenPage.title "Forbidden Site">
|
||||
<!-- Localization note (safeb.blocked.forbiddenPage.shortDesc) - Please don't translate the contents of the <span id="forbidden_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
|
||||
<!ENTITY safeb.blocked.forbiddenPage.shortDesc "This Web page at <span id='forbidden_sitename'/> has been blocked based on your browser configuration.">
|
||||
|
||||
|
@ -32,6 +32,7 @@ externalProtocolLaunchBtn=Launch application
|
||||
malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
|
||||
unwantedBlocked=The site at %S has been reported as serving unwanted software and has been blocked based on your security preferences.
|
||||
phishingBlocked=The website at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
|
||||
forbiddenBlocked=The site at %S has been blocked by your browser configuration.
|
||||
cspBlocked=This page has a content security policy that prevents it from being loaded in this way.
|
||||
corruptedContentError=The page you are trying to view cannot be shown because an error in the data transmission was detected.
|
||||
remoteXUL=This page uses an unsupported technology that is no longer available by default in Firefox.
|
||||
|
@ -175,6 +175,10 @@ be temporary, and you can try again later.</li>
|
||||
<p>These types of web forgeries are used in scams known as phishing attacks, in which fraudulent web pages and emails are used to imitate sources you may trust.</p>
|
||||
">
|
||||
|
||||
<!ENTITY forbiddenBlocked.title "Forbidden Site">
|
||||
<!ENTITY forbiddenBlocked.longDesc "<p>&brandShortName; prevented this page from loading because it is configured to block it.</p>
|
||||
">
|
||||
|
||||
<!ENTITY cspBlocked.title "Blocked by Content Security Policy">
|
||||
<!ENTITY cspBlocked.longDesc "<p>&brandShortName; prevented this page from loading in this way because the page has a content security policy that disallows it.</p>">
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
|
||||
<svg version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.5 KiB |
@ -4,14 +4,45 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/devtools/DominatorTree.h"
|
||||
|
||||
#include "js/Debug.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "mozilla/dom/DominatorTreeBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace devtools {
|
||||
|
||||
dom::Nullable<uint64_t>
|
||||
DominatorTree::GetRetainedSize(uint64_t aNodeId, ErrorResult& aRv)
|
||||
{
|
||||
JS::ubi::Node::Id id(aNodeId);
|
||||
auto node = mHeapSnapshot->getNodeById(id);
|
||||
if (node.isNothing())
|
||||
return dom::Nullable<uint64_t>();
|
||||
|
||||
auto ccrt = CycleCollectedJSRuntime::Get();
|
||||
MOZ_ASSERT(ccrt);
|
||||
auto rt = ccrt->Runtime();
|
||||
MOZ_ASSERT(rt);
|
||||
auto mallocSizeOf = JS::dbg::GetDebuggerMallocSizeOf(rt);
|
||||
MOZ_ASSERT(mallocSizeOf);
|
||||
|
||||
JS::ubi::Node::Size size = 0;
|
||||
if (!mDominatorTree.getRetainedSize(*node, mallocSizeOf, size)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return dom::Nullable<uint64_t>();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(size != 0,
|
||||
"The node should not have been unknown since we got it from the heap snapshot.");
|
||||
return dom::Nullable<uint64_t>(size);
|
||||
}
|
||||
|
||||
|
||||
/*** Cycle Collection Boilerplate *****************************************************************/
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DominatorTree, mParent)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DominatorTree, mParent, mHeapSnapshot)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(DominatorTree)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(DominatorTree)
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#ifndef mozilla_devtools_DominatorTree__
|
||||
#define mozilla_devtools_DominatorTree__
|
||||
|
||||
#include "mozilla/devtools/HeapSnapshot.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/RefCounted.h"
|
||||
@ -25,13 +26,17 @@ protected:
|
||||
|
||||
private:
|
||||
JS::ubi::DominatorTree mDominatorTree;
|
||||
RefPtr<HeapSnapshot> mHeapSnapshot;
|
||||
|
||||
public:
|
||||
explicit DominatorTree(JS::ubi::DominatorTree&& aDominatorTree, nsISupports* aParent)
|
||||
explicit DominatorTree(JS::ubi::DominatorTree&& aDominatorTree, HeapSnapshot* aHeapSnapshot,
|
||||
nsISupports* aParent)
|
||||
: mParent(aParent)
|
||||
, mDominatorTree(Move(aDominatorTree))
|
||||
, mHeapSnapshot(aHeapSnapshot)
|
||||
{
|
||||
MOZ_ASSERT(aParent);
|
||||
MOZ_ASSERT(aHeapSnapshot);
|
||||
};
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS;
|
||||
@ -42,7 +47,11 @@ public:
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// readonly attribute NodeId root
|
||||
uint64_t Root() const { return mDominatorTree.root().identifier(); }
|
||||
|
||||
// [Throws] NodeSize getRetainedSize(NodeId node)
|
||||
dom::Nullable<uint64_t> GetRetainedSize(uint64_t aNodeId, ErrorResult& aRv);
|
||||
};
|
||||
|
||||
} // namespace devtools
|
||||
|
@ -11,12 +11,15 @@
|
||||
|
||||
#include "js/Debug.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/UbiNodeCensus.h"
|
||||
#include "js/UbiNodeBreadthFirst.h"
|
||||
#include "js/UbiNodeCensus.h"
|
||||
#include "js/UbiNodeDominatorTree.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "mozilla/devtools/AutoMemMap.h"
|
||||
#include "mozilla/devtools/CoreDump.pb.h"
|
||||
#include "mozilla/devtools/DeserializedNode.h"
|
||||
#include "mozilla/devtools/DominatorTree.h"
|
||||
#include "mozilla/devtools/FileDescriptorOutputStream.h"
|
||||
#include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
|
||||
#include "mozilla/devtools/ZeroCopyNSIOutputStream.h"
|
||||
@ -538,7 +541,7 @@ HeapSnapshot::ComputeDominatorTree(ErrorResult& rv)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return MakeAndAddRef<DominatorTree>(Move(*maybeTree), mParent);
|
||||
return MakeAndAddRef<DominatorTree>(Move(*maybeTree), this, mParent);
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "js/HashTable.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/devtools/DeserializedNode.h"
|
||||
#include "mozilla/devtools/DominatorTree.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
@ -30,6 +29,8 @@
|
||||
namespace mozilla {
|
||||
namespace devtools {
|
||||
|
||||
class DominatorTree;
|
||||
|
||||
struct NSFreePolicy {
|
||||
void operator()(void* ptr) {
|
||||
NS_Free(ptr);
|
||||
@ -148,6 +149,13 @@ public:
|
||||
return JS::ubi::Node(const_cast<DeserializedNode*>(&node));
|
||||
}
|
||||
|
||||
Maybe<JS::ubi::Node> getNodeById(JS::ubi::Node::Id nodeId) {
|
||||
auto p = nodes.lookup(nodeId);
|
||||
if (!p)
|
||||
return Nothing();
|
||||
return Some(JS::ubi::Node(const_cast<DeserializedNode*>(&*p)));
|
||||
}
|
||||
|
||||
void TakeCensus(JSContext* cx, JS::HandleObject options,
|
||||
JS::MutableHandleValue rval, ErrorResult& rv);
|
||||
|
||||
|
@ -79,8 +79,8 @@ ZeroCopyNSIOutputStream::Next(void** data, int* size)
|
||||
void
|
||||
ZeroCopyNSIOutputStream::BackUp(int count)
|
||||
{
|
||||
MOZ_ASSERT(count > 0,
|
||||
"Must back up a positive number of bytes.");
|
||||
MOZ_ASSERT(count >= 0,
|
||||
"Cannot back up a negative amount of bytes.");
|
||||
MOZ_ASSERT(amountUsed == BUFFER_SIZE,
|
||||
"Can only call BackUp directly after calling Next.");
|
||||
MOZ_ASSERT(count <= amountUsed,
|
||||
|
@ -0,0 +1,22 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that we can get the retained sizes of dominator trees.
|
||||
|
||||
function run_test() {
|
||||
const dominatorTree = saveHeapSnapshotAndComputeDominatorTree();
|
||||
equal(typeof dominatorTree.getRetainedSize, "function",
|
||||
"getRetainedSize should be a function");
|
||||
|
||||
const size = dominatorTree.getRetainedSize(dominatorTree.root);
|
||||
ok(size, "should get a size for the root");
|
||||
equal(typeof size, "number", "retained sizes should be a number");
|
||||
equal(Math.floor(size), size, "size should be an integer");
|
||||
ok(size > 0, "size should be positive");
|
||||
ok(size <= Math.pow(2, 64), "size should be less than or equal to 2^64");
|
||||
|
||||
const bad = dominatorTree.getRetainedSize(1);
|
||||
equal(bad, null, "null is returned for unknown node ids");
|
||||
|
||||
do_test_finished();
|
||||
}
|
@ -31,6 +31,7 @@ support-files =
|
||||
[test_DominatorTree_01.js]
|
||||
[test_DominatorTree_02.js]
|
||||
[test_DominatorTree_03.js]
|
||||
[test_DominatorTree_04.js]
|
||||
[test_HeapAnalyses_getCreationTime_01.js]
|
||||
[test_HeapAnalyses_readHeapSnapshot_01.js]
|
||||
[test_HeapAnalyses_takeCensusDiff_01.js]
|
||||
|
@ -4909,7 +4909,8 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
||||
}
|
||||
} else if (NS_ERROR_PHISHING_URI == aError ||
|
||||
NS_ERROR_MALWARE_URI == aError ||
|
||||
NS_ERROR_UNWANTED_URI == aError) {
|
||||
NS_ERROR_UNWANTED_URI == aError ||
|
||||
NS_ERROR_FORBIDDEN_URI == aError) {
|
||||
nsAutoCString host;
|
||||
aURI->GetHost(host);
|
||||
CopyUTF8toUTF16(host, formatStrs[0]);
|
||||
@ -4924,21 +4925,27 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
||||
}
|
||||
|
||||
uint32_t bucketId;
|
||||
bool sendTelemetry = false;
|
||||
if (NS_ERROR_PHISHING_URI == aError) {
|
||||
sendTelemetry = true;
|
||||
error.AssignLiteral("phishingBlocked");
|
||||
bucketId = IsFrame() ? nsISecurityUITelemetry::WARNING_PHISHING_PAGE_FRAME
|
||||
: nsISecurityUITelemetry::WARNING_PHISHING_PAGE_TOP;
|
||||
} else if (NS_ERROR_MALWARE_URI == aError) {
|
||||
sendTelemetry = true;
|
||||
error.AssignLiteral("malwareBlocked");
|
||||
bucketId = IsFrame() ? nsISecurityUITelemetry::WARNING_MALWARE_PAGE_FRAME
|
||||
: nsISecurityUITelemetry::WARNING_MALWARE_PAGE_TOP;
|
||||
} else {
|
||||
} else if (NS_ERROR_UNWANTED_URI == aError) {
|
||||
sendTelemetry = true;
|
||||
error.AssignLiteral("unwantedBlocked");
|
||||
bucketId = IsFrame() ? nsISecurityUITelemetry::WARNING_UNWANTED_PAGE_FRAME
|
||||
: nsISecurityUITelemetry::WARNING_UNWANTED_PAGE_TOP;
|
||||
} else if (NS_ERROR_FORBIDDEN_URI == aError) {
|
||||
error.AssignLiteral("forbiddenBlocked");
|
||||
}
|
||||
|
||||
if (errorPage.EqualsIgnoreCase("blocked")) {
|
||||
if (sendTelemetry && errorPage.EqualsIgnoreCase("blocked")) {
|
||||
Telemetry::Accumulate(Telemetry::SECURITY_UI, bucketId);
|
||||
}
|
||||
|
||||
@ -7699,6 +7706,7 @@ nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
|
||||
aStatus == NS_ERROR_MALWARE_URI ||
|
||||
aStatus == NS_ERROR_PHISHING_URI ||
|
||||
aStatus == NS_ERROR_UNWANTED_URI ||
|
||||
aStatus == NS_ERROR_FORBIDDEN_URI ||
|
||||
aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
|
||||
aStatus == NS_ERROR_REMOTE_XUL ||
|
||||
aStatus == NS_ERROR_INTERCEPTION_FAILED ||
|
||||
|
@ -295,6 +295,7 @@
|
||||
<h1 id="et_nssBadCert">&nssBadCert.title;</h1>
|
||||
<h1 id="et_malwareBlocked">&malwareBlocked.title;</h1>
|
||||
<h1 id="et_unwantedBlocked">&unwantedBlocked.title;</h1>
|
||||
<h1 id="et_forbiddenBlocked">&forbiddenBlocked.title;</h1>
|
||||
<h1 id="et_cspBlocked">&cspBlocked.title;</h1>
|
||||
<h1 id="et_remoteXUL">&remoteXUL.title;</h1>
|
||||
<h1 id="et_corruptedContentError">&corruptedContentError.title;</h1>
|
||||
@ -322,6 +323,7 @@
|
||||
<div id="ed_nssBadCert">&nssBadCert.longDesc2;</div>
|
||||
<div id="ed_malwareBlocked">&malwareBlocked.longDesc;</div>
|
||||
<div id="ed_unwantedBlocked">&unwantedBlocked.longDesc;</div>
|
||||
<div id="ed_forbiddenBlocked">&forbiddenBlocked.longDesc;</div>
|
||||
<div id="ed_cspBlocked">&cspBlocked.longDesc;</div>
|
||||
<div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
|
||||
<div id="ed_corruptedContentError">&corruptedContentError.longDesc;</div>
|
||||
|
@ -37,7 +37,7 @@ ArchiveReader::Constructor(const GlobalObject& aGlobal,
|
||||
nsAutoCString encoding;
|
||||
if (!EncodingUtils::FindEncodingForLabelNoReplacement(aOptions.mEncoding,
|
||||
encoding)) {
|
||||
aError.ThrowRangeError<MSG_ENCODING_NOT_SUPPORTED>(&aOptions.mEncoding);
|
||||
aError.ThrowRangeError<MSG_ENCODING_NOT_SUPPORTED>(aOptions.mEncoding);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -329,35 +329,6 @@ protected:
|
||||
void* mMappedMemory;
|
||||
};
|
||||
|
||||
class UnlockDirectoryRunnable final
|
||||
: public nsRunnable
|
||||
{
|
||||
RefPtr<DirectoryLock> mDirectoryLock;
|
||||
|
||||
public:
|
||||
explicit
|
||||
UnlockDirectoryRunnable(already_AddRefed<DirectoryLock> aDirectoryLock)
|
||||
: mDirectoryLock(Move(aDirectoryLock))
|
||||
{ }
|
||||
|
||||
private:
|
||||
~UnlockDirectoryRunnable()
|
||||
{
|
||||
MOZ_ASSERT(!mDirectoryLock);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mDirectoryLock);
|
||||
|
||||
mDirectoryLock = nullptr;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
// A runnable that implements a state machine required to open a cache entry.
|
||||
// It executes in the parent for a cache access originating in the child.
|
||||
// This runnable gets registered as an IPDL subprotocol actor so that it
|
||||
@ -503,6 +474,9 @@ private:
|
||||
nsresult
|
||||
InitOnMainThread();
|
||||
|
||||
void
|
||||
OpenDirectory();
|
||||
|
||||
nsresult
|
||||
ReadMetadata();
|
||||
|
||||
@ -518,7 +492,7 @@ private:
|
||||
void
|
||||
DispatchToIOThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
// If shutdown just started, the QuotaManager may have been deleted.
|
||||
QuotaManager* qm = QuotaManager::Get();
|
||||
@ -593,8 +567,8 @@ private:
|
||||
// A cache entry has been selected to open.
|
||||
|
||||
mModuleIndex = aModuleIndex;
|
||||
mState = eDispatchToMainThread;
|
||||
NS_DispatchToMainThread(this);
|
||||
mState = eReadyToOpenCacheFileForRead;
|
||||
DispatchToIOThread();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -630,12 +604,13 @@ private:
|
||||
|
||||
enum State {
|
||||
eInitial, // Just created, waiting to be dispatched to main thread
|
||||
eWaitingToFinishInit, // Waiting to finish initialization
|
||||
eWaitingToOpenDirectory, // Waiting to open directory
|
||||
eWaitingToOpenMetadata, // Waiting to be called back from OpenDirectory
|
||||
eReadyToReadMetadata, // Waiting to read the metadata file on the IO thread
|
||||
eFailedToReadMetadata, // Waiting to be dispatched to owning thread after fail
|
||||
eSendingMetadataForRead, // Waiting to send OnOpenMetadataForRead
|
||||
eWaitingToOpenCacheFileForRead, // Waiting to hear back from child
|
||||
eDispatchToMainThread, // IO thread dispatch allowed from main thread only
|
||||
eReadyToOpenCacheFileForRead, // Waiting to open cache file for read
|
||||
eSendingCacheFile, // Waiting to send OnOpenCacheFile on the owning thread
|
||||
eOpened, // Finished calling OnOpenCacheFile, waiting to be closed
|
||||
@ -711,9 +686,6 @@ ParentRunnable::InitOnMainThread()
|
||||
return rv;
|
||||
}
|
||||
|
||||
QuotaManager* qm = QuotaManager::GetOrCreate();
|
||||
NS_ENSURE_STATE(qm);
|
||||
|
||||
rv = QuotaManager::GetInfoFromPrincipal(principal, &mGroup, &mOrigin,
|
||||
&mIsApp);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -726,6 +698,26 @@ ParentRunnable::InitOnMainThread()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ParentRunnable::OpenDirectory()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mState == eWaitingToFinishInit ||
|
||||
mState == eWaitingToOpenDirectory);
|
||||
MOZ_ASSERT(QuotaManager::Get());
|
||||
|
||||
mState = eWaitingToOpenMetadata;
|
||||
|
||||
// XXX The exclusive lock shouldn't be needed for read operations.
|
||||
QuotaManager::Get()->OpenDirectory(mPersistence,
|
||||
mGroup,
|
||||
mOrigin,
|
||||
mIsApp,
|
||||
quota::Client::ASMJS,
|
||||
/* aExclusive */ true,
|
||||
this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
ParentRunnable::ReadMetadata()
|
||||
{
|
||||
@ -903,12 +895,7 @@ ParentRunnable::FinishOnOwningThread()
|
||||
// releasing the directory lock.
|
||||
FileDescriptorHolder::Finish();
|
||||
|
||||
if (mDirectoryLock) {
|
||||
RefPtr<UnlockDirectoryRunnable> runnable =
|
||||
new UnlockDirectoryRunnable(mDirectoryLock.forget());
|
||||
|
||||
NS_DispatchToMainThread(runnable);
|
||||
}
|
||||
mDirectoryLock = nullptr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -928,17 +915,41 @@ ParentRunnable::Run()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mState = eWaitingToOpenMetadata;
|
||||
mState = eWaitingToFinishInit;
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||
mOwningThread->Dispatch(this, NS_DISPATCH_NORMAL)));
|
||||
|
||||
// XXX The exclusive lock shouldn't be needed for read operations.
|
||||
QuotaManager::Get()->OpenDirectory(mPersistence,
|
||||
mGroup,
|
||||
mOrigin,
|
||||
mIsApp,
|
||||
quota::Client::ASMJS,
|
||||
/* aExclusive */ true,
|
||||
this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case eWaitingToFinishInit: {
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (QuotaManager::IsShuttingDown()) {
|
||||
Fail();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (QuotaManager::Get()) {
|
||||
OpenDirectory();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mState = eWaitingToOpenDirectory;
|
||||
QuotaManager::GetOrCreate(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case eWaitingToOpenDirectory: {
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (NS_WARN_IF(!QuotaManager::Get())) {
|
||||
Fail();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
OpenDirectory();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -999,14 +1010,6 @@ ParentRunnable::Run()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case eDispatchToMainThread: {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mState = eReadyToOpenCacheFileForRead;
|
||||
DispatchToIOThread();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case eReadyToOpenCacheFileForRead: {
|
||||
AssertIsOnIOThread();
|
||||
MOZ_ASSERT(mOpenMode == eOpenForRead);
|
||||
@ -1064,7 +1067,7 @@ ParentRunnable::Run()
|
||||
void
|
||||
ParentRunnable::DirectoryLockAcquired(DirectoryLock* aLock)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mState == eWaitingToOpenMetadata);
|
||||
MOZ_ASSERT(!mDirectoryLock);
|
||||
|
||||
@ -1077,11 +1080,11 @@ ParentRunnable::DirectoryLockAcquired(DirectoryLock* aLock)
|
||||
void
|
||||
ParentRunnable::DirectoryLockFailed()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mState == eWaitingToOpenMetadata);
|
||||
MOZ_ASSERT(!mDirectoryLock);
|
||||
|
||||
FailOnNonOwningThread();
|
||||
Fail();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(ParentRunnable, FileDescriptorHolder)
|
||||
@ -1812,7 +1815,11 @@ public:
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
PerformIdleMaintenance() override
|
||||
StartIdleMaintenance() override
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
StopIdleMaintenance() override
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
|
@ -305,14 +305,13 @@ AutoJSAPI::AutoJSAPI()
|
||||
: mCx(nullptr)
|
||||
, mOwnErrorReporting(false)
|
||||
, mOldAutoJSAPIOwnsErrorReporting(false)
|
||||
, mIsMainThread(false) // For lack of anything better
|
||||
{
|
||||
}
|
||||
|
||||
AutoJSAPI::~AutoJSAPI()
|
||||
{
|
||||
if (mOwnErrorReporting) {
|
||||
MOZ_ASSERT(NS_IsMainThread(), "See corresponding assertion in TakeOwnershipOfErrorReporting()");
|
||||
|
||||
ReportException();
|
||||
|
||||
// We need to do this _after_ processing the existing exception, because the
|
||||
@ -332,7 +331,10 @@ void
|
||||
AutoJSAPI::InitInternal(JSObject* aGlobal, JSContext* aCx, bool aIsMainThread)
|
||||
{
|
||||
MOZ_ASSERT(aCx);
|
||||
MOZ_ASSERT(aIsMainThread == NS_IsMainThread());
|
||||
|
||||
mCx = aCx;
|
||||
mIsMainThread = aIsMainThread;
|
||||
if (aIsMainThread) {
|
||||
// This Rooted<> is necessary only as long as AutoCxPusher::AutoCxPusher
|
||||
// can GC, which is only possible because XPCJSContextStack::Push calls
|
||||
@ -357,11 +359,12 @@ AutoJSAPI::AutoJSAPI(nsIGlobalObject* aGlobalObject,
|
||||
JSContext* aCx)
|
||||
: mOwnErrorReporting(false)
|
||||
, mOldAutoJSAPIOwnsErrorReporting(false)
|
||||
, mIsMainThread(aIsMainThread)
|
||||
{
|
||||
MOZ_ASSERT(aGlobalObject);
|
||||
MOZ_ASSERT(aGlobalObject->GetGlobalJSObject(), "Must have a JS global");
|
||||
MOZ_ASSERT(aCx);
|
||||
MOZ_ASSERT_IF(aIsMainThread, NS_IsMainThread());
|
||||
MOZ_ASSERT(aIsMainThread == NS_IsMainThread());
|
||||
|
||||
InitInternal(aGlobalObject->GetGlobalJSObject(), aCx, aIsMainThread);
|
||||
}
|
||||
@ -460,7 +463,9 @@ AutoJSAPI::InitWithLegacyErrorReporting(nsGlobalWindow* aWindow)
|
||||
void
|
||||
WarningOnlyErrorReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aRep)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(JSREPORT_IS_WARNING(aRep->flags));
|
||||
|
||||
RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
nsPIDOMWindow* win = xpc::CurrentWindowOrNull(aCx);
|
||||
xpcReport->Init(aRep, aMessage, nsContentUtils::IsCallerChrome(),
|
||||
@ -471,14 +476,19 @@ WarningOnlyErrorReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aR
|
||||
void
|
||||
AutoJSAPI::TakeOwnershipOfErrorReporting()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Can't own error reporting off-main-thread yet");
|
||||
MOZ_ASSERT(!mOwnErrorReporting);
|
||||
mOwnErrorReporting = true;
|
||||
|
||||
JSRuntime *rt = JS_GetRuntime(cx());
|
||||
mOldAutoJSAPIOwnsErrorReporting = JS::ContextOptionsRef(cx()).autoJSAPIOwnsErrorReporting();
|
||||
JS::ContextOptionsRef(cx()).setAutoJSAPIOwnsErrorReporting(true);
|
||||
JS_SetErrorReporter(rt, WarningOnlyErrorReporter);
|
||||
// Workers have their own error reporting mechanism which deals with warnings
|
||||
// as well, so don't change the worker error reporter for now. Once we switch
|
||||
// all of workers to TakeOwnershipOfErrorReporting(), we will just make the
|
||||
// default worker error reporter assert that it only sees warnings.
|
||||
if (mIsMainThread) {
|
||||
JS_SetErrorReporter(rt, WarningOnlyErrorReporter);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -498,18 +508,35 @@ AutoJSAPI::ReportException()
|
||||
if (!errorGlobal)
|
||||
errorGlobal = xpc::PrivilegedJunkScope();
|
||||
JSAutoCompartment ac(cx(), errorGlobal);
|
||||
nsCOMPtr<nsPIDOMWindow> win = xpc::WindowGlobalOrNull(errorGlobal);
|
||||
JS::Rooted<JS::Value> exn(cx());
|
||||
js::ErrorReport jsReport(cx());
|
||||
if (StealException(&exn) && jsReport.init(cx(), exn)) {
|
||||
RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
xpcReport->Init(jsReport.report(), jsReport.message(),
|
||||
nsContentUtils::IsCallerChrome(),
|
||||
win ? win->WindowID() : 0);
|
||||
if (win) {
|
||||
DispatchScriptErrorEvent(win, JS_GetRuntime(cx()), xpcReport, exn);
|
||||
if (mIsMainThread) {
|
||||
RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
nsCOMPtr<nsPIDOMWindow> win = xpc::WindowGlobalOrNull(errorGlobal);
|
||||
xpcReport->Init(jsReport.report(), jsReport.message(),
|
||||
nsContentUtils::IsCallerChrome(),
|
||||
win ? win->WindowID() : 0);
|
||||
if (win) {
|
||||
DispatchScriptErrorEvent(win, JS_GetRuntime(cx()), xpcReport, exn);
|
||||
} else {
|
||||
xpcReport->LogToConsole();
|
||||
}
|
||||
} else {
|
||||
xpcReport->LogToConsole();
|
||||
// On a worker, we just use the worker error reporting mechanism and don't
|
||||
// bother with xpc::ErrorReport. This will ensure that all the right
|
||||
// events (which are a lot more complicated than in the window case) get
|
||||
// fired.
|
||||
workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(worker);
|
||||
MOZ_ASSERT(worker->GetJSContext() == cx());
|
||||
// Before invoking ReportError, put the exception back on the context,
|
||||
// because it may want to put it in its error events and has no other way
|
||||
// to get hold of it. After we invoke ReportError, clear the exception on
|
||||
// cx(), just in case ReportError didn't.
|
||||
JS_SetPendingException(cx(), exn);
|
||||
worker->ReportError(cx(), jsReport.message(), jsReport.report());
|
||||
ClearException();
|
||||
}
|
||||
} else {
|
||||
NS_WARNING("OOMed while acquiring uncaught exception from JSAPI");
|
||||
@ -519,7 +546,7 @@ AutoJSAPI::ReportException()
|
||||
bool
|
||||
AutoJSAPI::StealException(JS::MutableHandle<JS::Value> aVal)
|
||||
{
|
||||
MOZ_ASSERT(CxPusherIsStackTop());
|
||||
MOZ_ASSERT_IF(mIsMainThread, CxPusherIsStackTop());
|
||||
MOZ_ASSERT(HasException());
|
||||
MOZ_ASSERT(js::GetContextCompartment(cx()));
|
||||
if (!JS_GetPendingException(cx(), aVal)) {
|
||||
|
@ -262,7 +262,7 @@ public:
|
||||
|
||||
JSContext* cx() const {
|
||||
MOZ_ASSERT(mCx, "Must call Init before using an AutoJSAPI");
|
||||
MOZ_ASSERT_IF(NS_IsMainThread(), CxPusherIsStackTop());
|
||||
MOZ_ASSERT_IF(mIsMainThread, CxPusherIsStackTop());
|
||||
return mCx;
|
||||
}
|
||||
|
||||
@ -279,7 +279,7 @@ public:
|
||||
void ReportException();
|
||||
|
||||
bool HasException() const {
|
||||
MOZ_ASSERT(CxPusherIsStackTop());
|
||||
MOZ_ASSERT_IF(NS_IsMainThread(), CxPusherIsStackTop());
|
||||
return JS_IsExceptionPending(cx());
|
||||
};
|
||||
|
||||
@ -292,7 +292,7 @@ public:
|
||||
bool StealException(JS::MutableHandle<JS::Value> aVal);
|
||||
|
||||
void ClearException() {
|
||||
MOZ_ASSERT(CxPusherIsStackTop());
|
||||
MOZ_ASSERT_IF(NS_IsMainThread(), CxPusherIsStackTop());
|
||||
JS_ClearPendingException(cx());
|
||||
}
|
||||
|
||||
@ -312,6 +312,8 @@ private:
|
||||
// Track state between the old and new error reporting modes.
|
||||
bool mOwnErrorReporting;
|
||||
bool mOldAutoJSAPIOwnsErrorReporting;
|
||||
// Whether we're mainthread or not; set when we're initialized.
|
||||
bool mIsMainThread;
|
||||
Maybe<JSErrorReporter> mOldErrorReporter;
|
||||
|
||||
void InitInternal(JSObject* aGlobal, JSContext* aCx, bool aIsMainThread);
|
||||
|
@ -78,7 +78,7 @@ URL::Constructor(nsISupports* aParent, const nsAString& aUrl,
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(baseUri), aBase, nullptr, nullptr,
|
||||
nsContentUtils::GetIOService());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.ThrowTypeError<MSG_INVALID_URL>(&aBase);
|
||||
aRv.ThrowTypeError<MSG_INVALID_URL>(aBase);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -94,7 +94,7 @@ URL::Constructor(nsISupports* aParent, const nsAString& aUrl, nsIURI* aBase,
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, nullptr, aBase,
|
||||
nsContentUtils::GetIOService());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRv.ThrowTypeError<MSG_INVALID_URL>(&aUrl);
|
||||
aRv.ThrowTypeError<MSG_INVALID_URL>(aUrl);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -229,8 +229,7 @@ URL::SetHref(const nsAString& aHref, ErrorResult& aRv)
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = ioService->NewURI(href, nullptr, nullptr, getter_AddRefs(uri));
|
||||
if (NS_FAILED(rv)) {
|
||||
nsAutoString label(aHref);
|
||||
aRv.ThrowTypeError<MSG_INVALID_URL>(&label);
|
||||
aRv.ThrowTypeError<MSG_INVALID_URL>(aHref);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ WindowNamedPropertiesHandler::defineProperty(JSContext* aCx,
|
||||
{
|
||||
ErrorResult rv;
|
||||
rv.ThrowTypeError<MSG_DEFINEPROPERTY_ON_GSP>();
|
||||
rv.ReportErrorWithMessage(aCx);
|
||||
rv.MaybeSetPendingException(aCx);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5115,19 +5115,17 @@ nsDocument::DocumentStatesChanged(EventStates aStateMask)
|
||||
|
||||
void
|
||||
nsDocument::StyleRuleChanged(CSSStyleSheet* aSheet,
|
||||
css::Rule* aOldStyleRule,
|
||||
css::Rule* aNewStyleRule)
|
||||
css::Rule* aStyleRule)
|
||||
{
|
||||
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleChanged,
|
||||
(this, aSheet,
|
||||
aOldStyleRule, aNewStyleRule));
|
||||
aStyleRule));
|
||||
|
||||
if (StyleSheetChangeEventsEnabled()) {
|
||||
DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent,
|
||||
"StyleRuleChanged",
|
||||
mRule,
|
||||
aNewStyleRule ? aNewStyleRule->GetDOMRule()
|
||||
: nullptr);
|
||||
aStyleRule ? aStyleRule->GetDOMRule() : nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -884,8 +884,7 @@ public:
|
||||
mozilla::EventStates aStateMask) override;
|
||||
|
||||
virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet,
|
||||
mozilla::css::Rule* aOldStyleRule,
|
||||
mozilla::css::Rule* aNewStyleRule) override;
|
||||
mozilla::css::Rule* aStyleRule) override;
|
||||
virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet,
|
||||
mozilla::css::Rule* aStyleRule) override;
|
||||
virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet,
|
||||
|
@ -6138,10 +6138,12 @@ nsGlobalWindow::FinishFullscreenChange(bool aIsFullscreen)
|
||||
mWakeLock = pmService->NewWakeLock(NS_LITERAL_STRING("DOM_Fullscreen"),
|
||||
this, rv);
|
||||
NS_WARN_IF_FALSE(!rv.Failed(), "Failed to lock the wakelock");
|
||||
rv.SuppressException();
|
||||
} else if (mWakeLock && !mFullScreen) {
|
||||
ErrorResult rv;
|
||||
mWakeLock->Unlock(rv);
|
||||
mWakeLock = nullptr;
|
||||
rv.SuppressException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -11764,6 +11766,7 @@ nsGlobalWindow::RunTimeoutHandler(nsTimeout* aTimeout,
|
||||
ErrorResult ignored;
|
||||
JS::Rooted<JS::Value> ignoredVal(CycleCollectedJSRuntime::Get()->Runtime());
|
||||
callback->Call(me, handler->GetArgs(), &ignoredVal, ignored, reason);
|
||||
ignored.SuppressException();
|
||||
}
|
||||
|
||||
// We ignore any failures from calling EvaluateString() on the context or
|
||||
|
@ -1131,7 +1131,10 @@ public:
|
||||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
mozilla::ErrorResult ignored;
|
||||
return GetContentInternal(ignored, /* aUnprivilegedCaller = */ false);
|
||||
nsCOMPtr<nsIDOMWindow> win =
|
||||
GetContentInternal(ignored, /* aUnprivilegedCaller = */ false);
|
||||
ignored.SuppressException();
|
||||
return win.forget();
|
||||
}
|
||||
|
||||
void Get_content(JSContext* aCx,
|
||||
|
@ -49,19 +49,19 @@ public:
|
||||
const nsTArray<nsString>& aStringParams) = 0;
|
||||
|
||||
// A version of AddConsoleReport() that accepts the message parameters
|
||||
// as variable nsString arguments. Note, the parameters must be exactly
|
||||
// nsString and not another string class. All other args the same as
|
||||
// AddConsoleReport().
|
||||
// as variable nsString arguments (or really, any sort of const nsAString).
|
||||
// All other args the same as AddConsoleReport().
|
||||
template<typename... Params>
|
||||
void
|
||||
AddConsoleReport(uint32_t aErrorFlags, const nsACString& aCategory,
|
||||
nsContentUtils::PropertiesFile aPropertiesFile,
|
||||
const nsACString& aSourceFileURI, uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber, const nsACString& aMessageName,
|
||||
Params... aParams)
|
||||
Params&&... aParams)
|
||||
{
|
||||
nsTArray<nsString> params;
|
||||
mozilla::dom::StringArrayAppender::Append(params, sizeof...(Params), aParams...);
|
||||
mozilla::dom::StringArrayAppender::Append(params, sizeof...(Params),
|
||||
mozilla::Forward<Params>(aParams)...);
|
||||
AddConsoleReport(aErrorFlags, aCategory, aPropertiesFile, aSourceFileURI,
|
||||
aLineNumber, aColumnNumber, aMessageName, params);
|
||||
}
|
||||
|
@ -155,8 +155,8 @@ typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
|
||||
} // namespace mozilla
|
||||
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0xecc9e376, 0x6c31, 0x4f04, \
|
||||
{ 0xbe, 0xde, 0xd6, 0x27, 0x61, 0xd7, 0x00, 0x84 } }
|
||||
{ 0x13011a82, 0x46cd, 0x4c33, \
|
||||
{ 0x9d, 0x4e, 0x31, 0x41, 0xbb, 0x3f, 0x18, 0xe9 } }
|
||||
|
||||
// Enum for requesting a particular type of document when creating a doc
|
||||
enum DocumentFlavor {
|
||||
@ -1290,8 +1290,7 @@ public:
|
||||
// Observation hooks for style data to propagate notifications
|
||||
// to document observers
|
||||
virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet,
|
||||
mozilla::css::Rule* aOldStyleRule,
|
||||
mozilla::css::Rule* aNewStyleRule) = 0;
|
||||
mozilla::css::Rule* aStyleRule) = 0;
|
||||
virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet,
|
||||
mozilla::css::Rule* aStyleRule) = 0;
|
||||
virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet,
|
||||
|
@ -21,8 +21,8 @@ class Rule;
|
||||
} // namespace mozilla
|
||||
|
||||
#define NS_IDOCUMENT_OBSERVER_IID \
|
||||
{ 0x21c8ad67, 0x3a7d, 0x4881, \
|
||||
{ 0xa5, 0x43, 0xcb, 0xa9, 0xbb, 0xe4, 0x9e, 0x39 } }
|
||||
{ 0x71041fa3, 0x6dd7, 0x4cde, \
|
||||
{ 0xbb, 0x76, 0xae, 0xcc, 0x69, 0xe1, 0x75, 0x78 } }
|
||||
|
||||
typedef uint32_t nsUpdateType;
|
||||
|
||||
@ -143,26 +143,13 @@ public:
|
||||
* the document. The notification is passed on to all of
|
||||
* the document observers.
|
||||
*
|
||||
* Since nsIStyleRule objects are immutable, there is a new object
|
||||
* replacing the old one. However, the use of this method (rather
|
||||
* than StyleRuleAdded and StyleRuleRemoved) implies that the new rule
|
||||
* matches the same elements and has the same priority (weight,
|
||||
* origin, specificity) as the old one. (However, if it is a CSS
|
||||
* style rule, there may be a change in whether it has an important
|
||||
* rule.)
|
||||
*
|
||||
* @param aDocument The document being observed
|
||||
* @param aStyleSheet the StyleSheet that contians the rule
|
||||
* @param aOldStyleRule The rule being removed. This rule may not be
|
||||
* fully valid anymore -- however, it can still
|
||||
* be used for pointer comparison and
|
||||
* |QueryInterface|.
|
||||
* @param aNewStyleRule The rule being added.
|
||||
* @param aStyleRule The rule being changed.
|
||||
*/
|
||||
virtual void StyleRuleChanged(nsIDocument *aDocument,
|
||||
mozilla::CSSStyleSheet* aStyleSheet,
|
||||
mozilla::css::Rule* aOldStyleRule,
|
||||
mozilla::css::Rule* aNewStyleRule) = 0;
|
||||
mozilla::css::Rule* aStyleRule) = 0;
|
||||
|
||||
/**
|
||||
* A StyleRule has just been added to a style sheet.
|
||||
@ -238,8 +225,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentObserver, NS_IDOCUMENT_OBSERVER_IID)
|
||||
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULECHANGED \
|
||||
virtual void StyleRuleChanged(nsIDocument* aDocument, \
|
||||
mozilla::CSSStyleSheet* aStyleSheet, \
|
||||
mozilla::css::Rule* aOldStyleRule, \
|
||||
mozilla::css::Rule* aNewStyleRule) override;
|
||||
mozilla::css::Rule* aStyleRule) override;
|
||||
|
||||
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEADDED \
|
||||
virtual void StyleRuleAdded(nsIDocument* aDocument, \
|
||||
@ -327,8 +313,7 @@ _class::StyleSheetApplicableStateChanged(nsIDocument* aDocument, \
|
||||
void \
|
||||
_class::StyleRuleChanged(nsIDocument* aDocument, \
|
||||
mozilla::CSSStyleSheet* aStyleSheet, \
|
||||
mozilla::css::Rule* aOldStyleRule, \
|
||||
mozilla::css::Rule* aNewStyleRule) \
|
||||
mozilla::css::Rule* aStyleRule) \
|
||||
{ \
|
||||
} \
|
||||
void \
|
||||
|
@ -272,6 +272,8 @@ skip-if = buildapp == 'b2g' # Requires webgl support
|
||||
[test_audioWindowUtils.html]
|
||||
[test_audioNotification.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_audioNotificationStream.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_audioNotificationStopOnNavigation.html]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_audioNotificationWithEarlyPlay.html]
|
||||
|
71
dom/base/test/test_audioNotificationStream.html
Normal file
71
dom/base/test/test_audioNotificationStream.html
Normal file
@ -0,0 +1,71 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for audio controller in windows</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var expectedNotification = null;
|
||||
|
||||
var observer = {
|
||||
observe: function(subject, topic, data) {
|
||||
is(topic, "audio-playback", "audio-playback received");
|
||||
is(data, expectedNotification, "This is the right notification");
|
||||
runTest();
|
||||
}
|
||||
};
|
||||
|
||||
var observerService = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIObserverService);
|
||||
|
||||
var audio = new Audio();
|
||||
audio.srcObject = (new AudioContext()).createMediaStreamDestination().stream;
|
||||
|
||||
var tests = [
|
||||
function() {
|
||||
observerService.addObserver(observer, "audio-playback", false);
|
||||
ok(true, "Observer set");
|
||||
runTest();
|
||||
},
|
||||
|
||||
function() {
|
||||
expectedNotification = 'active';
|
||||
audio.play();
|
||||
},
|
||||
|
||||
function() {
|
||||
expectedNotification = 'inactive';
|
||||
audio.pause();
|
||||
},
|
||||
|
||||
function() {
|
||||
observerService.removeObserver(observer, "audio-playback");
|
||||
ok(true, "Observer removed");
|
||||
runTest();
|
||||
}
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
runTest();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -139,23 +139,10 @@ public:
|
||||
}
|
||||
|
||||
// Return InternalType here so we can work with it usefully.
|
||||
InternalType& Construct()
|
||||
template<typename... Args>
|
||||
InternalType& Construct(Args&&... aArgs)
|
||||
{
|
||||
mImpl.emplace();
|
||||
return *mImpl;
|
||||
}
|
||||
|
||||
template <class T1>
|
||||
InternalType& Construct(const T1 &t1)
|
||||
{
|
||||
mImpl.emplace(t1);
|
||||
return *mImpl;
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
InternalType& Construct(const T1 &t1, const T2 &t2)
|
||||
{
|
||||
mImpl.emplace(t1, t2);
|
||||
mImpl.emplace(Forward<Args>(aArgs)...);
|
||||
return *mImpl;
|
||||
}
|
||||
|
||||
|
@ -125,38 +125,6 @@ ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
|
||||
NamesOfInterfacesWithProtos(aProtoId));
|
||||
}
|
||||
|
||||
bool
|
||||
ThrowMethodFailed(JSContext* cx, ErrorResult& rv)
|
||||
{
|
||||
if (rv.IsUncatchableException()) {
|
||||
// Nuke any existing exception on aCx, to make sure we're uncatchable.
|
||||
JS_ClearPendingException(cx);
|
||||
// Don't do any reporting. Just return false, to create an
|
||||
// uncatchable exception.
|
||||
return false;
|
||||
}
|
||||
if (rv.IsJSContextException()) {
|
||||
// Whatever we need to throw is on the JSContext already. We
|
||||
// can't assert that there is a pending exception on it, though,
|
||||
// because in the uncatchable exception case there won't be one.
|
||||
return false;
|
||||
}
|
||||
if (rv.IsErrorWithMessage()) {
|
||||
rv.ReportErrorWithMessage(cx);
|
||||
return false;
|
||||
}
|
||||
if (rv.IsJSException()) {
|
||||
rv.ReportJSException(cx);
|
||||
return false;
|
||||
}
|
||||
if (rv.IsDOMException()) {
|
||||
rv.ReportDOMException(cx);
|
||||
return false;
|
||||
}
|
||||
rv.ReportGenericError(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ThrowNoSetterArg(JSContext* aCx, prototypes::ID aProtoId)
|
||||
{
|
||||
@ -222,9 +190,9 @@ ErrorResult::DeserializeMessage(const IPC::Message* aMsg, void** aIter)
|
||||
}
|
||||
|
||||
void
|
||||
ErrorResult::ReportErrorWithMessage(JSContext* aCx)
|
||||
ErrorResult::SetPendingExceptionWithMessage(JSContext* aCx)
|
||||
{
|
||||
MOZ_ASSERT(mMessage, "ReportErrorWithMessage() can be called only once");
|
||||
MOZ_ASSERT(mMessage, "SetPendingExceptionWithMessage() can be called only once");
|
||||
MOZ_ASSERT(mUnionState == HasMessage);
|
||||
|
||||
Message* message = mMessage;
|
||||
@ -241,6 +209,7 @@ ErrorResult::ReportErrorWithMessage(JSContext* aCx)
|
||||
argCount > 0 ? args : nullptr);
|
||||
|
||||
ClearMessage();
|
||||
mResult = NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
@ -280,7 +249,7 @@ ErrorResult::ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn)
|
||||
}
|
||||
|
||||
void
|
||||
ErrorResult::ReportJSException(JSContext* cx)
|
||||
ErrorResult::SetPendingJSException(JSContext* cx)
|
||||
{
|
||||
MOZ_ASSERT(!mMightHaveUnreportedJSException,
|
||||
"Why didn't you tell us you planned to handle JS exceptions?");
|
||||
@ -295,25 +264,6 @@ ErrorResult::ReportJSException(JSContext* cx)
|
||||
// what, go ahead and unroot mJSException.
|
||||
js::RemoveRawValueRoot(cx, &mJSException);
|
||||
|
||||
// We no longer have a useful exception but we do want to signal that an error
|
||||
// occured.
|
||||
mResult = NS_ERROR_FAILURE;
|
||||
#ifdef DEBUG
|
||||
mUnionState = HasNothing;
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
void
|
||||
ErrorResult::StealJSException(JSContext* cx,
|
||||
JS::MutableHandle<JS::Value> value)
|
||||
{
|
||||
MOZ_ASSERT(!mMightHaveUnreportedJSException,
|
||||
"Must call WouldReportJSException unconditionally in all codepaths that might call StealJSException");
|
||||
MOZ_ASSERT(IsJSException(), "No exception to steal");
|
||||
MOZ_ASSERT(mUnionState == HasJSException);
|
||||
|
||||
value.set(mJSException);
|
||||
js::RemoveRawValueRoot(cx, &mJSException);
|
||||
mResult = NS_OK;
|
||||
#ifdef DEBUG
|
||||
mUnionState = HasNothing;
|
||||
@ -373,14 +323,16 @@ ErrorResult::ThrowDOMException(nsresult rv, const nsACString& message)
|
||||
}
|
||||
|
||||
void
|
||||
ErrorResult::ReportDOMException(JSContext* cx)
|
||||
ErrorResult::SetPendingDOMException(JSContext* cx)
|
||||
{
|
||||
MOZ_ASSERT(mDOMExceptionInfo, "ReportDOMException() can be called only once");
|
||||
MOZ_ASSERT(mDOMExceptionInfo,
|
||||
"SetPendingDOMException() can be called only once");
|
||||
MOZ_ASSERT(mUnionState == HasDOMExceptionInfo);
|
||||
|
||||
dom::Throw(cx, mDOMExceptionInfo->mRv, mDOMExceptionInfo->mMessage);
|
||||
|
||||
ClearDOMExceptionInfo();
|
||||
mResult = NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
@ -414,12 +366,13 @@ ErrorResult::ClearUnionData()
|
||||
}
|
||||
|
||||
void
|
||||
ErrorResult::ReportGenericError(JSContext* cx)
|
||||
ErrorResult::SetPendingGenericErrorException(JSContext* cx)
|
||||
{
|
||||
MOZ_ASSERT(!IsErrorWithMessage());
|
||||
MOZ_ASSERT(!IsJSException());
|
||||
MOZ_ASSERT(!IsDOMException());
|
||||
dom::Throw(cx, ErrorCode());
|
||||
mResult = NS_OK;
|
||||
}
|
||||
|
||||
ErrorResult&
|
||||
@ -508,6 +461,39 @@ ErrorResult::SuppressException()
|
||||
mResult = NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ErrorResult::SetPendingException(JSContext* cx)
|
||||
{
|
||||
if (IsUncatchableException()) {
|
||||
// Nuke any existing exception on cx, to make sure we're uncatchable.
|
||||
JS_ClearPendingException(cx);
|
||||
// Don't do any reporting. Just return, to create an
|
||||
// uncatchable exception.
|
||||
mResult = NS_OK;
|
||||
return;
|
||||
}
|
||||
if (IsJSContextException()) {
|
||||
// Whatever we need to throw is on the JSContext already. We
|
||||
// can't assert that there is a pending exception on it, though,
|
||||
// because in the uncatchable exception case there won't be one.
|
||||
mResult = NS_OK;
|
||||
return;
|
||||
}
|
||||
if (IsErrorWithMessage()) {
|
||||
SetPendingExceptionWithMessage(cx);
|
||||
return;
|
||||
}
|
||||
if (IsJSException()) {
|
||||
SetPendingJSException(cx);
|
||||
return;
|
||||
}
|
||||
if (IsDOMException()) {
|
||||
SetPendingDOMException(cx);
|
||||
return;
|
||||
}
|
||||
SetPendingGenericErrorException(cx);
|
||||
}
|
||||
|
||||
namespace dom {
|
||||
|
||||
bool
|
||||
@ -2777,10 +2763,10 @@ ConvertExceptionToPromise(JSContext* cx,
|
||||
JS_ClearPendingException(cx);
|
||||
ErrorResult rv;
|
||||
RefPtr<Promise> promise = Promise::Reject(global, exn, rv);
|
||||
if (rv.Failed()) {
|
||||
// We just give up. Make sure to not leak memory on the
|
||||
// ErrorResult, but then just put the original exception back.
|
||||
ThrowMethodFailed(cx, rv);
|
||||
if (rv.MaybeSetPendingException(cx)) {
|
||||
// We just give up. We put the exception from the ErrorResult on
|
||||
// the JSContext just to make sure to not leak memory on the
|
||||
// ErrorResult, but now just put the original exception back.
|
||||
JS_SetPendingException(cx, exn);
|
||||
return false;
|
||||
}
|
||||
|
@ -92,9 +92,6 @@ ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
|
||||
const ErrNum aErrorNumber,
|
||||
prototypes::ID aProtoId);
|
||||
|
||||
bool
|
||||
ThrowMethodFailed(JSContext* cx, ErrorResult& rv);
|
||||
|
||||
// Returns true if the JSClass is used for DOM objects.
|
||||
inline bool
|
||||
IsDOMClass(const JSClass* clasp)
|
||||
|
@ -1663,11 +1663,7 @@ class CGClassConstructor(CGAbstractStaticMethod):
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
JS::Rooted<JSObject*> obj(cx, &args.callee());
|
||||
$*{chromeOnlyCheck}
|
||||
bool mayInvoke = args.isConstructing();
|
||||
#ifdef RELEASE_BUILD
|
||||
mayInvoke = mayInvoke || nsContentUtils::ThreadsafeIsCallerChrome();
|
||||
#endif // RELEASE_BUILD
|
||||
if (!mayInvoke) {
|
||||
if (!args.isConstructing()) {
|
||||
// XXXbz wish I could get the name from the callee instead of
|
||||
// Adding more relocations
|
||||
return ThrowConstructorWithoutNew(cx, "${ctorName}");
|
||||
@ -1728,9 +1724,7 @@ class CGConstructNavigatorObject(CGAbstractMethod):
|
||||
JS::Rooted<JS::Value> v(aCx);
|
||||
{ // Scope to make sure |result| goes out of scope while |v| is rooted
|
||||
RefPtr<mozilla::dom::${descriptorName}> result = ConstructNavigatorObjectHelper(aCx, global, rv);
|
||||
rv.WouldReportJSException();
|
||||
if (rv.Failed()) {
|
||||
ThrowMethodFailed(aCx, rv);
|
||||
if (rv.MaybeSetPendingException(aCx)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!GetOrCreateDOMReflector(aCx, result, &v)) {
|
||||
@ -5101,8 +5095,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
}
|
||||
ErrorResult promiseRv;
|
||||
$${declName} = Promise::Resolve(promiseGlobal, $${val}, promiseRv);
|
||||
if (promiseRv.Failed()) {
|
||||
ThrowMethodFailed(cx, promiseRv);
|
||||
if (promiseRv.MaybeSetPendingException(cx)) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
}
|
||||
@ -6274,21 +6267,14 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
||||
resultLoc = result
|
||||
conversion = fill(
|
||||
"""
|
||||
{
|
||||
// Scope for resultStr
|
||||
MOZ_ASSERT(uint32_t(${result}) < ArrayLength(${strings}));
|
||||
JSString* resultStr = JS_NewStringCopyN(cx, ${strings}[uint32_t(${result})].value, ${strings}[uint32_t(${result})].length);
|
||||
if (!resultStr) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
$*{setResultStr}
|
||||
if (!ToJSValue(cx, ${result}, $${jsvalHandle})) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
$*{successCode}
|
||||
""",
|
||||
result=resultLoc,
|
||||
strings=(type.unroll().inner.identifier.name + "Values::" +
|
||||
ENUM_ENTRY_VARIABLE_NAME),
|
||||
exceptionCode=exceptionCode,
|
||||
setResultStr=setString("resultStr"))
|
||||
successCode=successCode)
|
||||
|
||||
if type.nullable():
|
||||
conversion = CGIfElseWrapper(
|
||||
@ -6664,23 +6650,18 @@ class CGCallGenerator(CGThing):
|
||||
A class to generate an actual call to a C++ object. Assumes that the C++
|
||||
object is stored in a variable whose name is given by the |object| argument.
|
||||
|
||||
errorReport should be a CGThing for an error report or None if no
|
||||
error reporting is needed.
|
||||
isFallible is a boolean indicating whether the call should be fallible.
|
||||
|
||||
resultVar: If the returnType is not void, then the result of the call is
|
||||
stored in a C++ variable named by resultVar. The caller is responsible for
|
||||
declaring the result variable. If the caller doesn't care about the result
|
||||
value, resultVar can be omitted.
|
||||
"""
|
||||
def __init__(self, errorReport, arguments, argsPre, returnType,
|
||||
def __init__(self, isFallible, arguments, argsPre, returnType,
|
||||
extendedAttributes, descriptorProvider, nativeMethodName,
|
||||
static, object="self", argsPost=[], resultVar=None):
|
||||
CGThing.__init__(self)
|
||||
|
||||
assert errorReport is None or isinstance(errorReport, CGThing)
|
||||
|
||||
isFallible = errorReport is not None
|
||||
|
||||
result, resultOutParam, resultRooter, resultArgs, resultConversion = \
|
||||
getRetvalDeclarationForType(returnType, descriptorProvider)
|
||||
|
||||
@ -6775,10 +6756,12 @@ class CGCallGenerator(CGThing):
|
||||
|
||||
if isFallible:
|
||||
self.cgRoot.prepend(CGGeneric("ErrorResult rv;\n"))
|
||||
self.cgRoot.append(CGGeneric("rv.WouldReportJSException();\n"))
|
||||
self.cgRoot.append(CGGeneric("if (MOZ_UNLIKELY(rv.Failed())) {\n"))
|
||||
self.cgRoot.append(CGIndenter(errorReport))
|
||||
self.cgRoot.append(CGGeneric("}\n"))
|
||||
self.cgRoot.append(CGGeneric(dedent(
|
||||
"""
|
||||
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
|
||||
return false;
|
||||
}
|
||||
""")))
|
||||
|
||||
self.cgRoot.append(CGGeneric("MOZ_ASSERT(!JS_IsExceptionPending(cx));\n"))
|
||||
|
||||
@ -7172,7 +7155,7 @@ class CGPerSignatureCall(CGThing):
|
||||
idlNode.identifier.name))
|
||||
else:
|
||||
cgThings.append(CGCallGenerator(
|
||||
self.getErrorReport() if self.isFallible() else None,
|
||||
self.isFallible(),
|
||||
self.getArguments(), argsPre, returnType,
|
||||
self.extendedAttributes, descriptor, nativeMethodName,
|
||||
static, argsPost=argsPost, resultVar=resultVar))
|
||||
@ -7279,9 +7262,6 @@ class CGPerSignatureCall(CGThing):
|
||||
maybeWrap=getMaybeWrapValueFuncForType(self.idlNode.type))
|
||||
return wrapCode
|
||||
|
||||
def getErrorReport(self):
|
||||
return CGGeneric('return ThrowMethodFailed(cx, rv);\n')
|
||||
|
||||
def define(self):
|
||||
return (self.cgRoot.define() + self.wrap_return_value())
|
||||
|
||||
@ -8250,9 +8230,8 @@ class CGEnumerateHook(CGAbstractBindingMethod):
|
||||
nsAutoTArray<nsString, 8> names;
|
||||
ErrorResult rv;
|
||||
self->GetOwnPropertyNames(cx, names, rv);
|
||||
rv.WouldReportJSException();
|
||||
if (rv.Failed()) {
|
||||
return ThrowMethodFailed(cx, rv);
|
||||
if (rv.MaybeSetPendingException(cx)) {
|
||||
return false;
|
||||
}
|
||||
bool dummy;
|
||||
for (uint32_t i = 0; i < names.Length(); ++i) {
|
||||
@ -9068,11 +9047,53 @@ def getEnumValueName(value):
|
||||
' rename our internal EndGuard_ to something else')
|
||||
return nativeName
|
||||
|
||||
class CGEnumToJSValue(CGAbstractMethod):
|
||||
def __init__(self, enum):
|
||||
enumType = enum.identifier.name
|
||||
self.stringsArray = enumType + "Values::" + ENUM_ENTRY_VARIABLE_NAME
|
||||
CGAbstractMethod.__init__(self, None, "ToJSValue", "bool",
|
||||
[Argument("JSContext*", "aCx"),
|
||||
Argument(enumType, "aArgument"),
|
||||
Argument("JS::MutableHandle<JS::Value>",
|
||||
"aValue")])
|
||||
|
||||
def definition_body(self):
|
||||
return fill(
|
||||
"""
|
||||
MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(${strings}));
|
||||
JSString* resultStr =
|
||||
JS_NewStringCopyN(aCx, ${strings}[uint32_t(aArgument)].value,
|
||||
${strings}[uint32_t(aArgument)].length);
|
||||
if (!resultStr) {
|
||||
return false;
|
||||
}
|
||||
aValue.setString(resultStr);
|
||||
return true;
|
||||
""",
|
||||
strings=self.stringsArray)
|
||||
|
||||
|
||||
class CGEnum(CGThing):
|
||||
def __init__(self, enum):
|
||||
CGThing.__init__(self)
|
||||
self.enum = enum
|
||||
strings = CGNamespace(
|
||||
self.stringsNamespace(),
|
||||
CGGeneric(declare=("extern const EnumEntry %s[%d];\n" %
|
||||
(ENUM_ENTRY_VARIABLE_NAME, self.nEnumStrings())),
|
||||
define=fill(
|
||||
"""
|
||||
extern const EnumEntry ${name}[${count}] = {
|
||||
$*{entries}
|
||||
{ nullptr, 0 }
|
||||
};
|
||||
""",
|
||||
name=ENUM_ENTRY_VARIABLE_NAME,
|
||||
count=self.nEnumStrings(),
|
||||
entries=''.join('{"%s", %d},\n' % (val, len(val))
|
||||
for val in self.enum.values()))))
|
||||
toJSValue = CGEnumToJSValue(enum)
|
||||
self.cgThings = CGList([strings, toJSValue], "\n")
|
||||
|
||||
def stringsNamespace(self):
|
||||
return self.enum.identifier.name + "Values"
|
||||
@ -9093,22 +9114,10 @@ class CGEnum(CGThing):
|
||||
strings = CGNamespace(self.stringsNamespace(),
|
||||
CGGeneric(declare="extern const EnumEntry %s[%d];\n"
|
||||
% (ENUM_ENTRY_VARIABLE_NAME, self.nEnumStrings())))
|
||||
return decl + "\n" + strings.declare()
|
||||
return decl + "\n" + self.cgThings.declare()
|
||||
|
||||
def define(self):
|
||||
strings = fill(
|
||||
"""
|
||||
extern const EnumEntry ${name}[${count}] = {
|
||||
$*{entries}
|
||||
{ nullptr, 0 }
|
||||
};
|
||||
""",
|
||||
name=ENUM_ENTRY_VARIABLE_NAME,
|
||||
count=self.nEnumStrings(),
|
||||
entries=''.join('{"%s", %d},\n' % (val, len(val))
|
||||
for val in self.enum.values()))
|
||||
return CGNamespace(self.stringsNamespace(),
|
||||
CGGeneric(define=indent(strings))).define()
|
||||
return self.cgThings.define()
|
||||
|
||||
def deps(self):
|
||||
return self.enum.getDeps()
|
||||
@ -10308,9 +10317,8 @@ class CGEnumerateOwnPropertiesViaGetOwnPropertyNames(CGAbstractBindingMethod):
|
||||
nsAutoTArray<nsString, 8> names;
|
||||
ErrorResult rv;
|
||||
self->GetOwnPropertyNames(cx, names, rv);
|
||||
rv.WouldReportJSException();
|
||||
if (rv.Failed()) {
|
||||
return ThrowMethodFailed(cx, rv);
|
||||
if (rv.MaybeSetPendingException(cx)) {
|
||||
return false;
|
||||
}
|
||||
// OK to pass null as "proxy" because it's ignored if
|
||||
// shadowPrototypeProperties is true
|
||||
@ -12172,11 +12180,9 @@ class CGDictionary(CGThing):
|
||||
if m.canHaveMissingValue():
|
||||
memberAssign = CGGeneric(fill(
|
||||
"""
|
||||
${name}.Reset();
|
||||
if (aOther.${name}.WasPassed()) {
|
||||
${name}.Construct();
|
||||
${name}.Value() = aOther.${name}.Value();
|
||||
} else {
|
||||
${name}.Reset();
|
||||
${name}.Construct(aOther.${name}.Value());
|
||||
}
|
||||
""",
|
||||
name=memberName))
|
||||
@ -13014,6 +13020,11 @@ class CGBindingRoot(CGThing):
|
||||
bindingHeaders["mozilla/dom/DOMJSClass.h"] = descriptors
|
||||
bindingHeaders["mozilla/dom/ScriptSettings.h"] = dictionaries # AutoJSAPI
|
||||
bindingHeaders["xpcpublic.h"] = dictionaries # xpc::UnprivilegedJunkScope
|
||||
# Ensure we see our enums in the generated .cpp file, for the ToJSValue
|
||||
# method body. Also ensure that we see jsapi.h.
|
||||
if enums:
|
||||
bindingHeaders[CGHeaders.getDeclarationFilename(enums[0])] = True
|
||||
bindingHeaders["jsapi.h"] = True
|
||||
|
||||
# For things that have [UseCounter]
|
||||
def descriptorRequiresTelemetry(desc):
|
||||
|
@ -6,6 +6,17 @@
|
||||
|
||||
/**
|
||||
* A struct for tracking exceptions that need to be thrown to JS.
|
||||
*
|
||||
* Conceptually, an ErrorResult represents either success or an exception in the
|
||||
* process of being thrown. This means that a failing ErrorResult _must_ be
|
||||
* handled in one of the following ways before coming off the stack:
|
||||
*
|
||||
* 1) Suppressed via SuppressException().
|
||||
* 2) Converted to a pure nsresult return value via StealNSResult().
|
||||
* 3) Converted to an actual pending exception on a JSContext via
|
||||
* MaybeSetPendingException.
|
||||
* 4) Converted to an exception JS::Value (probably to then reject a Promise
|
||||
* with) via dom::ToJSValue.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_ErrorResult_h
|
||||
@ -61,14 +72,14 @@ struct StringArrayAppender
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
static void Append(nsTArray<nsString>& aArgs, uint16_t aCount, const nsAString* aFirst, Ts... aOtherArgs)
|
||||
static void Append(nsTArray<nsString>& aArgs, uint16_t aCount, const nsAString& aFirst, Ts&&... aOtherArgs)
|
||||
{
|
||||
if (aCount == 0) {
|
||||
MOZ_ASSERT(false, "There should not be more string arguments provided than are required by the ErrNum.");
|
||||
return;
|
||||
}
|
||||
aArgs.AppendElement(*aFirst);
|
||||
Append(aArgs, aCount - 1, aOtherArgs...);
|
||||
aArgs.AppendElement(aFirst);
|
||||
Append(aArgs, aCount - 1, Forward<Ts>(aOtherArgs)...);
|
||||
}
|
||||
};
|
||||
|
||||
@ -87,8 +98,9 @@ public:
|
||||
|
||||
#ifdef DEBUG
|
||||
~ErrorResult() {
|
||||
MOZ_ASSERT_IF(IsErrorWithMessage(), !mMessage);
|
||||
MOZ_ASSERT_IF(IsDOMException(), !mDOMExceptionInfo);
|
||||
// Consumers should have called one of MaybeSetPendingException
|
||||
// (possibly via ToJSValue), StealNSResult, and SuppressException
|
||||
MOZ_ASSERT(!Failed());
|
||||
MOZ_ASSERT(!mMightHaveUnreportedJSException);
|
||||
MOZ_ASSERT(mUnionState == HasNothing);
|
||||
}
|
||||
@ -134,33 +146,71 @@ public:
|
||||
return rv;
|
||||
}
|
||||
|
||||
template<dom::ErrNum errorNumber, typename... Ts>
|
||||
void ThrowTypeError(Ts... messageArgs)
|
||||
// Use MaybeSetPendingException to convert an ErrorResult to a pending
|
||||
// exception on the given JSContext. This is the normal "throw an exception"
|
||||
// codepath.
|
||||
//
|
||||
// The return value is false if the ErrorResult represents success, true
|
||||
// otherwise. This does mean that in JSAPI method implementations you can't
|
||||
// just use this as |return rv.MaybeSetPendingException(cx)| (though you could
|
||||
// |return !rv.MaybeSetPendingException(cx)|), but in practice pretty much any
|
||||
// consumer would want to do some more work on the success codepath. So
|
||||
// instead the way you use this is:
|
||||
//
|
||||
// if (rv.MaybeSetPendingException(cx)) {
|
||||
// bail out here
|
||||
// }
|
||||
// go on to do something useful
|
||||
//
|
||||
// The success path is inline, since it should be the common case and we don't
|
||||
// want to pay the price of a function call in some of the consumers of this
|
||||
// method in the common case.
|
||||
//
|
||||
// Note that a true return value does NOT mean there is now a pending
|
||||
// exception on aCx, due to uncatchable exceptions. It should still be
|
||||
// considered equivalent to a JSAPI failure in terms of what callers should do
|
||||
// after true is returned.
|
||||
//
|
||||
// After this call, the ErrorResult will no longer return true from Failed(),
|
||||
// since the exception will have moved to the JSContext.
|
||||
bool MaybeSetPendingException(JSContext* cx)
|
||||
{
|
||||
ThrowErrorWithMessage<errorNumber>(NS_ERROR_TYPE_ERR, messageArgs...);
|
||||
WouldReportJSException();
|
||||
if (!Failed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SetPendingException(cx);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<dom::ErrNum errorNumber, typename... Ts>
|
||||
void ThrowRangeError(Ts... messageArgs)
|
||||
void ThrowTypeError(Ts&&... messageArgs)
|
||||
{
|
||||
ThrowErrorWithMessage<errorNumber>(NS_ERROR_RANGE_ERR, messageArgs...);
|
||||
ThrowErrorWithMessage<errorNumber>(NS_ERROR_TYPE_ERR,
|
||||
Forward<Ts>(messageArgs)...);
|
||||
}
|
||||
|
||||
template<dom::ErrNum errorNumber, typename... Ts>
|
||||
void ThrowRangeError(Ts&&... messageArgs)
|
||||
{
|
||||
ThrowErrorWithMessage<errorNumber>(NS_ERROR_RANGE_ERR,
|
||||
Forward<Ts>(messageArgs)...);
|
||||
}
|
||||
|
||||
void ReportErrorWithMessage(JSContext* cx);
|
||||
bool IsErrorWithMessage() const { return ErrorCode() == NS_ERROR_TYPE_ERR || ErrorCode() == NS_ERROR_RANGE_ERR; }
|
||||
|
||||
// Facilities for throwing a preexisting JS exception value via this
|
||||
// ErrorResult. The contract is that any code which might end up calling
|
||||
// ThrowJSException() must call MightThrowJSException() even if no exception
|
||||
// is being thrown. Code that would call ReportJSException or
|
||||
// StealJSException as needed must first call WouldReportJSException even if
|
||||
// is being thrown. Code that conditionally calls ToJSValue on this
|
||||
// ErrorResult only if Failed() must first call WouldReportJSException even if
|
||||
// this ErrorResult has not failed.
|
||||
//
|
||||
// The exn argument to ThrowJSException can be in any compartment. It does
|
||||
// not have to be in the compartment of cx. If someone later uses it, they
|
||||
// will wrap it into whatever compartment they're working in, as needed.
|
||||
void ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn);
|
||||
void ReportJSException(JSContext* cx);
|
||||
bool IsJSException() const { return ErrorCode() == NS_ERROR_DOM_JS_EXCEPTION; }
|
||||
|
||||
// Facilities for throwing a DOMException. If an empty message string is
|
||||
@ -169,7 +219,6 @@ public:
|
||||
// passed in must be one we create DOMExceptions for; otherwise you may get an
|
||||
// XPConnect Exception.
|
||||
void ThrowDOMException(nsresult rv, const nsACString& message = EmptyCString());
|
||||
void ReportDOMException(JSContext* cx);
|
||||
bool IsDOMException() const { return ErrorCode() == NS_ERROR_DOM_DOMEXCEPTION; }
|
||||
|
||||
// Flag on the ErrorResult that whatever needs throwing has been
|
||||
@ -183,10 +232,6 @@ public:
|
||||
return ErrorCode() == NS_ERROR_DOM_EXCEPTION_ON_JSCONTEXT;
|
||||
}
|
||||
|
||||
// Report a generic error. This should only be used if we're not
|
||||
// some more specific exception type.
|
||||
void ReportGenericError(JSContext* cx);
|
||||
|
||||
// Support for uncatchable exceptions.
|
||||
void ThrowUncatchableException() {
|
||||
Throw(NS_ERROR_UNCATCHABLE_EXCEPTION);
|
||||
@ -195,11 +240,6 @@ public:
|
||||
return ErrorCode() == NS_ERROR_UNCATCHABLE_EXCEPTION;
|
||||
}
|
||||
|
||||
// StealJSException steals the JS Exception from the object. This method must
|
||||
// be called only if IsJSException() returns true. This method also resets the
|
||||
// error code to NS_OK.
|
||||
void StealJSException(JSContext* cx, JS::MutableHandle<JS::Value> value);
|
||||
|
||||
void MOZ_ALWAYS_INLINE MightThrowJSException()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@ -264,7 +304,7 @@ private:
|
||||
nsTArray<nsString>& CreateErrorMessageHelper(const dom::ErrNum errorNumber, nsresult errorType);
|
||||
|
||||
template<dom::ErrNum errorNumber, typename... Ts>
|
||||
void ThrowErrorWithMessage(nsresult errorType, Ts... messageArgs)
|
||||
void ThrowErrorWithMessage(nsresult errorType, Ts&&... messageArgs)
|
||||
{
|
||||
#if defined(DEBUG) && (defined(__clang__) || defined(__GNUC__))
|
||||
static_assert(dom::ErrorFormatNumArgs[errorNumber] == sizeof...(messageArgs),
|
||||
@ -275,7 +315,8 @@ private:
|
||||
|
||||
nsTArray<nsString>& messageArgsArray = CreateErrorMessageHelper(errorNumber, errorType);
|
||||
uint16_t argCount = dom::GetErrorArgCount(errorNumber);
|
||||
dom::StringArrayAppender::Append(messageArgsArray, argCount, messageArgs...);
|
||||
dom::StringArrayAppender::Append(messageArgsArray, argCount,
|
||||
Forward<Ts>(messageArgs)...);
|
||||
#ifdef DEBUG
|
||||
mUnionState = HasMessage;
|
||||
#endif // DEBUG
|
||||
@ -306,6 +347,17 @@ private:
|
||||
// anymore.
|
||||
void ClearUnionData();
|
||||
|
||||
// Implementation of MaybeSetPendingException for the case when we're a
|
||||
// failure result.
|
||||
void SetPendingException(JSContext* cx);
|
||||
|
||||
// Methods for setting various specific kinds of pending exceptions.
|
||||
void SetPendingExceptionWithMessage(JSContext* cx);
|
||||
void SetPendingJSException(JSContext* cx);
|
||||
void SetPendingDOMException(JSContext* cx);
|
||||
void SetPendingGenericErrorException(JSContext* cx);
|
||||
|
||||
|
||||
// Special values of mResult:
|
||||
// NS_ERROR_TYPE_ERR -- ThrowTypeError() called on us.
|
||||
// NS_ERROR_RANGE_ERR -- ThrowRangeError() called on us.
|
||||
@ -317,11 +369,11 @@ private:
|
||||
struct Message;
|
||||
struct DOMExceptionInfo;
|
||||
// mMessage is set by ThrowErrorWithMessage and reported (and deallocated) by
|
||||
// ReportErrorWithMessage.
|
||||
// SetPendingExceptionWithMessage.
|
||||
// mJSException is set (and rooted) by ThrowJSException and reported
|
||||
// (and unrooted) by ReportJSException.
|
||||
// (and unrooted) by SetPendingJSException.
|
||||
// mDOMExceptionInfo is set by ThrowDOMException and reported
|
||||
// (and deallocated) by ReportDOMException.
|
||||
// (and deallocated) by SetPendingDOMException.
|
||||
union {
|
||||
Message* mMessage; // valid when IsErrorWithMessage()
|
||||
JS::Value mJSException; // valid when IsJSException()
|
||||
|
@ -56,8 +56,8 @@ ToJSValue(JSContext* aCx,
|
||||
MOZ_ASSERT(!aArgument.IsUncatchableException(),
|
||||
"Doesn't make sense to convert uncatchable exception to a JS value!");
|
||||
AutoForceSetExceptionOnContext forceExn(aCx);
|
||||
DebugOnly<bool> throwResult = ThrowMethodFailed(aCx, aArgument);
|
||||
MOZ_ASSERT(!throwResult);
|
||||
DebugOnly<bool> throwResult = aArgument.MaybeSetPendingException(aCx);
|
||||
MOZ_ASSERT(throwResult);
|
||||
DebugOnly<bool> getPendingResult = JS_GetPendingException(aCx, aValue);
|
||||
MOZ_ASSERT(getPendingResult);
|
||||
JS_ClearPendingException(aCx);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/dom/ipc/BlobChild.h"
|
||||
|
@ -2037,6 +2037,9 @@ BrowserElementChild.prototype = {
|
||||
case Cr.NS_ERROR_UNWANTED_URI :
|
||||
sendAsyncMsg('error', { type: 'unwantedBlocked' });
|
||||
return;
|
||||
case Cr.NS_ERROR_FORBIDDEN_URI :
|
||||
sendAsyncMsg('error', { type: 'forbiddenBlocked' });
|
||||
return;
|
||||
|
||||
case Cr.NS_ERROR_OFFLINE :
|
||||
sendAsyncMsg('error', { type: 'offline' });
|
||||
|
6
dom/cache/Cache.cpp
vendored
6
dom/cache/Cache.cpp
vendored
@ -46,8 +46,8 @@ IsValidPutRequestURL(const nsAString& aUrl, ErrorResult& aRv)
|
||||
}
|
||||
|
||||
if (!validScheme) {
|
||||
NS_NAMED_LITERAL_STRING(label, "Request");
|
||||
aRv.ThrowTypeError<MSG_INVALID_URL_SCHEME>(&label, &aUrl);
|
||||
aRv.ThrowTypeError<MSG_INVALID_URL_SCHEME>(NS_LITERAL_STRING("Request"),
|
||||
aUrl);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ IsValidPutRequestMethod(const Request& aRequest, ErrorResult& aRv)
|
||||
aRequest.GetMethod(method);
|
||||
if (!method.LowerCaseEqualsLiteral("get")) {
|
||||
NS_ConvertASCIItoUTF16 label(method);
|
||||
aRv.ThrowTypeError<MSG_INVALID_REQUEST_METHOD>(&label);
|
||||
aRv.ThrowTypeError<MSG_INVALID_REQUEST_METHOD>(label);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
4
dom/cache/CacheStorage.cpp
vendored
4
dom/cache/CacheStorage.cpp
vendored
@ -261,8 +261,8 @@ CacheStorage::DefineCaches(JSContext* aCx, JS::Handle<JSObject*> aGlobal)
|
||||
false, /* private browsing */
|
||||
true, /* force trusted */
|
||||
rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return ThrowMethodFailed(aCx, rv);
|
||||
if (NS_WARN_IF(rv.MaybeSetPendingException(aCx))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> caches(aCx);
|
||||
|
121
dom/cache/Context.cpp
vendored
121
dom/cache/Context.cpp
vendored
@ -132,7 +132,7 @@ public:
|
||||
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
|
||||
MOZ_ASSERT(mState == STATE_INIT);
|
||||
|
||||
mState = STATE_OPEN_DIRECTORY;
|
||||
mState = STATE_GET_INFO;
|
||||
nsresult rv = NS_DispatchToMainThread(this, nsIThread::DISPATCH_NORMAL);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mState = STATE_COMPLETE;
|
||||
@ -149,6 +149,8 @@ public:
|
||||
mInitAction->CancelOnInitiatingThread();
|
||||
}
|
||||
|
||||
void OpenDirectory();
|
||||
|
||||
// OpenDirectoryListener methods
|
||||
virtual void
|
||||
DirectoryLockAcquired(DirectoryLock* aLock) override;
|
||||
@ -195,6 +197,8 @@ private:
|
||||
enum State
|
||||
{
|
||||
STATE_INIT,
|
||||
STATE_GET_INFO,
|
||||
STATE_CREATE_QUOTA_MANAGER,
|
||||
STATE_OPEN_DIRECTORY,
|
||||
STATE_WAIT_FOR_DIRECTORY_LOCK,
|
||||
STATE_ENSURE_ORIGIN_INITIALIZED,
|
||||
@ -234,7 +238,7 @@ private:
|
||||
nsCOMPtr<nsIThread> mInitiatingThread;
|
||||
nsresult mResult;
|
||||
QuotaInfo mQuotaInfo;
|
||||
nsMainThreadPtrHandle<DirectoryLock> mDirectoryLock;
|
||||
RefPtr<DirectoryLock> mDirectoryLock;
|
||||
State mState;
|
||||
Atomic<bool> mCanceled;
|
||||
|
||||
@ -243,14 +247,35 @@ public:
|
||||
NS_DECL_NSIRUNNABLE
|
||||
};
|
||||
|
||||
void
|
||||
Context::QuotaInitRunnable::OpenDirectory()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
|
||||
MOZ_ASSERT(mState == STATE_CREATE_QUOTA_MANAGER ||
|
||||
mState == STATE_OPEN_DIRECTORY);
|
||||
MOZ_ASSERT(QuotaManager::Get());
|
||||
|
||||
// QuotaManager::OpenDirectory() will hold a reference to us as
|
||||
// a listener. We will then get DirectoryLockAcquired() on the owning
|
||||
// thread when it is safe to access our storage directory.
|
||||
mState = STATE_WAIT_FOR_DIRECTORY_LOCK;
|
||||
QuotaManager::Get()->OpenDirectory(PERSISTENCE_TYPE_DEFAULT,
|
||||
mQuotaInfo.mGroup,
|
||||
mQuotaInfo.mOrigin,
|
||||
mQuotaInfo.mIsApp,
|
||||
quota::Client::DOMCACHE,
|
||||
/* aExclusive */ false,
|
||||
this);
|
||||
}
|
||||
|
||||
void
|
||||
Context::QuotaInitRunnable::DirectoryLockAcquired(DirectoryLock* aLock)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
|
||||
MOZ_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK);
|
||||
MOZ_ASSERT(!mDirectoryLock);
|
||||
|
||||
mDirectoryLock = new nsMainThreadPtrHolder<DirectoryLock>(aLock);
|
||||
mDirectoryLock = aLock;
|
||||
|
||||
if (mCanceled) {
|
||||
Complete(NS_ERROR_ABORT);
|
||||
@ -271,7 +296,7 @@ Context::QuotaInitRunnable::DirectoryLockAcquired(DirectoryLock* aLock)
|
||||
void
|
||||
Context::QuotaInitRunnable::DirectoryLockFailed()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
|
||||
MOZ_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK);
|
||||
MOZ_ASSERT(!mDirectoryLock);
|
||||
|
||||
@ -290,13 +315,23 @@ NS_IMPL_ISUPPORTS(mozilla::dom::cache::Context::QuotaInitRunnable, nsIRunnable);
|
||||
// +-------+-------+ |
|
||||
// | |
|
||||
// +----------v-----------+ |
|
||||
// | OpenDirectory | Resolve(error) |
|
||||
// | GetInfo | Resolve(error) |
|
||||
// | (Main Thread) +-----------------+
|
||||
// +----------+-----------+ |
|
||||
// | |
|
||||
// +----------v-----------+ |
|
||||
// | CreateQuotaManager | Resolve(error) |
|
||||
// | (Orig Thread) +-----------------+
|
||||
// +----------+-----------+ |
|
||||
// | |
|
||||
// +----------v-----------+ |
|
||||
// | OpenDirectory | Resolve(error) |
|
||||
// | (Orig Thread) +-----------------+
|
||||
// +----------+-----------+ |
|
||||
// | |
|
||||
// +----------v-----------+ |
|
||||
// | WaitForDirectoryLock | Resolve(error) |
|
||||
// | (Main Thread) +-----------------+
|
||||
// | (Orig Thread) +-----------------+
|
||||
// +----------+-----------+ |
|
||||
// | |
|
||||
// +----------v------------+ |
|
||||
@ -330,43 +365,61 @@ Context::QuotaInitRunnable::Run()
|
||||
|
||||
switch(mState) {
|
||||
// -----------------------------------
|
||||
case STATE_OPEN_DIRECTORY:
|
||||
case STATE_GET_INFO:
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mCanceled) {
|
||||
resolver->Resolve(NS_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
|
||||
RefPtr<ManagerId> managerId = mManager->GetManagerId();
|
||||
nsCOMPtr<nsIPrincipal> principal = managerId->Principal();
|
||||
nsresult rv = QuotaManager::GetInfoFromPrincipal(principal,
|
||||
&mQuotaInfo.mGroup,
|
||||
&mQuotaInfo.mOrigin,
|
||||
&mQuotaInfo.mIsApp);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
resolver->Resolve(rv);
|
||||
break;
|
||||
}
|
||||
|
||||
mState = STATE_CREATE_QUOTA_MANAGER;
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||
mInitiatingThread->Dispatch(this, nsIThread::DISPATCH_NORMAL)));
|
||||
break;
|
||||
}
|
||||
// ----------------------------------
|
||||
case STATE_CREATE_QUOTA_MANAGER:
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
|
||||
|
||||
if (mCanceled || QuotaManager::IsShuttingDown()) {
|
||||
resolver->Resolve(NS_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
|
||||
QuotaManager* qm = QuotaManager::GetOrCreate();
|
||||
if (!qm) {
|
||||
if (QuotaManager::Get()) {
|
||||
OpenDirectory();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mState = STATE_OPEN_DIRECTORY;
|
||||
QuotaManager::GetOrCreate(this);
|
||||
break;
|
||||
}
|
||||
// ----------------------------------
|
||||
case STATE_OPEN_DIRECTORY:
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
|
||||
|
||||
if (NS_WARN_IF(!QuotaManager::Get())) {
|
||||
resolver->Resolve(NS_ERROR_FAILURE);
|
||||
break;
|
||||
}
|
||||
|
||||
RefPtr<ManagerId> managerId = mManager->GetManagerId();
|
||||
nsCOMPtr<nsIPrincipal> principal = managerId->Principal();
|
||||
nsresult rv = qm->GetInfoFromPrincipal(principal,
|
||||
&mQuotaInfo.mGroup,
|
||||
&mQuotaInfo.mOrigin,
|
||||
&mQuotaInfo.mIsApp);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
resolver->Resolve(rv);
|
||||
break;
|
||||
}
|
||||
|
||||
// QuotaManager::OpenDirectory() will hold a reference to us as
|
||||
// a listener. We will then get DirectoryLockAcquired() on the main
|
||||
// thread when it is safe to access our storage directory.
|
||||
mState = STATE_WAIT_FOR_DIRECTORY_LOCK;
|
||||
qm->OpenDirectory(PERSISTENCE_TYPE_DEFAULT,
|
||||
mQuotaInfo.mGroup,
|
||||
mQuotaInfo.mOrigin,
|
||||
mQuotaInfo.mIsApp,
|
||||
quota::Client::DOMCACHE,
|
||||
/* aExclusive */ false,
|
||||
this);
|
||||
OpenDirectory();
|
||||
break;
|
||||
}
|
||||
// ----------------------------------
|
||||
@ -425,7 +478,7 @@ Context::QuotaInitRunnable::Run()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
|
||||
mInitAction->CompleteOnInitiatingThread(mResult);
|
||||
mContext->OnQuotaInit(mResult, mQuotaInfo, mDirectoryLock);
|
||||
mContext->OnQuotaInit(mResult, mQuotaInfo, mDirectoryLock.forget());
|
||||
mState = STATE_COMPLETE;
|
||||
|
||||
// Explicitly cleanup here as the destructor could fire on any of
|
||||
@ -987,7 +1040,7 @@ Context::DispatchAction(Action* aAction, bool aDoomData)
|
||||
|
||||
void
|
||||
Context::OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
|
||||
nsMainThreadPtrHandle<DirectoryLock>& aDirectoryLock)
|
||||
already_AddRefed<DirectoryLock> aDirectoryLock)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(Context);
|
||||
|
||||
|
5
dom/cache/Context.h
vendored
5
dom/cache/Context.h
vendored
@ -190,7 +190,8 @@ private:
|
||||
void Start();
|
||||
void DispatchAction(Action* aAction, bool aDoomData = false);
|
||||
void OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
|
||||
nsMainThreadPtrHandle<DirectoryLock>& aDirectoryLock);
|
||||
already_AddRefed<DirectoryLock> aDirectoryLock);
|
||||
|
||||
|
||||
already_AddRefed<ThreadsafeHandle>
|
||||
CreateThreadsafeHandle();
|
||||
@ -221,7 +222,7 @@ private:
|
||||
// when ThreadsafeHandle::AllowToClose() is called.
|
||||
RefPtr<ThreadsafeHandle> mThreadsafeHandle;
|
||||
|
||||
nsMainThreadPtrHandle<DirectoryLock> mDirectoryLock;
|
||||
RefPtr<DirectoryLock> mDirectoryLock;
|
||||
RefPtr<Context> mNextContext;
|
||||
|
||||
public:
|
||||
|
208
dom/cache/Manager.cpp
vendored
208
dom/cache/Manager.cpp
vendored
@ -242,55 +242,61 @@ public:
|
||||
}
|
||||
|
||||
static void
|
||||
StartAbortOnMainThread(const nsACString& aOrigin)
|
||||
Abort(const nsACString& aOrigin)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
// Lock for sBackgroundThread.
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
|
||||
if (!sBackgroundThread) {
|
||||
if (!sFactory) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Guaranteed to succeed because we should get abort only before the
|
||||
// background thread is destroyed.
|
||||
nsCOMPtr<nsIRunnable> runnable = new AbortRunnable(aOrigin);
|
||||
nsresult rv = sBackgroundThread->Dispatch(runnable,
|
||||
nsIThread::DISPATCH_NORMAL);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv));
|
||||
MOZ_ASSERT(!sFactory->mManagerList.IsEmpty());
|
||||
|
||||
{
|
||||
ManagerList::ForwardIterator iter(sFactory->mManagerList);
|
||||
while (iter.HasMore()) {
|
||||
RefPtr<Manager> manager = iter.GetNext();
|
||||
if (aOrigin.IsVoid() ||
|
||||
manager->mManagerId->QuotaOrigin() == aOrigin) {
|
||||
manager->Abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
StartShutdownAllOnMainThread()
|
||||
ShutdownAll()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
// Lock for sFactoryShutdown and sBackgroundThread.
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
|
||||
sFactoryShutdown = true;
|
||||
|
||||
if (!sBackgroundThread) {
|
||||
if (!sFactory) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Guaranteed to succeed because we should be shutdown before the
|
||||
// background thread is destroyed.
|
||||
nsCOMPtr<nsIRunnable> runnable = new ShutdownAllRunnable();
|
||||
nsresult rv = sBackgroundThread->Dispatch(runnable,
|
||||
nsIThread::DISPATCH_NORMAL);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv));
|
||||
MOZ_ASSERT(!sFactory->mManagerList.IsEmpty());
|
||||
|
||||
{
|
||||
// Note that we are synchronously calling shutdown code here. If any
|
||||
// of the shutdown code synchronously decides to delete the Factory
|
||||
// we need to delay that delete until the end of this method.
|
||||
AutoRestore<bool> restore(sFactory->mInSyncShutdown);
|
||||
sFactory->mInSyncShutdown = true;
|
||||
|
||||
ManagerList::ForwardIterator iter(sFactory->mManagerList);
|
||||
while (iter.HasMore()) {
|
||||
RefPtr<Manager> manager = iter.GetNext();
|
||||
manager->Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
MaybeDestroyInstance();
|
||||
}
|
||||
|
||||
static bool
|
||||
IsShutdownAllCompleteOnMainThread()
|
||||
IsShutdownAllComplete()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
// Infer whether we have shutdown using the sBackgroundThread value. We
|
||||
// guarantee this is nullptr when sFactory is destroyed.
|
||||
return sFactoryShutdown && !sBackgroundThread;
|
||||
mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
return !sFactory;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -322,12 +328,6 @@ private:
|
||||
if (sFactoryShutdown) {
|
||||
return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
|
||||
}
|
||||
|
||||
// Cannot use ClearOnShutdown() because we're on the background thread.
|
||||
// This is automatically cleared when Factory::Remove() calls
|
||||
// MaybeDestroyInstance().
|
||||
MOZ_ASSERT(!sBackgroundThread);
|
||||
sBackgroundThread = NS_GetCurrentThread();
|
||||
}
|
||||
|
||||
// We cannot use ClearOnShutdown() here because we're not on the main
|
||||
@ -359,134 +359,21 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
// Be clear about what we are locking. sFactory is bg thread only, so
|
||||
// we don't need to lock it here. Just protect sBackgroundThread.
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
MOZ_ASSERT(sBackgroundThread);
|
||||
sBackgroundThread = nullptr;
|
||||
}
|
||||
|
||||
sFactory = nullptr;
|
||||
}
|
||||
|
||||
static void
|
||||
AbortOnBackgroundThread(const nsACString& aOrigin)
|
||||
{
|
||||
mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
// The factory was destroyed between when abort started on main thread and
|
||||
// when we could start abort on the worker thread. Just declare abort
|
||||
// complete.
|
||||
if (!sFactory) {
|
||||
#ifdef DEBUG
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
MOZ_ASSERT(!sBackgroundThread);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!sFactory->mManagerList.IsEmpty());
|
||||
|
||||
{
|
||||
ManagerList::ForwardIterator iter(sFactory->mManagerList);
|
||||
while (iter.HasMore()) {
|
||||
RefPtr<Manager> manager = iter.GetNext();
|
||||
if (aOrigin.IsVoid() ||
|
||||
manager->mManagerId->QuotaOrigin() == aOrigin) {
|
||||
manager->Abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ShutdownAllOnBackgroundThread()
|
||||
{
|
||||
mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
// The factory shutdown between when shutdown started on main thread and
|
||||
// when we could start shutdown on the worker thread. Just declare
|
||||
// shutdown complete. The sFactoryShutdown flag prevents the factory
|
||||
// from racing to restart here.
|
||||
if (!sFactory) {
|
||||
#ifdef DEBUG
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
MOZ_ASSERT(!sBackgroundThread);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!sFactory->mManagerList.IsEmpty());
|
||||
|
||||
{
|
||||
// Note that we are synchronously calling shutdown code here. If any
|
||||
// of the shutdown code synchronously decides to delete the Factory
|
||||
// we need to delay that delete until the end of this method.
|
||||
AutoRestore<bool> restore(sFactory->mInSyncShutdown);
|
||||
sFactory->mInSyncShutdown = true;
|
||||
|
||||
ManagerList::ForwardIterator iter(sFactory->mManagerList);
|
||||
while (iter.HasMore()) {
|
||||
RefPtr<Manager> manager = iter.GetNext();
|
||||
manager->Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
MaybeDestroyInstance();
|
||||
}
|
||||
|
||||
class AbortRunnable final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
explicit AbortRunnable(const nsACString& aOrigin)
|
||||
: mOrigin(aOrigin)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
AbortOnBackgroundThread(mOrigin);
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
~AbortRunnable() { }
|
||||
|
||||
const nsCString mOrigin;
|
||||
};
|
||||
|
||||
class ShutdownAllRunnable final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD
|
||||
Run() override
|
||||
{
|
||||
mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
ShutdownAllOnBackgroundThread();
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
~ShutdownAllRunnable() { }
|
||||
};
|
||||
|
||||
// Singleton created on demand and deleted when last Manager is cleared
|
||||
// in Remove().
|
||||
// PBackground thread only.
|
||||
static StaticAutoPtr<Factory> sFactory;
|
||||
|
||||
// protects following static attributes
|
||||
// protects following static attribute
|
||||
static StaticMutex sMutex;
|
||||
|
||||
// Indicate if shutdown has occurred to block re-creation of sFactory.
|
||||
// Must hold sMutex to access.
|
||||
static bool sFactoryShutdown;
|
||||
|
||||
// Background thread owning all Manager objects. Only set while sFactory is
|
||||
// set.
|
||||
// Must hold sMutex to access.
|
||||
static StaticRefPtr<nsIThread> sBackgroundThread;
|
||||
|
||||
// Weak references as we don't want to keep Manager objects alive forever.
|
||||
// When a Manager is destroyed it calls Factory::Remove() to clear itself.
|
||||
// PBackground thread only.
|
||||
@ -508,9 +395,6 @@ StaticMutex Manager::Factory::sMutex;
|
||||
// static
|
||||
bool Manager::Factory::sFactoryShutdown = false;
|
||||
|
||||
// static
|
||||
StaticRefPtr<nsIThread> Manager::Factory::sBackgroundThread;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Abstract class to help implement the various Actions. The vast majority
|
||||
@ -1531,13 +1415,13 @@ Manager::Get(ManagerId* aManagerId)
|
||||
|
||||
// static
|
||||
void
|
||||
Manager::ShutdownAllOnMainThread()
|
||||
Manager::ShutdownAll()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
Factory::StartShutdownAllOnMainThread();
|
||||
Factory::ShutdownAll();
|
||||
|
||||
while (!Factory::IsShutdownAllCompleteOnMainThread()) {
|
||||
while (!Factory::IsShutdownAllComplete()) {
|
||||
if (!NS_ProcessNextEvent()) {
|
||||
NS_WARNING("Something bad happened!");
|
||||
break;
|
||||
@ -1547,11 +1431,11 @@ Manager::ShutdownAllOnMainThread()
|
||||
|
||||
// static
|
||||
void
|
||||
Manager::AbortOnMainThread(const nsACString& aOrigin)
|
||||
Manager::Abort(const nsACString& aOrigin)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
Factory::StartAbortOnMainThread(aOrigin);
|
||||
Factory::Abort(aOrigin);
|
||||
}
|
||||
|
||||
void
|
||||
|
6
dom/cache/Manager.h
vendored
6
dom/cache/Manager.h
vendored
@ -131,11 +131,11 @@ public:
|
||||
static nsresult GetOrCreate(ManagerId* aManagerId, Manager** aManagerOut);
|
||||
static already_AddRefed<Manager> Get(ManagerId* aManagerId);
|
||||
|
||||
// Synchronously shutdown from main thread. This spins the event loop.
|
||||
static void ShutdownAllOnMainThread();
|
||||
// Synchronously shutdown. This spins the event loop.
|
||||
static void ShutdownAll();
|
||||
|
||||
// Cancel actions for given origin or all actions if passed string is null.
|
||||
static void AbortOnMainThread(const nsACString& aOrigin);
|
||||
static void Abort(const nsACString& aOrigin);
|
||||
|
||||
// Must be called by Listener objects before they are destroyed.
|
||||
void RemoveListener(Listener* aListener);
|
||||
|
20
dom/cache/QuotaClient.cpp
vendored
20
dom/cache/QuotaClient.cpp
vendored
@ -10,6 +10,7 @@
|
||||
#include "mozilla/dom/cache/Manager.h"
|
||||
#include "mozilla/dom/quota/QuotaManager.h"
|
||||
#include "mozilla/dom/quota/UsageInfo.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsThreadUtils.h"
|
||||
@ -23,6 +24,7 @@ using mozilla::dom::quota::Client;
|
||||
using mozilla::dom::quota::PersistenceType;
|
||||
using mozilla::dom::quota::QuotaManager;
|
||||
using mozilla::dom::quota::UsageInfo;
|
||||
using mozilla::ipc::AssertIsOnBackgroundThread;
|
||||
|
||||
static nsresult
|
||||
GetBodyUsage(nsIFile* aDir, UsageInfo* aUsageInfo)
|
||||
@ -175,9 +177,9 @@ public:
|
||||
virtual void
|
||||
AbortOperations(const nsACString& aOrigin) override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
Manager::AbortOnMainThread(aOrigin);
|
||||
Manager::Abort(aOrigin);
|
||||
}
|
||||
|
||||
virtual void
|
||||
@ -195,22 +197,26 @@ public:
|
||||
}
|
||||
|
||||
virtual void
|
||||
PerformIdleMaintenance() override
|
||||
StartIdleMaintenance() override
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
StopIdleMaintenance() override
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
ShutdownWorkThreads() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
// spins the event loop and synchronously shuts down all Managers
|
||||
Manager::ShutdownAllOnMainThread();
|
||||
Manager::ShutdownAll();
|
||||
}
|
||||
|
||||
private:
|
||||
~CacheQuotaClient()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsOnBackgroundThread();
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(CacheQuotaClient, override)
|
||||
@ -224,6 +230,8 @@ namespace cache {
|
||||
|
||||
already_AddRefed<quota::Client> CreateQuotaClient()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
RefPtr<CacheQuotaClient> ref = new CacheQuotaClient();
|
||||
return ref.forget();
|
||||
}
|
||||
|
4
dom/cache/TypeUtils.cpp
vendored
4
dom/cache/TypeUtils.cpp
vendored
@ -162,9 +162,9 @@ TypeUtils::ToCacheRequest(CacheRequest& aOut, InternalRequest* aIn,
|
||||
|
||||
if (!schemeValid) {
|
||||
if (aSchemeAction == TypeErrorOnInvalidScheme) {
|
||||
NS_NAMED_LITERAL_STRING(label, "Request");
|
||||
NS_ConvertUTF8toUTF16 urlUTF16(url);
|
||||
aRv.ThrowTypeError<MSG_INVALID_URL_SCHEME>(&label, &urlUTF16);
|
||||
aRv.ThrowTypeError<MSG_INVALID_URL_SCHEME>(NS_LITERAL_STRING("Request"),
|
||||
urlUTF16);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
6
dom/cache/test/mochitest/driver.js
vendored
6
dom/cache/test/mochitest/driver.js
vendored
@ -35,7 +35,11 @@ function runTests(testFile, order) {
|
||||
// adapted from dom/indexedDB/test/helpers.js
|
||||
function clearStorage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SpecialPowers.clearStorageForDoc(SpecialPowers.wrap(document), resolve);
|
||||
var qms = SpecialPowers.Services.qms;
|
||||
var principal = SpecialPowers.wrap(document).nodePrincipal;
|
||||
var request = qms.clearStoragesForPrincipal(principal);
|
||||
var cb = SpecialPowers.wrapCallback(resolve);
|
||||
request.callback = cb;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -24,19 +24,31 @@ function setupTestIframe() {
|
||||
|
||||
function clearStorage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SpecialPowers.clearStorageForDoc(SpecialPowers.wrap(document), resolve);
|
||||
var qms = SpecialPowers.Services.qms;
|
||||
var principal = SpecialPowers.wrap(document).nodePrincipal;
|
||||
var request = qms.clearStoragesForPrincipal(principal);
|
||||
var cb = SpecialPowers.wrapCallback(resolve);
|
||||
request.callback = cb;
|
||||
});
|
||||
}
|
||||
|
||||
function storageUsage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SpecialPowers.getStorageUsageForDoc(SpecialPowers.wrap(document), resolve);
|
||||
var qms = SpecialPowers.Services.qms;
|
||||
var principal = SpecialPowers.wrap(document).nodePrincipal;
|
||||
var cb = SpecialPowers.wrapCallback(function(request) {
|
||||
resolve(request.usage, request.fileUsage);
|
||||
});
|
||||
qms.getUsageForPrincipal(principal, cb);
|
||||
});
|
||||
}
|
||||
|
||||
function resetStorage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SpecialPowers.resetStorageForDoc(SpecialPowers.wrap(document), resolve);
|
||||
var qms = SpecialPowers.Services.qms;
|
||||
var request = qms.reset();
|
||||
var cb = SpecialPowers.wrapCallback(resolve);
|
||||
request.callback = cb;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -24,19 +24,31 @@ function setupTestIframe() {
|
||||
|
||||
function clearStorage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SpecialPowers.clearStorageForDoc(SpecialPowers.wrap(document), resolve);
|
||||
var qms = SpecialPowers.Services.qms;
|
||||
var principal = SpecialPowers.wrap(document).nodePrincipal;
|
||||
var request = qms.clearStoragesForPrincipal(principal);
|
||||
var cb = SpecialPowers.wrapCallback(resolve);
|
||||
request.callback = cb;
|
||||
});
|
||||
}
|
||||
|
||||
function storageUsage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SpecialPowers.getStorageUsageForDoc(SpecialPowers.wrap(document), resolve);
|
||||
var qms = SpecialPowers.Services.qms;
|
||||
var principal = SpecialPowers.wrap(document).nodePrincipal;
|
||||
var cb = SpecialPowers.wrapCallback(function(request) {
|
||||
resolve(request.usage, request.fileUsage);
|
||||
});
|
||||
qms.getUsageForPrincipal(principal, cb);
|
||||
});
|
||||
}
|
||||
|
||||
function resetStorage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SpecialPowers.resetStorageForDoc(SpecialPowers.wrap(document), resolve);
|
||||
var qms = SpecialPowers.Services.qms;
|
||||
var request = qms.reset();
|
||||
var cb = SpecialPowers.wrapCallback(resolve);
|
||||
request.callback = cb;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,10 @@ function setupTestIframe() {
|
||||
|
||||
function resetStorage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SpecialPowers.resetStorageForDoc(SpecialPowers.wrap(document), resolve);
|
||||
var qms = SpecialPowers.Services.qms;
|
||||
var request = qms.reset();
|
||||
var cb = SpecialPowers.wrapCallback(resolve);
|
||||
request.callback = cb;
|
||||
});
|
||||
}
|
||||
|
||||
|
18
dom/cache/test/mochitest/test_cache_shrink.html
vendored
18
dom/cache/test/mochitest/test_cache_shrink.html
vendored
@ -24,19 +24,31 @@ function setupTestIframe() {
|
||||
|
||||
function clearStorage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SpecialPowers.clearStorageForDoc(SpecialPowers.wrap(document), resolve);
|
||||
var qms = SpecialPowers.Services.qms;
|
||||
var principal = SpecialPowers.wrap(document).nodePrincipal;
|
||||
var request = qms.clearStoragesForPrincipal(principal);
|
||||
var cb = SpecialPowers.wrapCallback(resolve);
|
||||
request.callback = cb;
|
||||
});
|
||||
}
|
||||
|
||||
function storageUsage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SpecialPowers.getStorageUsageForDoc(SpecialPowers.wrap(document), resolve);
|
||||
var qms = SpecialPowers.Services.qms;
|
||||
var principal = SpecialPowers.wrap(document).nodePrincipal;
|
||||
var cb = SpecialPowers.wrapCallback(function(request) {
|
||||
resolve(request.usage, request.fileUsage);
|
||||
});
|
||||
qms.getUsageForPrincipal(principal, cb);
|
||||
});
|
||||
}
|
||||
|
||||
function resetStorage() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SpecialPowers.resetStorageForDoc(SpecialPowers.wrap(document), resolve);
|
||||
var qms = SpecialPowers.Services.qms;
|
||||
var request = qms.reset();
|
||||
var cb = SpecialPowers.wrapCallback(resolve);
|
||||
request.callback = cb;
|
||||
});
|
||||
}
|
||||
|
||||
|
15
dom/cache/test/xpcshell/make_profile.js
vendored
15
dom/cache/test/xpcshell/make_profile.js
vendored
@ -92,22 +92,11 @@ function resetQuotaManager() {
|
||||
var pref = 'dom.quotaManager.testing';
|
||||
prefService.getBranch(null).setBoolPref(pref, true);
|
||||
|
||||
qm.reset();
|
||||
var request = qm.reset();
|
||||
request.callback = resolve;
|
||||
|
||||
// disable quota manager testing mode
|
||||
//prefService.getBranch(null).setBoolPref(pref, false);
|
||||
|
||||
var uri = Cc['@mozilla.org/network/io-service;1']
|
||||
.getService(Ci.nsIIOService)
|
||||
.newURI('http://example.com', null, null);
|
||||
var principal = Cc['@mozilla.org/scriptsecuritymanager;1']
|
||||
.getService(Ci.nsIScriptSecurityManager)
|
||||
.getSystemPrincipal();
|
||||
|
||||
// use getUsageForPrincipal() to get a callback when the reset() is done
|
||||
qm.getUsageForPrincipal(principal, function(principal, usage, fileUsage) {
|
||||
resolve(usage);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1276,8 +1276,6 @@ nsDOMCameraControl::OnHardwareStateChange(CameraControlListener::HardwareState a
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
ErrorResult ignored;
|
||||
|
||||
switch (aState) {
|
||||
case CameraControlListener::kHardwareOpen:
|
||||
DOM_CAMERA_LOGI("DOM OnHardwareStateChange: open\n");
|
||||
@ -1405,7 +1403,6 @@ nsDOMCameraControl::OnRecorderStateChange(CameraControlListener::RecorderState a
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p, state=%u\n", __func__, __LINE__, this, aState);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
ErrorResult ignored;
|
||||
nsString state;
|
||||
|
||||
switch (aState) {
|
||||
|
@ -3967,6 +3967,7 @@ gfxFontGroup *CanvasRenderingContext2D::GetCurrentFontStyle()
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
bool fontUpdated = SetFontInternal(kDefaultFontStyle, err);
|
||||
if (err.Failed() || !fontUpdated) {
|
||||
err.SuppressException();
|
||||
gfxFontStyle style;
|
||||
style.size = kDefaultFontSize;
|
||||
gfxTextPerfMetrics* tp = nullptr;
|
||||
|
@ -1,5 +1,5 @@
|
||||
# WebGL Reftests!
|
||||
default-preferences pref(webgl.force-enabled,true)
|
||||
default-preferences pref(webgl.force-enabled,true) pref(media.useAudioChannelAPI,true) pref(dom.audiochannel.mutedByDefault,false)
|
||||
|
||||
# Check that disabling works:
|
||||
== webgl-disable-test.html?nogl wrapper.html?green.png
|
||||
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"runtests":{
|
||||
},
|
||||
"excludetests":{
|
||||
"dom/devicestorage/test/test_dirs.html":"excluded",
|
||||
"dom/devicestorage/test/test_storageAreaListener.html":"excluded"
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
[DEFAULT]
|
||||
skip-if = toolkit == 'android' || e10s #bug 781789 & bug 782275
|
||||
support-files =
|
||||
../test/devicestorage_common.js
|
||||
ipc.json
|
||||
|
||||
[test_ipc.html]
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' # b2g(nested ipc not working) b2g-debug(nested ipc not working) b2g-desktop(nested ipc not working)
|
@ -1,173 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for OOP DeviceStorage</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestFlakyTimeout("untriaged");
|
||||
|
||||
// The crash observer registration functions are stubbed out here to
|
||||
// prevent the iframe test runner from breaking later crash-related tests.
|
||||
function iframeScriptFirst() {
|
||||
SpecialPowers.prototype.registerProcessCrashObservers = () => {};
|
||||
SpecialPowers.prototype.unregisterProcessCrashObservers = () => {};
|
||||
|
||||
content.wrappedJSObject.RunSet.reloadAndRunAll({
|
||||
preventDefault: function() { },
|
||||
__exposedProps__: { preventDefault: 'r' }
|
||||
});
|
||||
}
|
||||
|
||||
function iframeScriptSecond() {
|
||||
let TestRunner = content.wrappedJSObject.TestRunner;
|
||||
|
||||
let oldComplete = TestRunner.onComplete;
|
||||
|
||||
TestRunner.onComplete = function() {
|
||||
TestRunner.onComplete = oldComplete;
|
||||
|
||||
sendAsyncMessage("test:DeviceStorage:ipcTestComplete", {
|
||||
result: JSON.stringify(TestRunner._failedTests)
|
||||
});
|
||||
|
||||
if (oldComplete) {
|
||||
oldComplete();
|
||||
}
|
||||
};
|
||||
|
||||
TestRunner.structuredLogger._dumpMessage = function(msg) {
|
||||
sendAsyncMessage("test:DeviceStorage:ipcTestMessage", { msg: msg });
|
||||
}
|
||||
}
|
||||
|
||||
let VALID_ACTIONS = ['suite_start', 'suite_end', 'test_start', 'test_end', 'test_status', 'process_output', 'log'];
|
||||
function validStructuredMessage(message) {
|
||||
return message.action !== undefined && VALID_ACTIONS.indexOf(message.action) >= 0;
|
||||
}
|
||||
function onTestMessage(data) {
|
||||
let message = SpecialPowers.wrap(data).data.msg;
|
||||
|
||||
if (validStructuredMessage(message)) {
|
||||
switch (message.action) {
|
||||
case "test_status":
|
||||
case "test_end":
|
||||
let test_tokens = message.test.split("/");
|
||||
let test_name = test_tokens[test_tokens.length - 1];
|
||||
if (message.subtest) {
|
||||
test_name += " | " + message.subtest;
|
||||
}
|
||||
ok(message.expected === undefined, test_name, message.message);
|
||||
break;
|
||||
case "log":
|
||||
info(message.message);
|
||||
break;
|
||||
default:
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onTestComplete() {
|
||||
let comp = SpecialPowers.wrap(SpecialPowers.Components);
|
||||
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
|
||||
let spObserver = comp.classes["@mozilla.org/special-powers-observer;1"]
|
||||
.getService(comp.interfaces.nsIMessageListener);
|
||||
|
||||
mm.removeMessageListener("SPPrefService", spObserver);
|
||||
mm.removeMessageListener("SPProcessCrashService", spObserver);
|
||||
mm.removeMessageListener("SPPingService", spObserver);
|
||||
mm.removeMessageListener("SpecialPowers.Quit", spObserver);
|
||||
mm.removeMessageListener("SPPermissionManager", spObserver);
|
||||
|
||||
mm.removeMessageListener("test:DeviceStorage:ipcTestMessage", onTestMessage);
|
||||
mm.removeMessageListener("test:DeviceStorage:ipcTestComplete", onTestComplete);
|
||||
|
||||
SimpleTest.executeSoon(function () { SimpleTest.finish(); });
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
let iframe = document.createElement("iframe");
|
||||
SpecialPowers.wrap(iframe).mozbrowser = true;
|
||||
iframe.id = "iframe";
|
||||
iframe.style.width = "100%";
|
||||
iframe.style.height = "1000px";
|
||||
|
||||
function iframeLoadSecond() {
|
||||
ok(true, "Got second iframe load event.");
|
||||
iframe.removeEventListener("mozbrowserloadend", iframeLoadSecond);
|
||||
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
|
||||
mm.loadFrameScript("data:,(" + iframeScriptSecond.toString() + ")();",
|
||||
false);
|
||||
}
|
||||
|
||||
function iframeLoadFirst() {
|
||||
ok(true, "Got first iframe load event.");
|
||||
iframe.removeEventListener("mozbrowserloadend", iframeLoadFirst);
|
||||
iframe.addEventListener("mozbrowserloadend", iframeLoadSecond);
|
||||
|
||||
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
|
||||
|
||||
let comp = SpecialPowers.wrap(SpecialPowers.Components);
|
||||
|
||||
let spObserver =
|
||||
comp.classes["@mozilla.org/special-powers-observer;1"]
|
||||
.getService(comp.interfaces.nsIMessageListener);
|
||||
|
||||
mm.addMessageListener("SPPrefService", spObserver);
|
||||
mm.addMessageListener("SPProcessCrashService", spObserver);
|
||||
mm.addMessageListener("SPPingService", spObserver);
|
||||
mm.addMessageListener("SpecialPowers.Quit", spObserver);
|
||||
mm.addMessageListener("SPPermissionManager", spObserver);
|
||||
|
||||
mm.addMessageListener("test:DeviceStorage:ipcTestMessage", onTestMessage);
|
||||
mm.addMessageListener("test:DeviceStorage:ipcTestComplete", onTestComplete);
|
||||
|
||||
let specialPowersBase = "chrome://specialpowers/content/";
|
||||
mm.loadFrameScript(specialPowersBase + "MozillaLogger.js", false);
|
||||
mm.loadFrameScript(specialPowersBase + "specialpowersAPI.js", false);
|
||||
mm.loadFrameScript(specialPowersBase + "specialpowers.js", false);
|
||||
|
||||
mm.loadFrameScript("data:,(" + iframeScriptFirst.toString() + ")();", false);
|
||||
}
|
||||
|
||||
iframe.addEventListener("mozbrowserloadend", iframeLoadFirst);
|
||||
|
||||
// Strip this filename and one directory level and then add "/test".
|
||||
let href = window.location.href;
|
||||
href = href.substring(0, href.lastIndexOf('/'));
|
||||
href = href.substring(0, href.lastIndexOf('/'));
|
||||
let manifest = "tests/dom/devicestorage/ipc/ipc.json";
|
||||
iframe.src = href + "/test?consoleLevel=INFO&testManifest=" + manifest;
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
addEventListener("load", function() {
|
||||
|
||||
SpecialPowers.addPermission("browser", true, document);
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
|
||||
["device.storage.enabled", true],
|
||||
["device.storage.testing", true],
|
||||
["device.storage.prompt.testing", true],
|
||||
|
||||
// TODO: remove this as part of bug 820712
|
||||
["network.disable.ipc.security", true],
|
||||
|
||||
["dom.ipc.browser_frames.oop_by_default", true],
|
||||
["dom.mozBrowserFramesEnabled", true],
|
||||
["browser.pagethumbnails.capturing_disabled", true]
|
||||
]
|
||||
}, runTests);
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -41,7 +41,6 @@ LOCAL_INCLUDES += [
|
||||
]
|
||||
|
||||
MOCHITEST_MANIFESTS += [
|
||||
'ipc/mochitest.ini',
|
||||
'test/mochitest.ini',
|
||||
]
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
var oldVal = false;
|
||||
|
||||
|
||||
Object.defineProperty(Array.prototype, "remove", {
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
@ -17,36 +17,18 @@ Object.defineProperty(Array.prototype, "remove", {
|
||||
}
|
||||
});
|
||||
|
||||
function devicestorage_setup() {
|
||||
|
||||
// ensure that the directory we are writing into is empty
|
||||
try {
|
||||
const Cc = SpecialPowers.Cc;
|
||||
const Ci = SpecialPowers.Ci;
|
||||
var directoryService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
||||
var f = directoryService.get("TmpD", Ci.nsIFile);
|
||||
f.appendRelativePath("device-storage-testing");
|
||||
f.remove(true);
|
||||
} catch(e) {}
|
||||
|
||||
function devicestorage_setup(callback) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
if (SpecialPowers.isMainProcess()) {
|
||||
try {
|
||||
oldVal = SpecialPowers.getBoolPref("device.storage.enabled");
|
||||
} catch(e) {}
|
||||
SpecialPowers.setBoolPref("device.storage.enabled", true);
|
||||
SpecialPowers.setBoolPref("device.storage.testing", true);
|
||||
SpecialPowers.setBoolPref("device.storage.prompt.testing", true);
|
||||
}
|
||||
}
|
||||
|
||||
function devicestorage_cleanup() {
|
||||
if (SpecialPowers.isMainProcess()) {
|
||||
SpecialPowers.setBoolPref("device.storage.enabled", oldVal);
|
||||
SpecialPowers.setBoolPref("device.storage.testing", false);
|
||||
SpecialPowers.setBoolPref("device.storage.prompt.testing", false);
|
||||
}
|
||||
SimpleTest.finish();
|
||||
let script = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('remove_testing_directory.js'));
|
||||
|
||||
script.addMessageListener('directory-removed', function listener () {
|
||||
script.removeMessageListener('directory-removed', listener);
|
||||
var prefs = [["device.storage.enabled", true],
|
||||
["device.storage.testing", true],
|
||||
["device.storage.prompt.testing", true]];
|
||||
SpecialPowers.pushPrefEnv({"set": prefs}, callback);
|
||||
});
|
||||
}
|
||||
|
||||
function getRandomBuffer() {
|
||||
@ -75,7 +57,7 @@ function randomFilename(l) {
|
||||
|
||||
function reportErrorAndQuit(e) {
|
||||
ok(false, "handleError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function createTestFiles(storage, paths) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
[DEFAULT]
|
||||
skip-if = e10s || (toolkit == 'android' && processor == 'x86') # e10s: bug 1222522. Android: bug 781789 & bug 782275
|
||||
skip-if = (toolkit == 'android' && processor == 'x86') # Android: bug 781789 & bug 782275
|
||||
support-files = devicestorage_common.js
|
||||
remove_testing_directory.js
|
||||
|
||||
[test_823965.html]
|
||||
# [test_add.html]
|
||||
@ -9,6 +10,7 @@ support-files = devicestorage_common.js
|
||||
[test_available.html]
|
||||
[test_basic.html]
|
||||
[test_dirs.html]
|
||||
skip-if = e10s # Bug 1063569.
|
||||
# [test_diskSpace.html]
|
||||
# Possible race between the time we write a file, and the
|
||||
# time it takes to be reflected by statfs(). Bug # 791287
|
||||
|
11
dom/devicestorage/test/remove_testing_directory.js
Normal file
11
dom/devicestorage/test/remove_testing_directory.js
Normal file
@ -0,0 +1,11 @@
|
||||
// ensure that the directory we are writing into is empty
|
||||
try {
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var directoryService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
||||
var f = directoryService.get("TmpD", Ci.nsIFile);
|
||||
f.appendRelativePath("device-storage-testing");
|
||||
f.remove(true);
|
||||
} catch(e) {}
|
||||
|
||||
sendAsyncMessage('directory-removed', {});
|
@ -22,7 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=823965
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
var gFileName = "devicestorage/" + randomFilename(12) + "/hi.png";
|
||||
var gData = "My name is Doug Turner (?!?). My IRC nick is DougT. I like Maple cookies."
|
||||
@ -43,11 +43,11 @@ function getSuccess(e) {
|
||||
var dreq = storage2.delete(mreq.result.name);
|
||||
dreq.onerror = function () {
|
||||
ok(true, "The bug has been fixed");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
};
|
||||
dreq.onsuccess = function () {
|
||||
ok(false, "The bug has been fixed");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
};
|
||||
};
|
||||
|
||||
@ -56,7 +56,7 @@ function getSuccess(e) {
|
||||
|
||||
function getError(e) {
|
||||
ok(false, "getError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
@ -85,7 +85,7 @@ function addSuccess(e) {
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
@ -99,8 +99,9 @@ ok(request, "Should have a non-null request");
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -18,13 +18,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=786922
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=786922">Mozilla Bug 786922</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function add(storage, mime) {
|
||||
dump("adding: " + mime + "\n");
|
||||
@ -40,18 +40,18 @@ var tests = [
|
||||
|
||||
function fail(e) {
|
||||
ok(false, "onerror was called");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function next(e) {
|
||||
|
||||
if (e != undefined)
|
||||
ok(true, "addError was called");
|
||||
|
||||
|
||||
var f = tests.pop();
|
||||
|
||||
if (f == undefined) {
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -62,8 +62,9 @@ function next(e) {
|
||||
|
||||
next();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -18,13 +18,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=786922
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=786922">Mozilla Bug 786922</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function addNamed(storage, mime, fileExtension) {
|
||||
dump("adding: " + mime + " " + fileExtension + "\n");
|
||||
@ -45,18 +45,18 @@ function fail(e) {
|
||||
ok(false, "addSuccess was called");
|
||||
ok(e.target.error.name == "TypeMismatchError", "Error must be TypeMismatchError");
|
||||
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function next(e) {
|
||||
|
||||
if (e != undefined)
|
||||
ok(true, "addError was called");
|
||||
|
||||
|
||||
var f = tests.pop();
|
||||
|
||||
if (f == undefined) {
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -67,8 +67,9 @@ function next(e) {
|
||||
|
||||
next();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -22,16 +22,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=834595
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function availableSuccess(e) {
|
||||
isnot(e.target.result, null, "result should not be null");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function availableError(e) {
|
||||
ok(false, "availableError was called");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
@ -42,6 +42,8 @@ ok(request, "Should have a non-null request");
|
||||
request.onsuccess = availableSuccess;
|
||||
request.onerror = availableError;
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
@ -17,12 +17,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function() {
|
||||
|
||||
var gFileName = "devicestorage/" + randomFilename(12) + "/hi.png";
|
||||
var gData = "My name is Doug Turner. My IRC nick is DougT. I like Maple cookies."
|
||||
@ -31,12 +31,12 @@ var gFileReader = new FileReader();
|
||||
|
||||
function getAfterDeleteSuccess(e) {
|
||||
ok(false, "file was deleted not successfully");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function getAfterDeleteError(e) {
|
||||
ok(true, "file was deleted successfully");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function deleteSuccess(e) {
|
||||
@ -53,7 +53,7 @@ function deleteSuccess(e) {
|
||||
|
||||
function deleteError(e) {
|
||||
ok(false, "deleteError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function getSuccess(e) {
|
||||
@ -88,7 +88,7 @@ function readerCallback(e) {
|
||||
|
||||
function getError(e) {
|
||||
ok(false, "getError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
@ -119,7 +119,7 @@ function addSuccess(e) {
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
@ -133,8 +133,9 @@ ok(request, "Should have a non-null request");
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -17,13 +17,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup();
|
||||
|
||||
devicestorage_setup(function () {
|
||||
|
||||
var freeBytes = -1;
|
||||
var stats = 0;
|
||||
@ -39,7 +38,7 @@ function stat(s, file_list_length) {
|
||||
stats = stats + 1;
|
||||
|
||||
if (stats == 2) {
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +59,7 @@ function addSuccess(e) {
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
ok(true, "hi");
|
||||
@ -94,8 +93,9 @@ for (var i=0; i < music_files.length; i++) {
|
||||
request.onerror = addError;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -17,12 +17,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function testingStorage() {
|
||||
return navigator.getDeviceStorage("pictures");
|
||||
@ -40,20 +40,20 @@ var gFileName = "../owned.png";
|
||||
function fail(e) {
|
||||
ok(false, "addSuccess was called");
|
||||
dump(request);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function next(e) {
|
||||
|
||||
if (e != undefined) {
|
||||
ok(true, "addError was called");
|
||||
ok(true, "addError was called");
|
||||
ok(e.target.error.name == "SecurityError", "Error must be SecurityError");
|
||||
}
|
||||
|
||||
var f = tests.pop();
|
||||
|
||||
if (f == undefined) {
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -64,10 +64,9 @@ function next(e) {
|
||||
|
||||
next();
|
||||
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -17,22 +17,22 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function enumerateSuccess(e) {
|
||||
|
||||
if (e.target.result == null) {
|
||||
ok(files.length == 0, "when the enumeration is done, we shouldn't have any files in this array")
|
||||
dump("We still have length = " + files.length + "\n");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var filename = e.target.result.name;
|
||||
if (filename[0] == "/") {
|
||||
// We got /storageName/prefix/filename
|
||||
@ -61,7 +61,7 @@ function enumerateSuccess(e) {
|
||||
|
||||
function handleError(e) {
|
||||
ok(false, "handleError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
@ -76,7 +76,7 @@ function addSuccess(e) {
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
@ -96,8 +96,9 @@ for (var i=0; i<files.length; i++) {
|
||||
request.onerror = addError;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -17,12 +17,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function enumerateSuccess(e) {
|
||||
}
|
||||
@ -39,12 +39,12 @@ try {
|
||||
}
|
||||
catch (e) {
|
||||
ok(true, "Calling continue before enumerateSuccess fires should throw");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -35,7 +35,7 @@ function enumerateSuccess(e) {
|
||||
|
||||
if (e.target.result == null) {
|
||||
ok(files.length == 0, "when the enumeration is done, we shouldn't have any files in this array")
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ function enumerateSuccess(e) {
|
||||
|
||||
function handleError(e) {
|
||||
ok(false, "handleError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
@ -82,7 +82,7 @@ function addSuccess(e) {
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
|
@ -18,12 +18,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup()
|
||||
devicestorage_setup(function () {
|
||||
|
||||
storage = navigator.getDeviceStorage("pictures");
|
||||
|
||||
@ -70,12 +70,11 @@ var cursor = storage.enumerate({"path": "a", "since": new Date(0) });
|
||||
} catch(e) {throws = true}
|
||||
ok(!throws, "enumerate object parameter with path");
|
||||
|
||||
SimpleTest.finish()
|
||||
|
||||
});
|
||||
|
||||
|
||||
devicestorage_cleanup()
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -22,23 +22,23 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function freeSpaceSuccess(e) {
|
||||
ok(e.target.result > 0, "free bytes should exist and be greater than zero");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function freeSpaceError(e) {
|
||||
ok(false, "freeSpaceError was called");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var storage = navigator.getDeviceStorage("pictures");
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
@ -54,8 +54,9 @@ request = storage.addNamed(createRandomBlob('image/png'), prefix + "/a/b.png");
|
||||
request.onsuccess = addSuccess;
|
||||
request.onerror = addError;
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -26,15 +26,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=855952
|
||||
var file = new Blob(["This is a text file."], {type: "text/plain"});
|
||||
var appendFile = new Blob([" Another text file."], {type: "text/plain"});
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
function deleteSuccess(e) {
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function deleteError(e) {
|
||||
ok(false, "deleteError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function appendSuccess(e) {
|
||||
@ -47,7 +47,7 @@ function appendSuccess(e) {
|
||||
|
||||
function appendError(e) {
|
||||
ok(false, "appendError was called.");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
@ -83,8 +83,9 @@ ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
ok(gStorage, "Should get storage from sdcard");
|
||||
runtest();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=910412
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
var gFileName = randomFilename(12);
|
||||
|
||||
@ -46,12 +46,12 @@ function createDirectorySuccess(d) {
|
||||
|
||||
function getSuccess(d) {
|
||||
ok(d.name === gFileName, "Should get directory - " + gFileName + ".");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function cbError(e) {
|
||||
ok(false, "Should not arrive here! Error: " + e.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
|
||||
@ -63,8 +63,10 @@ var promise = storage.getRoot();
|
||||
ok(promise, "Should have a non-null promise");
|
||||
|
||||
promise.then(getRootSuccess, cbError);
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=910412
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
// The root directory object.
|
||||
var gRoot;
|
||||
@ -59,7 +59,7 @@ function getSuccess(d) {
|
||||
// Create directory with an existing path.
|
||||
gRoot.createDirectory(gPath).then(function(what) {
|
||||
ok(false, "Should not overwrite an existing directory.");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}, function(e) {
|
||||
ok(true, "Creating directory should fail if it already exists.");
|
||||
|
||||
@ -73,10 +73,10 @@ function getSuccess(d) {
|
||||
// Create the parent directory.
|
||||
d.createDirectory('..').then(function(what) {
|
||||
ok(false, "Should not overwrite an existing directory.");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}, function(e) {
|
||||
ok(true, "Accessing parent directory with '..' is not allowed.");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
break;
|
||||
}
|
||||
@ -85,7 +85,7 @@ function getSuccess(d) {
|
||||
|
||||
function cbError(e) {
|
||||
ok(false, e.name + " error should not arrive here!");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage.");
|
||||
@ -98,8 +98,10 @@ ok(promise, "Should have a non-null promise for getRoot.");
|
||||
|
||||
gName = storage.storageName;
|
||||
promise.then(getSuccess, cbError);
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=910412
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.7">
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
let gTestCount = 0;
|
||||
let gFileReader = new FileReader();
|
||||
@ -84,7 +84,7 @@ let gTestCases = [
|
||||
|
||||
function next() {
|
||||
if (gTestCount >= gTestCases.length) {
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
let c = gTestCases[gTestCount++];
|
||||
@ -122,11 +122,12 @@ storage.getRoot().then(function(dir) {
|
||||
next();
|
||||
}, function(e) {
|
||||
ok(false, e.name + " error should not arrive here!");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -21,7 +21,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=910412
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
SimpleTest.requestCompleteLog();
|
||||
|
||||
// The root directory object.
|
||||
@ -77,7 +78,7 @@ function getSuccess(r) {
|
||||
break;
|
||||
default:
|
||||
ok(false, "Should not arrive at getSuccess!");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
break;
|
||||
}
|
||||
gTestCount++;
|
||||
@ -137,11 +138,11 @@ function getFailure(e) {
|
||||
testGetFailure(gRoot, "sub1//sub2");
|
||||
break;
|
||||
case 17:
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
break;
|
||||
default:
|
||||
ok(false, "Should not arrive here!");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
break;
|
||||
}
|
||||
gTestCount++;
|
||||
@ -149,12 +150,12 @@ function getFailure(e) {
|
||||
|
||||
function cbError(e) {
|
||||
ok(false, "Should not arrive at cbError! Error: " + e.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function cbSuccess(e) {
|
||||
ok(false, "Should not arrive at cbSuccess!");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage.");
|
||||
@ -173,7 +174,7 @@ function createTestFile(path, callback) {
|
||||
|
||||
req.onerror = function(e) {
|
||||
ok(false, "Failed to create " + path + ": " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
};
|
||||
}
|
||||
|
||||
@ -197,8 +198,9 @@ createTestFile("sub1/sub2/test.png", function() {
|
||||
promise.then(getSuccess, cbError);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=XXX
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
SimpleTest.requestCompleteLog();
|
||||
|
||||
// The root directory object.
|
||||
@ -62,12 +62,12 @@ function checkContents1(contents) {
|
||||
|
||||
function checkContents2(contents) {
|
||||
is(contents[0].name, "c.png", "'sub2' should contain 'c.png'");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function handleError(e) {
|
||||
ok(false, "Should not arrive at handleError! Error: " + e.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var gStorage = navigator.getDeviceStorage("pictures");
|
||||
@ -87,11 +87,12 @@ createTestFiles(gStorage, ["sub/a.png", "sub/b.png", "sub/sub2/c.png", "sub/sub3
|
||||
runTests();
|
||||
}, function() {
|
||||
ok(false, "Failed to created test files.");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=934368
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.7">
|
||||
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
let gStorage = null;
|
||||
let gTestCount = 0;
|
||||
@ -93,7 +93,7 @@ function runNextTests() {
|
||||
function runTests() {
|
||||
function cbError(e) {
|
||||
ok(false, "Should not arrive at cbError! Error: " + e.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function cbSuccess(r) {
|
||||
@ -116,7 +116,7 @@ function runNextTests() {
|
||||
testNextRemove();
|
||||
}, function() {
|
||||
ok(false, "Failed to get test files.");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}, cbError);
|
||||
};
|
||||
@ -124,7 +124,7 @@ function runNextTests() {
|
||||
runTests();
|
||||
}, function() {
|
||||
ok(false, "Failed to created test files.");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@ function testNextRemove() {
|
||||
return;
|
||||
}
|
||||
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
ok(navigator.getDeviceStorage, "Should have getDeviceStorage.");
|
||||
@ -168,8 +168,9 @@ ok(gStorage, "Should have gotten a storage.");
|
||||
gRemoveDeep = true;
|
||||
runNextTests();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -17,13 +17,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.requestFlakyTimeout("untriaged");
|
||||
devicestorage_setup();
|
||||
devicestorage_setup(function () {
|
||||
|
||||
// We put the old files in 2 levels deep. When you add a file to a directory
|
||||
// it will modify the parents last modification time, but not the parents
|
||||
// parents. So we want to make sure that even though x's timestamp is earlier
|
||||
@ -44,7 +45,7 @@ function verifyAndDelete(prefix, files, e) {
|
||||
ok(files.length == 0, "when the enumeration is done, we shouldn't have any files in this array")
|
||||
dump("We still have length = " + files.length + "\n");
|
||||
dump(files + "\n");
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -86,12 +87,12 @@ function addFile(filename, callback) {
|
||||
}
|
||||
getReq.onerror = function(e) {
|
||||
ok(false, "getError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
};
|
||||
}
|
||||
addReq.onerror = function(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,7 +116,7 @@ function delFile(filename, callback) {
|
||||
};
|
||||
req.onerror = function(e) {
|
||||
ok(false, "delError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
};
|
||||
}
|
||||
|
||||
@ -129,7 +130,7 @@ function afterNewFiles() {
|
||||
};
|
||||
cursor.onerror = function (e) {
|
||||
ok(false, "handleError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
SimpleTest.finish();
|
||||
};
|
||||
}
|
||||
|
||||
@ -167,8 +168,9 @@ function addOldFiles() {
|
||||
|
||||
addOldFiles();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user