merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-11-23 14:08:50 +01:00
Родитель 7e51d297a6 694a81aba1
Коммит 5f1ac1afb3
417 изменённых файлов: 11977 добавлений и 4672 удалений

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

@ -3,7 +3,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
chrome.jar: chrome.jar:
% content branding %content/branding/ % content branding %content/branding/ contentaccessible=yes
content/branding/about.png (about.png) content/branding/about.png (about.png)
content/branding/logoWordmark.png (logoWordmark.png) content/branding/logoWordmark.png (logoWordmark.png)
content/branding/logo.png (logo.png) content/branding/logo.png (logo.png)

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

@ -3,7 +3,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
chrome.jar: chrome.jar:
% content branding %content/branding/ % content branding %content/branding/ contentaccessible=yes
content/branding/about.png (about.png) content/branding/about.png (about.png)
content/branding/logoWordmark.png (logoWordmark.png) content/branding/logoWordmark.png (logoWordmark.png)
content/branding/logo.png (logo.png) content/branding/logo.png (logo.png)

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

@ -3,7 +3,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
chrome.jar: chrome.jar:
% content branding %content/branding/ % content branding %content/branding/ contentaccessible=yes
content/branding/about.png (about.png) content/branding/about.png (about.png)
content/branding/logoWordmark.png (logoWordmark.png) content/branding/logoWordmark.png (logoWordmark.png)
content/branding/logo.png (logo.png) content/branding/logo.png (logo.png)

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

@ -3,7 +3,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
chrome.jar: chrome.jar:
% content branding %content/branding/ % content branding %content/branding/ contentaccessible=yes
content/branding/about.png (about.png) content/branding/about.png (about.png)
content/branding/logoWordmark.png (logoWordmark.png) content/branding/logoWordmark.png (logoWordmark.png)
content/branding/logo.png (logo.png) content/branding/logo.png (logo.png)

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

@ -5,7 +5,7 @@
chrome.jar: chrome.jar:
% content branding %content/branding/ % content branding %content/branding/ contentaccessible=yes
% content b2g %content/ % content b2g %content/
content/arrow.svg (content/arrow.svg) 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. 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. 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. 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. 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. 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. 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_nssBadCert">&nssBadCert.title;</h1>
<h1 id="et_malwareBlocked">&malwareBlocked.title;</h1> <h1 id="et_malwareBlocked">&malwareBlocked.title;</h1>
<h1 id="et_unwantedBlocked">&unwantedBlocked.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_cspBlocked">&cspBlocked.title;</h1>
<h1 id="et_remoteXUL">&remoteXUL.title;</h1> <h1 id="et_remoteXUL">&remoteXUL.title;</h1>
<h1 id="et_corruptedContentError">&corruptedContentError.title;</h1> <h1 id="et_corruptedContentError">&corruptedContentError.title;</h1>
@ -452,6 +453,7 @@
<div id="ed_nssBadCert">&nssBadCert.longDesc2;</div> <div id="ed_nssBadCert">&nssBadCert.longDesc2;</div>
<div id="ed_malwareBlocked">&malwareBlocked.longDesc;</div> <div id="ed_malwareBlocked">&malwareBlocked.longDesc;</div>
<div id="ed_unwantedBlocked">&unwantedBlocked.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_cspBlocked">&cspBlocked.longDesc;</div>
<div id="ed_remoteXUL">&remoteXUL.longDesc;</div> <div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
<div id="ed_corruptedContentError">&corruptedContentError.longDesc;</div> <div id="ed_corruptedContentError">&corruptedContentError.longDesc;</div>

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

@ -71,108 +71,73 @@
function initPage() function initPage()
{ {
// Handoff to the appropriate initializer, based on error code var error = "";
switch (getErrorCode()) { switch (getErrorCode()) {
case "malwareBlocked" : case "malwareBlocked" :
initPage_malware(); error = "malware";
break; break;
case "phishingBlocked" : case "phishingBlocked" :
initPage_phishing(); error = "phishing";
break; break;
case "unwantedBlocked" : case "unwantedBlocked" :
initPage_unwanted(); error = "unwanted";
break; break;
case "forbiddenBlocked" :
error = "forbidden";
break;
default:
return;
} }
}
/** var el;
* 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"); if (error !== "malware") {
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);
}
el = document.getElementById("errorLongDescText_phishing"); if (error !== "phishing") {
el.parentNode.removeChild(el); 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_unwanted"); if (error !== "unwanted") {
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);
}
el = document.getElementById("errorShortDescText_unwanted"); if (error !== "forbidden") {
el.parentNode.removeChild(el); el = document.getElementById("errorTitleText_forbidden");
el.parentNode.removeChild(el);
el = document.getElementById("errorLongDescText_unwanted"); el = document.getElementById("errorShortDescText_forbidden");
el.parentNode.removeChild(el); el.parentNode.removeChild(el);
} else {
el = document.getElementById("ignoreWarningButton");
el.parentNode.removeChild(el);
el = document.getElementById("reportButton");
el.parentNode.removeChild(el);
}
// Set sitename // Set sitename
document.getElementById("malware_sitename").textContent = getHostString(); document.getElementById(error + "_sitename").textContent = getHostString();
document.title = document.getElementById("errorTitleText_malware") document.title = document.getElementById("errorTitleText_" + error)
.innerHTML; .innerHTML;
}
/** // Inform the test harness that we're done loading the page
* Initialize custom strings and functionality for blocked malware case var event = new CustomEvent("AboutBlockedLoaded");
*/ document.dispatchEvent(event);
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;
} }
]]></script> ]]></script>
<style type="text/css"> <style type="text/css">
@ -213,6 +178,7 @@
<h1 id="errorTitleText_phishing">&safeb.blocked.phishingPage.title;</h1> <h1 id="errorTitleText_phishing">&safeb.blocked.phishingPage.title;</h1>
<h1 id="errorTitleText_malware">&safeb.blocked.malwarePage.title;</h1> <h1 id="errorTitleText_malware">&safeb.blocked.malwarePage.title;</h1>
<h1 id="errorTitleText_unwanted">&safeb.blocked.unwantedPage.title;</h1> <h1 id="errorTitleText_unwanted">&safeb.blocked.unwantedPage.title;</h1>
<h1 id="errorTitleText_forbidden">&safeb.blocked.forbiddenPage.title;</h1>
</div> </div>
<div id="errorLongContent"> <div id="errorLongContent">
@ -222,6 +188,7 @@
<p id="errorShortDescText_phishing">&safeb.blocked.phishingPage.shortDesc;</p> <p id="errorShortDescText_phishing">&safeb.blocked.phishingPage.shortDesc;</p>
<p id="errorShortDescText_malware">&safeb.blocked.malwarePage.shortDesc;</p> <p id="errorShortDescText_malware">&safeb.blocked.malwarePage.shortDesc;</p>
<p id="errorShortDescText_unwanted">&safeb.blocked.unwantedPage.shortDesc;</p> <p id="errorShortDescText_unwanted">&safeb.blocked.unwantedPage.shortDesc;</p>
<p id="errorShortDescText_forbidden">&safeb.blocked.forbiddenPage.shortDesc;</p>
</div> </div>
<!-- Long Description --> <!-- Long Description -->

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

@ -2958,10 +2958,16 @@ var BrowserOnClick = {
onAboutBlocked: function (elementId, reason, isTopFrame, location) { onAboutBlocked: function (elementId, reason, isTopFrame, location) {
// Depending on what page we are displaying here (malware/phishing/unwanted) // Depending on what page we are displaying here (malware/phishing/unwanted)
// use the right strings and links for each. // use the right strings and links for each.
let bucketName = "WARNING_PHISHING_PAGE_"; let bucketName = "";
let sendTelemetry = false;
if (reason === 'malware') { if (reason === 'malware') {
sendTelemetry = true;
bucketName = "WARNING_MALWARE_PAGE_"; bucketName = "WARNING_MALWARE_PAGE_";
} else if (reason === 'phishing') {
sendTelemetry = true;
bucketName = "WARNING_PHISHING_PAGE_";
} else if (reason === 'unwanted') { } else if (reason === 'unwanted') {
sendTelemetry = true;
bucketName = "WARNING_UNWANTED_PAGE_"; bucketName = "WARNING_UNWANTED_PAGE_";
} }
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI"); let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
@ -2969,7 +2975,9 @@ var BrowserOnClick = {
bucketName += isTopFrame ? "TOP_" : "FRAME_"; bucketName += isTopFrame ? "TOP_" : "FRAME_";
switch (elementId) { switch (elementId) {
case "getMeOutButton": case "getMeOutButton":
secHistogram.add(nsISecTel[bucketName + "GET_ME_OUT_OF_HERE"]); if (sendTelemetry) {
secHistogram.add(nsISecTel[bucketName + "GET_ME_OUT_OF_HERE"]);
}
getMeOutOfHere(); getMeOutOfHere();
break; break;
@ -2979,13 +2987,16 @@ var BrowserOnClick = {
// We log even if malware/phishing/unwanted info URL couldn't be found: // 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 // 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"); openHelpLink("phishing-malware", false, "current");
break; break;
case "ignoreWarningButton": case "ignoreWarningButton":
secHistogram.add(nsISecTel[bucketName + "IGNORE_WARNING"]); if (sendTelemetry) {
secHistogram.add(nsISecTel[bucketName + "IGNORE_WARNING"]);
}
this.ignoreWarningButton(reason); this.ignoreWarningButton(reason);
break; break;
} }
@ -3054,6 +3065,8 @@ var BrowserOnClick = {
title = gNavigatorBundle.getString("safebrowsing.reportedUnwantedSite"); title = gNavigatorBundle.getString("safebrowsing.reportedUnwantedSite");
// There is no button for reporting errors since Google doesn't currently // There is no button for reporting errors since Google doesn't currently
// provide a URL endpoint for these reports. // provide a URL endpoint for these reports.
} else {
return; // no notifications for forbidden sites
} }
let notificationBox = gBrowser.getNotificationBox(); let notificationBox = gBrowser.getNotificationBox();

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

@ -460,6 +460,8 @@ var ClickEventHandler = {
reason = 'malware'; reason = 'malware';
} else if (/e=unwantedBlocked/.test(ownerDoc.documentURI)) { } else if (/e=unwantedBlocked/.test(ownerDoc.documentURI)) {
reason = 'unwanted'; reason = 'unwanted';
} else if (/e=forbiddenBlocked/.test(ownerDoc.documentURI)) {
reason = 'forbidden';
} }
sendAsyncMessage("Browser:SiteBlockedError", { sendAsyncMessage("Browser:SiteBlockedError", {
location: ownerDoc.location.href, location: ownerDoc.location.href,

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

@ -5,7 +5,7 @@
Components.utils.import("resource:///modules/SitePermissions.jsm"); Components.utils.import("resource:///modules/SitePermissions.jsm");
Components.utils.import("resource://gre/modules/BrowserUtils.jsm"); Components.utils.import("resource://gre/modules/BrowserUtils.jsm");
const nsIQuotaManager = Components.interfaces.nsIQuotaManager; const nsIQuotaManagerService = Components.interfaces.nsIQuotaManagerService;
var gPermURI; var gPermURI;
var gUsageRequest; var gUsageRequest;
@ -186,13 +186,15 @@ function initIndexedDBRow()
row.appendChild(extras); row.appendChild(extras);
var quotaManager = Components.classes["@mozilla.org/dom/quota/manager;1"] var quotaManagerService =
.getService(nsIQuotaManager); Components.classes["@mozilla.org/dom/quota-manager-service;1"]
.getService(nsIQuotaManagerService);
let principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"] let principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
.getService(Components.interfaces.nsIScriptSecurityManager) .getService(Components.interfaces.nsIScriptSecurityManager)
.createCodebasePrincipal(gPermURI, {}); .createCodebasePrincipal(gPermURI, {});
gUsageRequest = gUsageRequest =
quotaManager.getUsageForPrincipal(principal, onIndexedDBUsageCallback); quotaManagerService.getUsageForPrincipal(principal,
onIndexedDBUsageCallback);
var status = document.getElementById("indexedDBStatus"); var status = document.getElementById("indexedDBStatus");
var button = document.getElementById("indexedDBClear"); var button = document.getElementById("indexedDBClear");
@ -208,8 +210,8 @@ function onIndexedDBClear()
.getService(Components.interfaces.nsIScriptSecurityManager) .getService(Components.interfaces.nsIScriptSecurityManager)
.createCodebasePrincipal(gPermURI, {}); .createCodebasePrincipal(gPermURI, {});
Components.classes["@mozilla.org/dom/quota/manager;1"] Components.classes["@mozilla.org/dom/quota-manager-service;1"]
.getService(nsIQuotaManager) .getService(nsIQuotaManagerService)
.clearStoragesForPrincipal(principal); .clearStoragesForPrincipal(principal);
Components.classes["@mozilla.org/serviceworkers/manager;1"] Components.classes["@mozilla.org/serviceworkers/manager;1"]
@ -220,14 +222,14 @@ function onIndexedDBClear()
initIndexedDBRow(); initIndexedDBRow();
} }
function onIndexedDBUsageCallback(principal, usage, fileUsage) function onIndexedDBUsageCallback(request)
{ {
let uri = principal.URI; let uri = request.principal.URI;
if (!uri.equals(gPermURI)) { if (!uri.equals(gPermURI)) {
throw new Error("Callback received for bad URI: " + uri); throw new Error("Callback received for bad URI: " + uri);
} }
if (usage) { if (request.usage) {
if (!("DownloadUtils" in window)) { if (!("DownloadUtils" in window)) {
Components.utils.import("resource://gre/modules/DownloadUtils.jsm"); Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
} }
@ -237,7 +239,7 @@ function onIndexedDBUsageCallback(principal, usage, fileUsage)
status.value = status.value =
gBundle.getFormattedString("indexedDBUsage", gBundle.getFormattedString("indexedDBUsage",
DownloadUtils.convertByteUnits(usage)); DownloadUtils.convertByteUnits(request.usage));
status.removeAttribute("hidden"); status.removeAttribute("hidden");
button.removeAttribute("hidden"); button.removeAttribute("hidden");
} }

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

@ -360,6 +360,10 @@ var gTests = [
EventUtils.synthesizeKey("a", { accelKey: true }); EventUtils.synthesizeKey("a", { accelKey: true });
EventUtils.synthesizeKey("VK_DELETE", {}); EventUtils.synthesizeKey("VK_DELETE", {});
ok(table.hidden, "Search suggestion table hidden"); ok(table.hidden, "Search suggestion table hidden");
try {
Services.search.removeEngine(engine);
} catch (ex) { }
}); });
} }
}, },
@ -369,6 +373,12 @@ var gTests = [
run: function() run: function()
{ {
return Task.spawn(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" // Start composition and type "x"
let input = gBrowser.contentDocument.getElementById("searchText"); let input = gBrowser.contentDocument.getElementById("searchText");
input.focus(); input.focus();

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

@ -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 offlineEvent.html
subtst_contextmenu.html subtst_contextmenu.html
video.ogg video.ogg
bug_1182546.xml
[test_bug364677.html] [test_bug364677.html]
[test_bug395533.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? skip-if = buildapp == 'mulet' || e10s # Bug 1066070 - I don't think either popup notifications nor addon install stuff works?
[test_offline_gzip.html] [test_offline_gzip.html]
skip-if = buildapp == 'mulet' || e10s # Bug 1066070 - I don't think either popup notifications nor addon install stuff works? skip-if = buildapp == 'mulet' || e10s # Bug 1066070 - I don't think either popup notifications nor addon install stuff works?
[test_bug1182546.html]

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

@ -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. // Migrate unencrypted cookies.
yield promiseMigration(migrator, MigrationUtils.resourceTypes.COOKIES, PROFILE); 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, Assert.equal(Services.cookies.countCookiesFromHost(COOKIE.host), 1,
"Migrated the expected number of unencrypted cookies"); "Migrated the expected number of unencrypted cookies");
Assert.equal(Services.cookies.countCookiesFromHost("encryptedcookie.invalid"), 0, Assert.equal(Services.cookies.countCookiesFromHost("encryptedcookie.invalid"), 0,
@ -46,4 +41,10 @@ add_task(function* () {
for (let prop of Object.keys(COOKIE)) { for (let prop of Object.keys(COOKIE)) {
Assert.equal(foundCookie[prop], COOKIE[prop], "Check cookie " + prop); 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] [DEFAULT]
support-files = head.js support-files = head.js
[browser_forbidden.js]
[browser_bug400731.js] [browser_bug400731.js]
skip-if = e10s skip-if = e10s
[browser_bug415846.js] [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.malwareTable", "test-malware-simple,test-unwanted-simple");
Services.prefs.setCharPref("urlclassifier.phishTable", "test-phish-simple"); Services.prefs.setCharPref("urlclassifier.phishTable", "test-phish-simple");
Services.prefs.setBoolPref("browser.safebrowsing.forbiddenURIs.enabled", true);
SafeBrowsing.init(); SafeBrowsing.init();

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

@ -7,5 +7,5 @@
DEFINES['APP_VERSION'] = CONFIG['FIREFOX_VERSION'] DEFINES['APP_VERSION'] = CONFIG['FIREFOX_VERSION']
DEFINES['MOZ_APP_NAME'] = CONFIG['MOZ_APP_NAME'] 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'] DEFINES['MOZILLA_VERSION'] = CONFIG['MOZILLA_VERSION']

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

@ -8,16 +8,21 @@
<!ENTITY safeb.palm.reportPage.label "Why was this page blocked?"> <!ENTITY safeb.palm.reportPage.label "Why was this page blocked?">
<!ENTITY safeb.blocked.malwarePage.title "Reported Attack Page!"> <!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.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.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!"> <!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.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.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!"> <!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.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.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. 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. 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. 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. 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. 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. 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> <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.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>"> <!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"?> <?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" <svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"

До

Ширина:  |  Высота:  |  Размер: 1.6 KiB

После

Ширина:  |  Высота:  |  Размер: 1.5 KiB

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

@ -4,14 +4,45 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/devtools/DominatorTree.h" #include "mozilla/devtools/DominatorTree.h"
#include "js/Debug.h"
#include "mozilla/CycleCollectedJSRuntime.h"
#include "mozilla/dom/DominatorTreeBinding.h" #include "mozilla/dom/DominatorTreeBinding.h"
namespace mozilla { namespace mozilla {
namespace devtools { 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 *****************************************************************/ /*** 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_ADDREF(DominatorTree)
NS_IMPL_CYCLE_COLLECTING_RELEASE(DominatorTree) NS_IMPL_CYCLE_COLLECTING_RELEASE(DominatorTree)

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

@ -6,6 +6,7 @@
#ifndef mozilla_devtools_DominatorTree__ #ifndef mozilla_devtools_DominatorTree__
#define mozilla_devtools_DominatorTree__ #define mozilla_devtools_DominatorTree__
#include "mozilla/devtools/HeapSnapshot.h"
#include "mozilla/dom/BindingDeclarations.h" #include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/ErrorResult.h" #include "mozilla/ErrorResult.h"
#include "mozilla/RefCounted.h" #include "mozilla/RefCounted.h"
@ -25,13 +26,17 @@ protected:
private: private:
JS::ubi::DominatorTree mDominatorTree; JS::ubi::DominatorTree mDominatorTree;
RefPtr<HeapSnapshot> mHeapSnapshot;
public: public:
explicit DominatorTree(JS::ubi::DominatorTree&& aDominatorTree, nsISupports* aParent) explicit DominatorTree(JS::ubi::DominatorTree&& aDominatorTree, HeapSnapshot* aHeapSnapshot,
nsISupports* aParent)
: mParent(aParent) : mParent(aParent)
, mDominatorTree(Move(aDominatorTree)) , mDominatorTree(Move(aDominatorTree))
, mHeapSnapshot(aHeapSnapshot)
{ {
MOZ_ASSERT(aParent); MOZ_ASSERT(aParent);
MOZ_ASSERT(aHeapSnapshot);
}; };
NS_DECL_CYCLE_COLLECTING_ISUPPORTS; NS_DECL_CYCLE_COLLECTING_ISUPPORTS;
@ -42,7 +47,11 @@ public:
virtual JSObject* WrapObject(JSContext* aCx, virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override; JS::Handle<JSObject*> aGivenProto) override;
// readonly attribute NodeId root
uint64_t Root() const { return mDominatorTree.root().identifier(); } 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 } // namespace devtools

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

@ -11,12 +11,15 @@
#include "js/Debug.h" #include "js/Debug.h"
#include "js/TypeDecls.h" #include "js/TypeDecls.h"
#include "js/UbiNodeCensus.h"
#include "js/UbiNodeBreadthFirst.h" #include "js/UbiNodeBreadthFirst.h"
#include "js/UbiNodeCensus.h"
#include "js/UbiNodeDominatorTree.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/CycleCollectedJSRuntime.h"
#include "mozilla/devtools/AutoMemMap.h" #include "mozilla/devtools/AutoMemMap.h"
#include "mozilla/devtools/CoreDump.pb.h" #include "mozilla/devtools/CoreDump.pb.h"
#include "mozilla/devtools/DeserializedNode.h" #include "mozilla/devtools/DeserializedNode.h"
#include "mozilla/devtools/DominatorTree.h"
#include "mozilla/devtools/FileDescriptorOutputStream.h" #include "mozilla/devtools/FileDescriptorOutputStream.h"
#include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h" #include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
#include "mozilla/devtools/ZeroCopyNSIOutputStream.h" #include "mozilla/devtools/ZeroCopyNSIOutputStream.h"
@ -538,7 +541,7 @@ HeapSnapshot::ComputeDominatorTree(ErrorResult& rv)
return nullptr; return nullptr;
} }
return MakeAndAddRef<DominatorTree>(Move(*maybeTree), mParent); return MakeAndAddRef<DominatorTree>(Move(*maybeTree), this, mParent);
} }

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

@ -9,7 +9,6 @@
#include "js/HashTable.h" #include "js/HashTable.h"
#include "mozilla/ErrorResult.h" #include "mozilla/ErrorResult.h"
#include "mozilla/devtools/DeserializedNode.h" #include "mozilla/devtools/DeserializedNode.h"
#include "mozilla/devtools/DominatorTree.h"
#include "mozilla/dom/BindingDeclarations.h" #include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/Nullable.h" #include "mozilla/dom/Nullable.h"
#include "mozilla/HashFunctions.h" #include "mozilla/HashFunctions.h"
@ -30,6 +29,8 @@
namespace mozilla { namespace mozilla {
namespace devtools { namespace devtools {
class DominatorTree;
struct NSFreePolicy { struct NSFreePolicy {
void operator()(void* ptr) { void operator()(void* ptr) {
NS_Free(ptr); NS_Free(ptr);
@ -148,6 +149,13 @@ public:
return JS::ubi::Node(const_cast<DeserializedNode*>(&node)); 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, void TakeCensus(JSContext* cx, JS::HandleObject options,
JS::MutableHandleValue rval, ErrorResult& rv); JS::MutableHandleValue rval, ErrorResult& rv);

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

@ -79,8 +79,8 @@ ZeroCopyNSIOutputStream::Next(void** data, int* size)
void void
ZeroCopyNSIOutputStream::BackUp(int count) ZeroCopyNSIOutputStream::BackUp(int count)
{ {
MOZ_ASSERT(count > 0, MOZ_ASSERT(count >= 0,
"Must back up a positive number of bytes."); "Cannot back up a negative amount of bytes.");
MOZ_ASSERT(amountUsed == BUFFER_SIZE, MOZ_ASSERT(amountUsed == BUFFER_SIZE,
"Can only call BackUp directly after calling Next."); "Can only call BackUp directly after calling Next.");
MOZ_ASSERT(count <= amountUsed, 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_01.js]
[test_DominatorTree_02.js] [test_DominatorTree_02.js]
[test_DominatorTree_03.js] [test_DominatorTree_03.js]
[test_DominatorTree_04.js]
[test_HeapAnalyses_getCreationTime_01.js] [test_HeapAnalyses_getCreationTime_01.js]
[test_HeapAnalyses_readHeapSnapshot_01.js] [test_HeapAnalyses_readHeapSnapshot_01.js]
[test_HeapAnalyses_takeCensusDiff_01.js] [test_HeapAnalyses_takeCensusDiff_01.js]

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

@ -4909,7 +4909,8 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
} }
} else if (NS_ERROR_PHISHING_URI == aError || } else if (NS_ERROR_PHISHING_URI == aError ||
NS_ERROR_MALWARE_URI == aError || NS_ERROR_MALWARE_URI == aError ||
NS_ERROR_UNWANTED_URI == aError) { NS_ERROR_UNWANTED_URI == aError ||
NS_ERROR_FORBIDDEN_URI == aError) {
nsAutoCString host; nsAutoCString host;
aURI->GetHost(host); aURI->GetHost(host);
CopyUTF8toUTF16(host, formatStrs[0]); CopyUTF8toUTF16(host, formatStrs[0]);
@ -4924,21 +4925,27 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
} }
uint32_t bucketId; uint32_t bucketId;
bool sendTelemetry = false;
if (NS_ERROR_PHISHING_URI == aError) { if (NS_ERROR_PHISHING_URI == aError) {
sendTelemetry = true;
error.AssignLiteral("phishingBlocked"); error.AssignLiteral("phishingBlocked");
bucketId = IsFrame() ? nsISecurityUITelemetry::WARNING_PHISHING_PAGE_FRAME bucketId = IsFrame() ? nsISecurityUITelemetry::WARNING_PHISHING_PAGE_FRAME
: nsISecurityUITelemetry::WARNING_PHISHING_PAGE_TOP; : nsISecurityUITelemetry::WARNING_PHISHING_PAGE_TOP;
} else if (NS_ERROR_MALWARE_URI == aError) { } else if (NS_ERROR_MALWARE_URI == aError) {
sendTelemetry = true;
error.AssignLiteral("malwareBlocked"); error.AssignLiteral("malwareBlocked");
bucketId = IsFrame() ? nsISecurityUITelemetry::WARNING_MALWARE_PAGE_FRAME bucketId = IsFrame() ? nsISecurityUITelemetry::WARNING_MALWARE_PAGE_FRAME
: nsISecurityUITelemetry::WARNING_MALWARE_PAGE_TOP; : nsISecurityUITelemetry::WARNING_MALWARE_PAGE_TOP;
} else { } else if (NS_ERROR_UNWANTED_URI == aError) {
sendTelemetry = true;
error.AssignLiteral("unwantedBlocked"); error.AssignLiteral("unwantedBlocked");
bucketId = IsFrame() ? nsISecurityUITelemetry::WARNING_UNWANTED_PAGE_FRAME bucketId = IsFrame() ? nsISecurityUITelemetry::WARNING_UNWANTED_PAGE_FRAME
: nsISecurityUITelemetry::WARNING_UNWANTED_PAGE_TOP; : 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); Telemetry::Accumulate(Telemetry::SECURITY_UI, bucketId);
} }
@ -7699,6 +7706,7 @@ nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_MALWARE_URI ||
aStatus == NS_ERROR_PHISHING_URI || aStatus == NS_ERROR_PHISHING_URI ||
aStatus == NS_ERROR_UNWANTED_URI || aStatus == NS_ERROR_UNWANTED_URI ||
aStatus == NS_ERROR_FORBIDDEN_URI ||
aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE || aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
aStatus == NS_ERROR_REMOTE_XUL || aStatus == NS_ERROR_REMOTE_XUL ||
aStatus == NS_ERROR_INTERCEPTION_FAILED || aStatus == NS_ERROR_INTERCEPTION_FAILED ||

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

@ -295,6 +295,7 @@
<h1 id="et_nssBadCert">&nssBadCert.title;</h1> <h1 id="et_nssBadCert">&nssBadCert.title;</h1>
<h1 id="et_malwareBlocked">&malwareBlocked.title;</h1> <h1 id="et_malwareBlocked">&malwareBlocked.title;</h1>
<h1 id="et_unwantedBlocked">&unwantedBlocked.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_cspBlocked">&cspBlocked.title;</h1>
<h1 id="et_remoteXUL">&remoteXUL.title;</h1> <h1 id="et_remoteXUL">&remoteXUL.title;</h1>
<h1 id="et_corruptedContentError">&corruptedContentError.title;</h1> <h1 id="et_corruptedContentError">&corruptedContentError.title;</h1>
@ -322,6 +323,7 @@
<div id="ed_nssBadCert">&nssBadCert.longDesc2;</div> <div id="ed_nssBadCert">&nssBadCert.longDesc2;</div>
<div id="ed_malwareBlocked">&malwareBlocked.longDesc;</div> <div id="ed_malwareBlocked">&malwareBlocked.longDesc;</div>
<div id="ed_unwantedBlocked">&unwantedBlocked.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_cspBlocked">&cspBlocked.longDesc;</div>
<div id="ed_remoteXUL">&remoteXUL.longDesc;</div> <div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
<div id="ed_corruptedContentError">&corruptedContentError.longDesc;</div> <div id="ed_corruptedContentError">&corruptedContentError.longDesc;</div>

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

@ -37,7 +37,7 @@ ArchiveReader::Constructor(const GlobalObject& aGlobal,
nsAutoCString encoding; nsAutoCString encoding;
if (!EncodingUtils::FindEncodingForLabelNoReplacement(aOptions.mEncoding, if (!EncodingUtils::FindEncodingForLabelNoReplacement(aOptions.mEncoding,
encoding)) { encoding)) {
aError.ThrowRangeError<MSG_ENCODING_NOT_SUPPORTED>(&aOptions.mEncoding); aError.ThrowRangeError<MSG_ENCODING_NOT_SUPPORTED>(aOptions.mEncoding);
return nullptr; return nullptr;
} }

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

@ -329,35 +329,6 @@ protected:
void* mMappedMemory; 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. // 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. // 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 // This runnable gets registered as an IPDL subprotocol actor so that it
@ -503,6 +474,9 @@ private:
nsresult nsresult
InitOnMainThread(); InitOnMainThread();
void
OpenDirectory();
nsresult nsresult
ReadMetadata(); ReadMetadata();
@ -518,7 +492,7 @@ private:
void void
DispatchToIOThread() DispatchToIOThread()
{ {
MOZ_ASSERT(NS_IsMainThread()); AssertIsOnOwningThread();
// If shutdown just started, the QuotaManager may have been deleted. // If shutdown just started, the QuotaManager may have been deleted.
QuotaManager* qm = QuotaManager::Get(); QuotaManager* qm = QuotaManager::Get();
@ -593,8 +567,8 @@ private:
// A cache entry has been selected to open. // A cache entry has been selected to open.
mModuleIndex = aModuleIndex; mModuleIndex = aModuleIndex;
mState = eDispatchToMainThread; mState = eReadyToOpenCacheFileForRead;
NS_DispatchToMainThread(this); DispatchToIOThread();
return true; return true;
} }
@ -630,12 +604,13 @@ private:
enum State { enum State {
eInitial, // Just created, waiting to be dispatched to main thread 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 eWaitingToOpenMetadata, // Waiting to be called back from OpenDirectory
eReadyToReadMetadata, // Waiting to read the metadata file on the IO thread eReadyToReadMetadata, // Waiting to read the metadata file on the IO thread
eFailedToReadMetadata, // Waiting to be dispatched to owning thread after fail eFailedToReadMetadata, // Waiting to be dispatched to owning thread after fail
eSendingMetadataForRead, // Waiting to send OnOpenMetadataForRead eSendingMetadataForRead, // Waiting to send OnOpenMetadataForRead
eWaitingToOpenCacheFileForRead, // Waiting to hear back from child eWaitingToOpenCacheFileForRead, // Waiting to hear back from child
eDispatchToMainThread, // IO thread dispatch allowed from main thread only
eReadyToOpenCacheFileForRead, // Waiting to open cache file for read eReadyToOpenCacheFileForRead, // Waiting to open cache file for read
eSendingCacheFile, // Waiting to send OnOpenCacheFile on the owning thread eSendingCacheFile, // Waiting to send OnOpenCacheFile on the owning thread
eOpened, // Finished calling OnOpenCacheFile, waiting to be closed eOpened, // Finished calling OnOpenCacheFile, waiting to be closed
@ -711,9 +686,6 @@ ParentRunnable::InitOnMainThread()
return rv; return rv;
} }
QuotaManager* qm = QuotaManager::GetOrCreate();
NS_ENSURE_STATE(qm);
rv = QuotaManager::GetInfoFromPrincipal(principal, &mGroup, &mOrigin, rv = QuotaManager::GetInfoFromPrincipal(principal, &mGroup, &mOrigin,
&mIsApp); &mIsApp);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -726,6 +698,26 @@ ParentRunnable::InitOnMainThread()
return NS_OK; 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 nsresult
ParentRunnable::ReadMetadata() ParentRunnable::ReadMetadata()
{ {
@ -903,12 +895,7 @@ ParentRunnable::FinishOnOwningThread()
// releasing the directory lock. // releasing the directory lock.
FileDescriptorHolder::Finish(); FileDescriptorHolder::Finish();
if (mDirectoryLock) { mDirectoryLock = nullptr;
RefPtr<UnlockDirectoryRunnable> runnable =
new UnlockDirectoryRunnable(mDirectoryLock.forget());
NS_DispatchToMainThread(runnable);
}
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -928,17 +915,41 @@ ParentRunnable::Run()
return NS_OK; 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. return NS_OK;
QuotaManager::Get()->OpenDirectory(mPersistence, }
mGroup,
mOrigin,
mIsApp,
quota::Client::ASMJS,
/* aExclusive */ true,
this);
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; return NS_OK;
} }
@ -999,14 +1010,6 @@ ParentRunnable::Run()
return NS_OK; return NS_OK;
} }
case eDispatchToMainThread: {
MOZ_ASSERT(NS_IsMainThread());
mState = eReadyToOpenCacheFileForRead;
DispatchToIOThread();
return NS_OK;
}
case eReadyToOpenCacheFileForRead: { case eReadyToOpenCacheFileForRead: {
AssertIsOnIOThread(); AssertIsOnIOThread();
MOZ_ASSERT(mOpenMode == eOpenForRead); MOZ_ASSERT(mOpenMode == eOpenForRead);
@ -1064,7 +1067,7 @@ ParentRunnable::Run()
void void
ParentRunnable::DirectoryLockAcquired(DirectoryLock* aLock) ParentRunnable::DirectoryLockAcquired(DirectoryLock* aLock)
{ {
MOZ_ASSERT(NS_IsMainThread()); AssertIsOnOwningThread();
MOZ_ASSERT(mState == eWaitingToOpenMetadata); MOZ_ASSERT(mState == eWaitingToOpenMetadata);
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLock);
@ -1077,11 +1080,11 @@ ParentRunnable::DirectoryLockAcquired(DirectoryLock* aLock)
void void
ParentRunnable::DirectoryLockFailed() ParentRunnable::DirectoryLockFailed()
{ {
MOZ_ASSERT(NS_IsMainThread()); AssertIsOnOwningThread();
MOZ_ASSERT(mState == eWaitingToOpenMetadata); MOZ_ASSERT(mState == eWaitingToOpenMetadata);
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLock);
FailOnNonOwningThread(); Fail();
} }
NS_IMPL_ISUPPORTS_INHERITED0(ParentRunnable, FileDescriptorHolder) NS_IMPL_ISUPPORTS_INHERITED0(ParentRunnable, FileDescriptorHolder)
@ -1812,7 +1815,11 @@ public:
{ } { }
virtual void virtual void
PerformIdleMaintenance() override StartIdleMaintenance() override
{ }
virtual void
StopIdleMaintenance() override
{ } { }
virtual void virtual void

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

@ -305,14 +305,13 @@ AutoJSAPI::AutoJSAPI()
: mCx(nullptr) : mCx(nullptr)
, mOwnErrorReporting(false) , mOwnErrorReporting(false)
, mOldAutoJSAPIOwnsErrorReporting(false) , mOldAutoJSAPIOwnsErrorReporting(false)
, mIsMainThread(false) // For lack of anything better
{ {
} }
AutoJSAPI::~AutoJSAPI() AutoJSAPI::~AutoJSAPI()
{ {
if (mOwnErrorReporting) { if (mOwnErrorReporting) {
MOZ_ASSERT(NS_IsMainThread(), "See corresponding assertion in TakeOwnershipOfErrorReporting()");
ReportException(); ReportException();
// We need to do this _after_ processing the existing exception, because the // 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) AutoJSAPI::InitInternal(JSObject* aGlobal, JSContext* aCx, bool aIsMainThread)
{ {
MOZ_ASSERT(aCx); MOZ_ASSERT(aCx);
MOZ_ASSERT(aIsMainThread == NS_IsMainThread());
mCx = aCx; mCx = aCx;
mIsMainThread = aIsMainThread;
if (aIsMainThread) { if (aIsMainThread) {
// This Rooted<> is necessary only as long as AutoCxPusher::AutoCxPusher // This Rooted<> is necessary only as long as AutoCxPusher::AutoCxPusher
// can GC, which is only possible because XPCJSContextStack::Push calls // can GC, which is only possible because XPCJSContextStack::Push calls
@ -357,11 +359,12 @@ AutoJSAPI::AutoJSAPI(nsIGlobalObject* aGlobalObject,
JSContext* aCx) JSContext* aCx)
: mOwnErrorReporting(false) : mOwnErrorReporting(false)
, mOldAutoJSAPIOwnsErrorReporting(false) , mOldAutoJSAPIOwnsErrorReporting(false)
, mIsMainThread(aIsMainThread)
{ {
MOZ_ASSERT(aGlobalObject); MOZ_ASSERT(aGlobalObject);
MOZ_ASSERT(aGlobalObject->GetGlobalJSObject(), "Must have a JS global"); MOZ_ASSERT(aGlobalObject->GetGlobalJSObject(), "Must have a JS global");
MOZ_ASSERT(aCx); MOZ_ASSERT(aCx);
MOZ_ASSERT_IF(aIsMainThread, NS_IsMainThread()); MOZ_ASSERT(aIsMainThread == NS_IsMainThread());
InitInternal(aGlobalObject->GetGlobalJSObject(), aCx, aIsMainThread); InitInternal(aGlobalObject->GetGlobalJSObject(), aCx, aIsMainThread);
} }
@ -460,7 +463,9 @@ AutoJSAPI::InitWithLegacyErrorReporting(nsGlobalWindow* aWindow)
void void
WarningOnlyErrorReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aRep) WarningOnlyErrorReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aRep)
{ {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(JSREPORT_IS_WARNING(aRep->flags)); MOZ_ASSERT(JSREPORT_IS_WARNING(aRep->flags));
RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport(); RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
nsPIDOMWindow* win = xpc::CurrentWindowOrNull(aCx); nsPIDOMWindow* win = xpc::CurrentWindowOrNull(aCx);
xpcReport->Init(aRep, aMessage, nsContentUtils::IsCallerChrome(), xpcReport->Init(aRep, aMessage, nsContentUtils::IsCallerChrome(),
@ -471,14 +476,19 @@ WarningOnlyErrorReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aR
void void
AutoJSAPI::TakeOwnershipOfErrorReporting() AutoJSAPI::TakeOwnershipOfErrorReporting()
{ {
MOZ_ASSERT(NS_IsMainThread(), "Can't own error reporting off-main-thread yet");
MOZ_ASSERT(!mOwnErrorReporting); MOZ_ASSERT(!mOwnErrorReporting);
mOwnErrorReporting = true; mOwnErrorReporting = true;
JSRuntime *rt = JS_GetRuntime(cx()); JSRuntime *rt = JS_GetRuntime(cx());
mOldAutoJSAPIOwnsErrorReporting = JS::ContextOptionsRef(cx()).autoJSAPIOwnsErrorReporting(); mOldAutoJSAPIOwnsErrorReporting = JS::ContextOptionsRef(cx()).autoJSAPIOwnsErrorReporting();
JS::ContextOptionsRef(cx()).setAutoJSAPIOwnsErrorReporting(true); 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 void
@ -498,18 +508,35 @@ AutoJSAPI::ReportException()
if (!errorGlobal) if (!errorGlobal)
errorGlobal = xpc::PrivilegedJunkScope(); errorGlobal = xpc::PrivilegedJunkScope();
JSAutoCompartment ac(cx(), errorGlobal); JSAutoCompartment ac(cx(), errorGlobal);
nsCOMPtr<nsPIDOMWindow> win = xpc::WindowGlobalOrNull(errorGlobal);
JS::Rooted<JS::Value> exn(cx()); JS::Rooted<JS::Value> exn(cx());
js::ErrorReport jsReport(cx()); js::ErrorReport jsReport(cx());
if (StealException(&exn) && jsReport.init(cx(), exn)) { if (StealException(&exn) && jsReport.init(cx(), exn)) {
RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport(); if (mIsMainThread) {
xpcReport->Init(jsReport.report(), jsReport.message(), RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
nsContentUtils::IsCallerChrome(), nsCOMPtr<nsPIDOMWindow> win = xpc::WindowGlobalOrNull(errorGlobal);
win ? win->WindowID() : 0); xpcReport->Init(jsReport.report(), jsReport.message(),
if (win) { nsContentUtils::IsCallerChrome(),
DispatchScriptErrorEvent(win, JS_GetRuntime(cx()), xpcReport, exn); win ? win->WindowID() : 0);
if (win) {
DispatchScriptErrorEvent(win, JS_GetRuntime(cx()), xpcReport, exn);
} else {
xpcReport->LogToConsole();
}
} else { } 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 { } else {
NS_WARNING("OOMed while acquiring uncaught exception from JSAPI"); NS_WARNING("OOMed while acquiring uncaught exception from JSAPI");
@ -519,7 +546,7 @@ AutoJSAPI::ReportException()
bool bool
AutoJSAPI::StealException(JS::MutableHandle<JS::Value> aVal) AutoJSAPI::StealException(JS::MutableHandle<JS::Value> aVal)
{ {
MOZ_ASSERT(CxPusherIsStackTop()); MOZ_ASSERT_IF(mIsMainThread, CxPusherIsStackTop());
MOZ_ASSERT(HasException()); MOZ_ASSERT(HasException());
MOZ_ASSERT(js::GetContextCompartment(cx())); MOZ_ASSERT(js::GetContextCompartment(cx()));
if (!JS_GetPendingException(cx(), aVal)) { if (!JS_GetPendingException(cx(), aVal)) {

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

@ -262,7 +262,7 @@ public:
JSContext* cx() const { JSContext* cx() const {
MOZ_ASSERT(mCx, "Must call Init before using an AutoJSAPI"); MOZ_ASSERT(mCx, "Must call Init before using an AutoJSAPI");
MOZ_ASSERT_IF(NS_IsMainThread(), CxPusherIsStackTop()); MOZ_ASSERT_IF(mIsMainThread, CxPusherIsStackTop());
return mCx; return mCx;
} }
@ -279,7 +279,7 @@ public:
void ReportException(); void ReportException();
bool HasException() const { bool HasException() const {
MOZ_ASSERT(CxPusherIsStackTop()); MOZ_ASSERT_IF(NS_IsMainThread(), CxPusherIsStackTop());
return JS_IsExceptionPending(cx()); return JS_IsExceptionPending(cx());
}; };
@ -292,7 +292,7 @@ public:
bool StealException(JS::MutableHandle<JS::Value> aVal); bool StealException(JS::MutableHandle<JS::Value> aVal);
void ClearException() { void ClearException() {
MOZ_ASSERT(CxPusherIsStackTop()); MOZ_ASSERT_IF(NS_IsMainThread(), CxPusherIsStackTop());
JS_ClearPendingException(cx()); JS_ClearPendingException(cx());
} }
@ -312,6 +312,8 @@ private:
// Track state between the old and new error reporting modes. // Track state between the old and new error reporting modes.
bool mOwnErrorReporting; bool mOwnErrorReporting;
bool mOldAutoJSAPIOwnsErrorReporting; bool mOldAutoJSAPIOwnsErrorReporting;
// Whether we're mainthread or not; set when we're initialized.
bool mIsMainThread;
Maybe<JSErrorReporter> mOldErrorReporter; Maybe<JSErrorReporter> mOldErrorReporter;
void InitInternal(JSObject* aGlobal, JSContext* aCx, bool aIsMainThread); 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, nsresult rv = NS_NewURI(getter_AddRefs(baseUri), aBase, nullptr, nullptr,
nsContentUtils::GetIOService()); nsContentUtils::GetIOService());
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.ThrowTypeError<MSG_INVALID_URL>(&aBase); aRv.ThrowTypeError<MSG_INVALID_URL>(aBase);
return nullptr; 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, nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, nullptr, aBase,
nsContentUtils::GetIOService()); nsContentUtils::GetIOService());
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.ThrowTypeError<MSG_INVALID_URL>(&aUrl); aRv.ThrowTypeError<MSG_INVALID_URL>(aUrl);
return nullptr; return nullptr;
} }
@ -229,8 +229,7 @@ URL::SetHref(const nsAString& aHref, ErrorResult& aRv)
nsCOMPtr<nsIURI> uri; nsCOMPtr<nsIURI> uri;
rv = ioService->NewURI(href, nullptr, nullptr, getter_AddRefs(uri)); rv = ioService->NewURI(href, nullptr, nullptr, getter_AddRefs(uri));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
nsAutoString label(aHref); aRv.ThrowTypeError<MSG_INVALID_URL>(aHref);
aRv.ThrowTypeError<MSG_INVALID_URL>(&label);
return; return;
} }

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

@ -158,7 +158,7 @@ WindowNamedPropertiesHandler::defineProperty(JSContext* aCx,
{ {
ErrorResult rv; ErrorResult rv;
rv.ThrowTypeError<MSG_DEFINEPROPERTY_ON_GSP>(); rv.ThrowTypeError<MSG_DEFINEPROPERTY_ON_GSP>();
rv.ReportErrorWithMessage(aCx); rv.MaybeSetPendingException(aCx);
return false; return false;
} }

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

@ -5115,19 +5115,17 @@ nsDocument::DocumentStatesChanged(EventStates aStateMask)
void void
nsDocument::StyleRuleChanged(CSSStyleSheet* aSheet, nsDocument::StyleRuleChanged(CSSStyleSheet* aSheet,
css::Rule* aOldStyleRule, css::Rule* aStyleRule)
css::Rule* aNewStyleRule)
{ {
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleChanged, NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleChanged,
(this, aSheet, (this, aSheet,
aOldStyleRule, aNewStyleRule)); aStyleRule));
if (StyleSheetChangeEventsEnabled()) { if (StyleSheetChangeEventsEnabled()) {
DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent, DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent,
"StyleRuleChanged", "StyleRuleChanged",
mRule, mRule,
aNewStyleRule ? aNewStyleRule->GetDOMRule() aStyleRule ? aStyleRule->GetDOMRule() : nullptr);
: nullptr);
} }
} }

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

@ -884,8 +884,7 @@ public:
mozilla::EventStates aStateMask) override; mozilla::EventStates aStateMask) override;
virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet, virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet,
mozilla::css::Rule* aOldStyleRule, mozilla::css::Rule* aStyleRule) override;
mozilla::css::Rule* aNewStyleRule) override;
virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet, virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet,
mozilla::css::Rule* aStyleRule) override; mozilla::css::Rule* aStyleRule) override;
virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet, virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet,

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

@ -6138,10 +6138,12 @@ nsGlobalWindow::FinishFullscreenChange(bool aIsFullscreen)
mWakeLock = pmService->NewWakeLock(NS_LITERAL_STRING("DOM_Fullscreen"), mWakeLock = pmService->NewWakeLock(NS_LITERAL_STRING("DOM_Fullscreen"),
this, rv); this, rv);
NS_WARN_IF_FALSE(!rv.Failed(), "Failed to lock the wakelock"); NS_WARN_IF_FALSE(!rv.Failed(), "Failed to lock the wakelock");
rv.SuppressException();
} else if (mWakeLock && !mFullScreen) { } else if (mWakeLock && !mFullScreen) {
ErrorResult rv; ErrorResult rv;
mWakeLock->Unlock(rv); mWakeLock->Unlock(rv);
mWakeLock = nullptr; mWakeLock = nullptr;
rv.SuppressException();
} }
} }
@ -11764,6 +11766,7 @@ nsGlobalWindow::RunTimeoutHandler(nsTimeout* aTimeout,
ErrorResult ignored; ErrorResult ignored;
JS::Rooted<JS::Value> ignoredVal(CycleCollectedJSRuntime::Get()->Runtime()); JS::Rooted<JS::Value> ignoredVal(CycleCollectedJSRuntime::Get()->Runtime());
callback->Call(me, handler->GetArgs(), &ignoredVal, ignored, reason); callback->Call(me, handler->GetArgs(), &ignoredVal, ignored, reason);
ignored.SuppressException();
} }
// We ignore any failures from calling EvaluateString() on the context or // We ignore any failures from calling EvaluateString() on the context or

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

@ -1131,7 +1131,10 @@ public:
{ {
MOZ_ASSERT(IsOuterWindow()); MOZ_ASSERT(IsOuterWindow());
mozilla::ErrorResult ignored; 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, void Get_content(JSContext* aCx,

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

@ -49,19 +49,19 @@ public:
const nsTArray<nsString>& aStringParams) = 0; const nsTArray<nsString>& aStringParams) = 0;
// A version of AddConsoleReport() that accepts the message parameters // A version of AddConsoleReport() that accepts the message parameters
// as variable nsString arguments. Note, the parameters must be exactly // as variable nsString arguments (or really, any sort of const nsAString).
// nsString and not another string class. All other args the same as // All other args the same as AddConsoleReport().
// AddConsoleReport().
template<typename... Params> template<typename... Params>
void void
AddConsoleReport(uint32_t aErrorFlags, const nsACString& aCategory, AddConsoleReport(uint32_t aErrorFlags, const nsACString& aCategory,
nsContentUtils::PropertiesFile aPropertiesFile, nsContentUtils::PropertiesFile aPropertiesFile,
const nsACString& aSourceFileURI, uint32_t aLineNumber, const nsACString& aSourceFileURI, uint32_t aLineNumber,
uint32_t aColumnNumber, const nsACString& aMessageName, uint32_t aColumnNumber, const nsACString& aMessageName,
Params... aParams) Params&&... aParams)
{ {
nsTArray<nsString> params; 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, AddConsoleReport(aErrorFlags, aCategory, aPropertiesFile, aSourceFileURI,
aLineNumber, aColumnNumber, aMessageName, params); aLineNumber, aColumnNumber, aMessageName, params);
} }

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

@ -155,8 +155,8 @@ typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
} // namespace mozilla } // namespace mozilla
#define NS_IDOCUMENT_IID \ #define NS_IDOCUMENT_IID \
{ 0xecc9e376, 0x6c31, 0x4f04, \ { 0x13011a82, 0x46cd, 0x4c33, \
{ 0xbe, 0xde, 0xd6, 0x27, 0x61, 0xd7, 0x00, 0x84 } } { 0x9d, 0x4e, 0x31, 0x41, 0xbb, 0x3f, 0x18, 0xe9 } }
// Enum for requesting a particular type of document when creating a doc // Enum for requesting a particular type of document when creating a doc
enum DocumentFlavor { enum DocumentFlavor {
@ -1290,8 +1290,7 @@ public:
// Observation hooks for style data to propagate notifications // Observation hooks for style data to propagate notifications
// to document observers // to document observers
virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet, virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet,
mozilla::css::Rule* aOldStyleRule, mozilla::css::Rule* aStyleRule) = 0;
mozilla::css::Rule* aNewStyleRule) = 0;
virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet, virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet,
mozilla::css::Rule* aStyleRule) = 0; mozilla::css::Rule* aStyleRule) = 0;
virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet, virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet,

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

@ -21,8 +21,8 @@ class Rule;
} // namespace mozilla } // namespace mozilla
#define NS_IDOCUMENT_OBSERVER_IID \ #define NS_IDOCUMENT_OBSERVER_IID \
{ 0x21c8ad67, 0x3a7d, 0x4881, \ { 0x71041fa3, 0x6dd7, 0x4cde, \
{ 0xa5, 0x43, 0xcb, 0xa9, 0xbb, 0xe4, 0x9e, 0x39 } } { 0xbb, 0x76, 0xae, 0xcc, 0x69, 0xe1, 0x75, 0x78 } }
typedef uint32_t nsUpdateType; typedef uint32_t nsUpdateType;
@ -143,26 +143,13 @@ public:
* the document. The notification is passed on to all of * the document. The notification is passed on to all of
* the document observers. * 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 aDocument The document being observed
* @param aStyleSheet the StyleSheet that contians the rule * @param aStyleSheet the StyleSheet that contians the rule
* @param aOldStyleRule The rule being removed. This rule may not be * @param aStyleRule The rule being changed.
* fully valid anymore -- however, it can still
* be used for pointer comparison and
* |QueryInterface|.
* @param aNewStyleRule The rule being added.
*/ */
virtual void StyleRuleChanged(nsIDocument *aDocument, virtual void StyleRuleChanged(nsIDocument *aDocument,
mozilla::CSSStyleSheet* aStyleSheet, mozilla::CSSStyleSheet* aStyleSheet,
mozilla::css::Rule* aOldStyleRule, mozilla::css::Rule* aStyleRule) = 0;
mozilla::css::Rule* aNewStyleRule) = 0;
/** /**
* A StyleRule has just been added to a style sheet. * 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 \ #define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULECHANGED \
virtual void StyleRuleChanged(nsIDocument* aDocument, \ virtual void StyleRuleChanged(nsIDocument* aDocument, \
mozilla::CSSStyleSheet* aStyleSheet, \ mozilla::CSSStyleSheet* aStyleSheet, \
mozilla::css::Rule* aOldStyleRule, \ mozilla::css::Rule* aStyleRule) override;
mozilla::css::Rule* aNewStyleRule) override;
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEADDED \ #define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEADDED \
virtual void StyleRuleAdded(nsIDocument* aDocument, \ virtual void StyleRuleAdded(nsIDocument* aDocument, \
@ -327,8 +313,7 @@ _class::StyleSheetApplicableStateChanged(nsIDocument* aDocument, \
void \ void \
_class::StyleRuleChanged(nsIDocument* aDocument, \ _class::StyleRuleChanged(nsIDocument* aDocument, \
mozilla::CSSStyleSheet* aStyleSheet, \ mozilla::CSSStyleSheet* aStyleSheet, \
mozilla::css::Rule* aOldStyleRule, \ mozilla::css::Rule* aStyleRule) \
mozilla::css::Rule* aNewStyleRule) \
{ \ { \
} \ } \
void \ void \

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

@ -272,6 +272,8 @@ skip-if = buildapp == 'b2g' # Requires webgl support
[test_audioWindowUtils.html] [test_audioWindowUtils.html]
[test_audioNotification.html] [test_audioNotification.html]
skip-if = buildapp == 'mulet' skip-if = buildapp == 'mulet'
[test_audioNotificationStream.html]
skip-if = buildapp == 'mulet'
[test_audioNotificationStopOnNavigation.html] [test_audioNotificationStopOnNavigation.html]
skip-if = buildapp == 'mulet' skip-if = buildapp == 'mulet'
[test_audioNotificationWithEarlyPlay.html] [test_audioNotificationWithEarlyPlay.html]

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

@ -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. // Return InternalType here so we can work with it usefully.
InternalType& Construct() template<typename... Args>
InternalType& Construct(Args&&... aArgs)
{ {
mImpl.emplace(); mImpl.emplace(Forward<Args>(aArgs)...);
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);
return *mImpl; return *mImpl;
} }

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

@ -125,38 +125,6 @@ ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
NamesOfInterfacesWithProtos(aProtoId)); 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 bool
ThrowNoSetterArg(JSContext* aCx, prototypes::ID aProtoId) ThrowNoSetterArg(JSContext* aCx, prototypes::ID aProtoId)
{ {
@ -222,9 +190,9 @@ ErrorResult::DeserializeMessage(const IPC::Message* aMsg, void** aIter)
} }
void 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); MOZ_ASSERT(mUnionState == HasMessage);
Message* message = mMessage; Message* message = mMessage;
@ -241,6 +209,7 @@ ErrorResult::ReportErrorWithMessage(JSContext* aCx)
argCount > 0 ? args : nullptr); argCount > 0 ? args : nullptr);
ClearMessage(); ClearMessage();
mResult = NS_OK;
} }
void void
@ -280,7 +249,7 @@ ErrorResult::ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn)
} }
void void
ErrorResult::ReportJSException(JSContext* cx) ErrorResult::SetPendingJSException(JSContext* cx)
{ {
MOZ_ASSERT(!mMightHaveUnreportedJSException, MOZ_ASSERT(!mMightHaveUnreportedJSException,
"Why didn't you tell us you planned to handle JS exceptions?"); "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. // what, go ahead and unroot mJSException.
js::RemoveRawValueRoot(cx, &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; mResult = NS_OK;
#ifdef DEBUG #ifdef DEBUG
mUnionState = HasNothing; mUnionState = HasNothing;
@ -373,14 +323,16 @@ ErrorResult::ThrowDOMException(nsresult rv, const nsACString& message)
} }
void 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); MOZ_ASSERT(mUnionState == HasDOMExceptionInfo);
dom::Throw(cx, mDOMExceptionInfo->mRv, mDOMExceptionInfo->mMessage); dom::Throw(cx, mDOMExceptionInfo->mRv, mDOMExceptionInfo->mMessage);
ClearDOMExceptionInfo(); ClearDOMExceptionInfo();
mResult = NS_OK;
} }
void void
@ -414,12 +366,13 @@ ErrorResult::ClearUnionData()
} }
void void
ErrorResult::ReportGenericError(JSContext* cx) ErrorResult::SetPendingGenericErrorException(JSContext* cx)
{ {
MOZ_ASSERT(!IsErrorWithMessage()); MOZ_ASSERT(!IsErrorWithMessage());
MOZ_ASSERT(!IsJSException()); MOZ_ASSERT(!IsJSException());
MOZ_ASSERT(!IsDOMException()); MOZ_ASSERT(!IsDOMException());
dom::Throw(cx, ErrorCode()); dom::Throw(cx, ErrorCode());
mResult = NS_OK;
} }
ErrorResult& ErrorResult&
@ -508,6 +461,39 @@ ErrorResult::SuppressException()
mResult = NS_OK; 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 { namespace dom {
bool bool
@ -2777,10 +2763,10 @@ ConvertExceptionToPromise(JSContext* cx,
JS_ClearPendingException(cx); JS_ClearPendingException(cx);
ErrorResult rv; ErrorResult rv;
RefPtr<Promise> promise = Promise::Reject(global, exn, rv); RefPtr<Promise> promise = Promise::Reject(global, exn, rv);
if (rv.Failed()) { if (rv.MaybeSetPendingException(cx)) {
// We just give up. Make sure to not leak memory on the // We just give up. We put the exception from the ErrorResult on
// ErrorResult, but then just put the original exception back. // the JSContext just to make sure to not leak memory on the
ThrowMethodFailed(cx, rv); // ErrorResult, but now just put the original exception back.
JS_SetPendingException(cx, exn); JS_SetPendingException(cx, exn);
return false; return false;
} }

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

@ -92,9 +92,6 @@ ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
const ErrNum aErrorNumber, const ErrNum aErrorNumber,
prototypes::ID aProtoId); prototypes::ID aProtoId);
bool
ThrowMethodFailed(JSContext* cx, ErrorResult& rv);
// Returns true if the JSClass is used for DOM objects. // Returns true if the JSClass is used for DOM objects.
inline bool inline bool
IsDOMClass(const JSClass* clasp) IsDOMClass(const JSClass* clasp)

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

@ -1663,11 +1663,7 @@ class CGClassConstructor(CGAbstractStaticMethod):
JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee()); JS::Rooted<JSObject*> obj(cx, &args.callee());
$*{chromeOnlyCheck} $*{chromeOnlyCheck}
bool mayInvoke = args.isConstructing(); if (!args.isConstructing()) {
#ifdef RELEASE_BUILD
mayInvoke = mayInvoke || nsContentUtils::ThreadsafeIsCallerChrome();
#endif // RELEASE_BUILD
if (!mayInvoke) {
// XXXbz wish I could get the name from the callee instead of // XXXbz wish I could get the name from the callee instead of
// Adding more relocations // Adding more relocations
return ThrowConstructorWithoutNew(cx, "${ctorName}"); return ThrowConstructorWithoutNew(cx, "${ctorName}");
@ -1728,9 +1724,7 @@ class CGConstructNavigatorObject(CGAbstractMethod):
JS::Rooted<JS::Value> v(aCx); JS::Rooted<JS::Value> v(aCx);
{ // Scope to make sure |result| goes out of scope while |v| is rooted { // Scope to make sure |result| goes out of scope while |v| is rooted
RefPtr<mozilla::dom::${descriptorName}> result = ConstructNavigatorObjectHelper(aCx, global, rv); RefPtr<mozilla::dom::${descriptorName}> result = ConstructNavigatorObjectHelper(aCx, global, rv);
rv.WouldReportJSException(); if (rv.MaybeSetPendingException(aCx)) {
if (rv.Failed()) {
ThrowMethodFailed(aCx, rv);
return nullptr; return nullptr;
} }
if (!GetOrCreateDOMReflector(aCx, result, &v)) { if (!GetOrCreateDOMReflector(aCx, result, &v)) {
@ -5101,8 +5095,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
} }
ErrorResult promiseRv; ErrorResult promiseRv;
$${declName} = Promise::Resolve(promiseGlobal, $${val}, promiseRv); $${declName} = Promise::Resolve(promiseGlobal, $${val}, promiseRv);
if (promiseRv.Failed()) { if (promiseRv.MaybeSetPendingException(cx)) {
ThrowMethodFailed(cx, promiseRv);
$*{exceptionCode} $*{exceptionCode}
} }
} }
@ -6274,21 +6267,14 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
resultLoc = result resultLoc = result
conversion = fill( conversion = fill(
""" """
{ if (!ToJSValue(cx, ${result}, $${jsvalHandle})) {
// Scope for resultStr $*{exceptionCode}
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}
} }
$*{successCode}
""", """,
result=resultLoc, result=resultLoc,
strings=(type.unroll().inner.identifier.name + "Values::" +
ENUM_ENTRY_VARIABLE_NAME),
exceptionCode=exceptionCode, exceptionCode=exceptionCode,
setResultStr=setString("resultStr")) successCode=successCode)
if type.nullable(): if type.nullable():
conversion = CGIfElseWrapper( conversion = CGIfElseWrapper(
@ -6664,23 +6650,18 @@ class CGCallGenerator(CGThing):
A class to generate an actual call to a C++ object. Assumes that the C++ 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. 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 isFallible is a boolean indicating whether the call should be fallible.
error reporting is needed.
resultVar: If the returnType is not void, then the result of the call is 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 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 declaring the result variable. If the caller doesn't care about the result
value, resultVar can be omitted. value, resultVar can be omitted.
""" """
def __init__(self, errorReport, arguments, argsPre, returnType, def __init__(self, isFallible, arguments, argsPre, returnType,
extendedAttributes, descriptorProvider, nativeMethodName, extendedAttributes, descriptorProvider, nativeMethodName,
static, object="self", argsPost=[], resultVar=None): static, object="self", argsPost=[], resultVar=None):
CGThing.__init__(self) CGThing.__init__(self)
assert errorReport is None or isinstance(errorReport, CGThing)
isFallible = errorReport is not None
result, resultOutParam, resultRooter, resultArgs, resultConversion = \ result, resultOutParam, resultRooter, resultArgs, resultConversion = \
getRetvalDeclarationForType(returnType, descriptorProvider) getRetvalDeclarationForType(returnType, descriptorProvider)
@ -6775,10 +6756,12 @@ class CGCallGenerator(CGThing):
if isFallible: if isFallible:
self.cgRoot.prepend(CGGeneric("ErrorResult rv;\n")) self.cgRoot.prepend(CGGeneric("ErrorResult rv;\n"))
self.cgRoot.append(CGGeneric("rv.WouldReportJSException();\n")) self.cgRoot.append(CGGeneric(dedent(
self.cgRoot.append(CGGeneric("if (MOZ_UNLIKELY(rv.Failed())) {\n")) """
self.cgRoot.append(CGIndenter(errorReport)) if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
self.cgRoot.append(CGGeneric("}\n")) return false;
}
""")))
self.cgRoot.append(CGGeneric("MOZ_ASSERT(!JS_IsExceptionPending(cx));\n")) self.cgRoot.append(CGGeneric("MOZ_ASSERT(!JS_IsExceptionPending(cx));\n"))
@ -7172,7 +7155,7 @@ class CGPerSignatureCall(CGThing):
idlNode.identifier.name)) idlNode.identifier.name))
else: else:
cgThings.append(CGCallGenerator( cgThings.append(CGCallGenerator(
self.getErrorReport() if self.isFallible() else None, self.isFallible(),
self.getArguments(), argsPre, returnType, self.getArguments(), argsPre, returnType,
self.extendedAttributes, descriptor, nativeMethodName, self.extendedAttributes, descriptor, nativeMethodName,
static, argsPost=argsPost, resultVar=resultVar)) static, argsPost=argsPost, resultVar=resultVar))
@ -7279,9 +7262,6 @@ class CGPerSignatureCall(CGThing):
maybeWrap=getMaybeWrapValueFuncForType(self.idlNode.type)) maybeWrap=getMaybeWrapValueFuncForType(self.idlNode.type))
return wrapCode return wrapCode
def getErrorReport(self):
return CGGeneric('return ThrowMethodFailed(cx, rv);\n')
def define(self): def define(self):
return (self.cgRoot.define() + self.wrap_return_value()) return (self.cgRoot.define() + self.wrap_return_value())
@ -8250,9 +8230,8 @@ class CGEnumerateHook(CGAbstractBindingMethod):
nsAutoTArray<nsString, 8> names; nsAutoTArray<nsString, 8> names;
ErrorResult rv; ErrorResult rv;
self->GetOwnPropertyNames(cx, names, rv); self->GetOwnPropertyNames(cx, names, rv);
rv.WouldReportJSException(); if (rv.MaybeSetPendingException(cx)) {
if (rv.Failed()) { return false;
return ThrowMethodFailed(cx, rv);
} }
bool dummy; bool dummy;
for (uint32_t i = 0; i < names.Length(); ++i) { for (uint32_t i = 0; i < names.Length(); ++i) {
@ -9068,11 +9047,53 @@ def getEnumValueName(value):
' rename our internal EndGuard_ to something else') ' rename our internal EndGuard_ to something else')
return nativeName 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): class CGEnum(CGThing):
def __init__(self, enum): def __init__(self, enum):
CGThing.__init__(self) CGThing.__init__(self)
self.enum = enum 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): def stringsNamespace(self):
return self.enum.identifier.name + "Values" return self.enum.identifier.name + "Values"
@ -9093,22 +9114,10 @@ class CGEnum(CGThing):
strings = CGNamespace(self.stringsNamespace(), strings = CGNamespace(self.stringsNamespace(),
CGGeneric(declare="extern const EnumEntry %s[%d];\n" CGGeneric(declare="extern const EnumEntry %s[%d];\n"
% (ENUM_ENTRY_VARIABLE_NAME, self.nEnumStrings()))) % (ENUM_ENTRY_VARIABLE_NAME, self.nEnumStrings())))
return decl + "\n" + strings.declare() return decl + "\n" + self.cgThings.declare()
def define(self): def define(self):
strings = fill( return self.cgThings.define()
"""
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()
def deps(self): def deps(self):
return self.enum.getDeps() return self.enum.getDeps()
@ -10308,9 +10317,8 @@ class CGEnumerateOwnPropertiesViaGetOwnPropertyNames(CGAbstractBindingMethod):
nsAutoTArray<nsString, 8> names; nsAutoTArray<nsString, 8> names;
ErrorResult rv; ErrorResult rv;
self->GetOwnPropertyNames(cx, names, rv); self->GetOwnPropertyNames(cx, names, rv);
rv.WouldReportJSException(); if (rv.MaybeSetPendingException(cx)) {
if (rv.Failed()) { return false;
return ThrowMethodFailed(cx, rv);
} }
// OK to pass null as "proxy" because it's ignored if // OK to pass null as "proxy" because it's ignored if
// shadowPrototypeProperties is true // shadowPrototypeProperties is true
@ -12172,11 +12180,9 @@ class CGDictionary(CGThing):
if m.canHaveMissingValue(): if m.canHaveMissingValue():
memberAssign = CGGeneric(fill( memberAssign = CGGeneric(fill(
""" """
${name}.Reset();
if (aOther.${name}.WasPassed()) { if (aOther.${name}.WasPassed()) {
${name}.Construct(); ${name}.Construct(aOther.${name}.Value());
${name}.Value() = aOther.${name}.Value();
} else {
${name}.Reset();
} }
""", """,
name=memberName)) name=memberName))
@ -13014,6 +13020,11 @@ class CGBindingRoot(CGThing):
bindingHeaders["mozilla/dom/DOMJSClass.h"] = descriptors bindingHeaders["mozilla/dom/DOMJSClass.h"] = descriptors
bindingHeaders["mozilla/dom/ScriptSettings.h"] = dictionaries # AutoJSAPI bindingHeaders["mozilla/dom/ScriptSettings.h"] = dictionaries # AutoJSAPI
bindingHeaders["xpcpublic.h"] = dictionaries # xpc::UnprivilegedJunkScope 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] # For things that have [UseCounter]
def descriptorRequiresTelemetry(desc): def descriptorRequiresTelemetry(desc):

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

@ -6,6 +6,17 @@
/** /**
* A struct for tracking exceptions that need to be thrown to JS. * 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 #ifndef mozilla_ErrorResult_h
@ -61,14 +72,14 @@ struct StringArrayAppender
} }
template<typename... Ts> 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) { if (aCount == 0) {
MOZ_ASSERT(false, "There should not be more string arguments provided than are required by the ErrNum."); MOZ_ASSERT(false, "There should not be more string arguments provided than are required by the ErrNum.");
return; return;
} }
aArgs.AppendElement(*aFirst); aArgs.AppendElement(aFirst);
Append(aArgs, aCount - 1, aOtherArgs...); Append(aArgs, aCount - 1, Forward<Ts>(aOtherArgs)...);
} }
}; };
@ -87,8 +98,9 @@ public:
#ifdef DEBUG #ifdef DEBUG
~ErrorResult() { ~ErrorResult() {
MOZ_ASSERT_IF(IsErrorWithMessage(), !mMessage); // Consumers should have called one of MaybeSetPendingException
MOZ_ASSERT_IF(IsDOMException(), !mDOMExceptionInfo); // (possibly via ToJSValue), StealNSResult, and SuppressException
MOZ_ASSERT(!Failed());
MOZ_ASSERT(!mMightHaveUnreportedJSException); MOZ_ASSERT(!mMightHaveUnreportedJSException);
MOZ_ASSERT(mUnionState == HasNothing); MOZ_ASSERT(mUnionState == HasNothing);
} }
@ -134,33 +146,71 @@ public:
return rv; return rv;
} }
template<dom::ErrNum errorNumber, typename... Ts> // Use MaybeSetPendingException to convert an ErrorResult to a pending
void ThrowTypeError(Ts... messageArgs) // 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> 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; } bool IsErrorWithMessage() const { return ErrorCode() == NS_ERROR_TYPE_ERR || ErrorCode() == NS_ERROR_RANGE_ERR; }
// Facilities for throwing a preexisting JS exception value via this // Facilities for throwing a preexisting JS exception value via this
// ErrorResult. The contract is that any code which might end up calling // ErrorResult. The contract is that any code which might end up calling
// ThrowJSException() must call MightThrowJSException() even if no exception // ThrowJSException() must call MightThrowJSException() even if no exception
// is being thrown. Code that would call ReportJSException or // is being thrown. Code that conditionally calls ToJSValue on this
// StealJSException as needed must first call WouldReportJSException even if // ErrorResult only if Failed() must first call WouldReportJSException even if
// this ErrorResult has not failed. // this ErrorResult has not failed.
// //
// The exn argument to ThrowJSException can be in any compartment. It does // 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 // 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. // will wrap it into whatever compartment they're working in, as needed.
void ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn); void ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn);
void ReportJSException(JSContext* cx);
bool IsJSException() const { return ErrorCode() == NS_ERROR_DOM_JS_EXCEPTION; } bool IsJSException() const { return ErrorCode() == NS_ERROR_DOM_JS_EXCEPTION; }
// Facilities for throwing a DOMException. If an empty message string is // 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 // passed in must be one we create DOMExceptions for; otherwise you may get an
// XPConnect Exception. // XPConnect Exception.
void ThrowDOMException(nsresult rv, const nsACString& message = EmptyCString()); void ThrowDOMException(nsresult rv, const nsACString& message = EmptyCString());
void ReportDOMException(JSContext* cx);
bool IsDOMException() const { return ErrorCode() == NS_ERROR_DOM_DOMEXCEPTION; } bool IsDOMException() const { return ErrorCode() == NS_ERROR_DOM_DOMEXCEPTION; }
// Flag on the ErrorResult that whatever needs throwing has been // Flag on the ErrorResult that whatever needs throwing has been
@ -183,10 +232,6 @@ public:
return ErrorCode() == NS_ERROR_DOM_EXCEPTION_ON_JSCONTEXT; 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. // Support for uncatchable exceptions.
void ThrowUncatchableException() { void ThrowUncatchableException() {
Throw(NS_ERROR_UNCATCHABLE_EXCEPTION); Throw(NS_ERROR_UNCATCHABLE_EXCEPTION);
@ -195,11 +240,6 @@ public:
return ErrorCode() == NS_ERROR_UNCATCHABLE_EXCEPTION; 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() void MOZ_ALWAYS_INLINE MightThrowJSException()
{ {
#ifdef DEBUG #ifdef DEBUG
@ -264,7 +304,7 @@ private:
nsTArray<nsString>& CreateErrorMessageHelper(const dom::ErrNum errorNumber, nsresult errorType); nsTArray<nsString>& CreateErrorMessageHelper(const dom::ErrNum errorNumber, nsresult errorType);
template<dom::ErrNum errorNumber, typename... Ts> 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__)) #if defined(DEBUG) && (defined(__clang__) || defined(__GNUC__))
static_assert(dom::ErrorFormatNumArgs[errorNumber] == sizeof...(messageArgs), static_assert(dom::ErrorFormatNumArgs[errorNumber] == sizeof...(messageArgs),
@ -275,7 +315,8 @@ private:
nsTArray<nsString>& messageArgsArray = CreateErrorMessageHelper(errorNumber, errorType); nsTArray<nsString>& messageArgsArray = CreateErrorMessageHelper(errorNumber, errorType);
uint16_t argCount = dom::GetErrorArgCount(errorNumber); uint16_t argCount = dom::GetErrorArgCount(errorNumber);
dom::StringArrayAppender::Append(messageArgsArray, argCount, messageArgs...); dom::StringArrayAppender::Append(messageArgsArray, argCount,
Forward<Ts>(messageArgs)...);
#ifdef DEBUG #ifdef DEBUG
mUnionState = HasMessage; mUnionState = HasMessage;
#endif // DEBUG #endif // DEBUG
@ -306,6 +347,17 @@ private:
// anymore. // anymore.
void ClearUnionData(); 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: // Special values of mResult:
// NS_ERROR_TYPE_ERR -- ThrowTypeError() called on us. // NS_ERROR_TYPE_ERR -- ThrowTypeError() called on us.
// NS_ERROR_RANGE_ERR -- ThrowRangeError() called on us. // NS_ERROR_RANGE_ERR -- ThrowRangeError() called on us.
@ -317,11 +369,11 @@ private:
struct Message; struct Message;
struct DOMExceptionInfo; struct DOMExceptionInfo;
// mMessage is set by ThrowErrorWithMessage and reported (and deallocated) by // mMessage is set by ThrowErrorWithMessage and reported (and deallocated) by
// ReportErrorWithMessage. // SetPendingExceptionWithMessage.
// mJSException is set (and rooted) by ThrowJSException and reported // mJSException is set (and rooted) by ThrowJSException and reported
// (and unrooted) by ReportJSException. // (and unrooted) by SetPendingJSException.
// mDOMExceptionInfo is set by ThrowDOMException and reported // mDOMExceptionInfo is set by ThrowDOMException and reported
// (and deallocated) by ReportDOMException. // (and deallocated) by SetPendingDOMException.
union { union {
Message* mMessage; // valid when IsErrorWithMessage() Message* mMessage; // valid when IsErrorWithMessage()
JS::Value mJSException; // valid when IsJSException() JS::Value mJSException; // valid when IsJSException()

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

@ -56,8 +56,8 @@ ToJSValue(JSContext* aCx,
MOZ_ASSERT(!aArgument.IsUncatchableException(), MOZ_ASSERT(!aArgument.IsUncatchableException(),
"Doesn't make sense to convert uncatchable exception to a JS value!"); "Doesn't make sense to convert uncatchable exception to a JS value!");
AutoForceSetExceptionOnContext forceExn(aCx); AutoForceSetExceptionOnContext forceExn(aCx);
DebugOnly<bool> throwResult = ThrowMethodFailed(aCx, aArgument); DebugOnly<bool> throwResult = aArgument.MaybeSetPendingException(aCx);
MOZ_ASSERT(!throwResult); MOZ_ASSERT(throwResult);
DebugOnly<bool> getPendingResult = JS_GetPendingException(aCx, aValue); DebugOnly<bool> getPendingResult = JS_GetPendingException(aCx, aValue);
MOZ_ASSERT(getPendingResult); MOZ_ASSERT(getPendingResult);
JS_ClearPendingException(aCx); JS_ClearPendingException(aCx);

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

@ -19,6 +19,7 @@
#include "mozilla/Services.h" #include "mozilla/Services.h"
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "mozilla/unused.h" #include "mozilla/unused.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h" #include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/dom/ipc/BlobChild.h" #include "mozilla/dom/ipc/BlobChild.h"

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

@ -2037,6 +2037,9 @@ BrowserElementChild.prototype = {
case Cr.NS_ERROR_UNWANTED_URI : case Cr.NS_ERROR_UNWANTED_URI :
sendAsyncMsg('error', { type: 'unwantedBlocked' }); sendAsyncMsg('error', { type: 'unwantedBlocked' });
return; return;
case Cr.NS_ERROR_FORBIDDEN_URI :
sendAsyncMsg('error', { type: 'forbiddenBlocked' });
return;
case Cr.NS_ERROR_OFFLINE : case Cr.NS_ERROR_OFFLINE :
sendAsyncMsg('error', { type: 'offline' }); sendAsyncMsg('error', { type: 'offline' });

6
dom/cache/Cache.cpp поставляемый
Просмотреть файл

@ -46,8 +46,8 @@ IsValidPutRequestURL(const nsAString& aUrl, ErrorResult& aRv)
} }
if (!validScheme) { if (!validScheme) {
NS_NAMED_LITERAL_STRING(label, "Request"); aRv.ThrowTypeError<MSG_INVALID_URL_SCHEME>(NS_LITERAL_STRING("Request"),
aRv.ThrowTypeError<MSG_INVALID_URL_SCHEME>(&label, &aUrl); aUrl);
return false; return false;
} }
@ -61,7 +61,7 @@ IsValidPutRequestMethod(const Request& aRequest, ErrorResult& aRv)
aRequest.GetMethod(method); aRequest.GetMethod(method);
if (!method.LowerCaseEqualsLiteral("get")) { if (!method.LowerCaseEqualsLiteral("get")) {
NS_ConvertASCIItoUTF16 label(method); NS_ConvertASCIItoUTF16 label(method);
aRv.ThrowTypeError<MSG_INVALID_REQUEST_METHOD>(&label); aRv.ThrowTypeError<MSG_INVALID_REQUEST_METHOD>(label);
return false; return false;
} }

4
dom/cache/CacheStorage.cpp поставляемый
Просмотреть файл

@ -261,8 +261,8 @@ CacheStorage::DefineCaches(JSContext* aCx, JS::Handle<JSObject*> aGlobal)
false, /* private browsing */ false, /* private browsing */
true, /* force trusted */ true, /* force trusted */
rv); rv);
if (NS_WARN_IF(rv.Failed())) { if (NS_WARN_IF(rv.MaybeSetPendingException(aCx))) {
return ThrowMethodFailed(aCx, rv); return false;
} }
JS::Rooted<JS::Value> caches(aCx); JS::Rooted<JS::Value> caches(aCx);

121
dom/cache/Context.cpp поставляемый
Просмотреть файл

@ -132,7 +132,7 @@ public:
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable); NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
MOZ_ASSERT(mState == STATE_INIT); MOZ_ASSERT(mState == STATE_INIT);
mState = STATE_OPEN_DIRECTORY; mState = STATE_GET_INFO;
nsresult rv = NS_DispatchToMainThread(this, nsIThread::DISPATCH_NORMAL); nsresult rv = NS_DispatchToMainThread(this, nsIThread::DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
mState = STATE_COMPLETE; mState = STATE_COMPLETE;
@ -149,6 +149,8 @@ public:
mInitAction->CancelOnInitiatingThread(); mInitAction->CancelOnInitiatingThread();
} }
void OpenDirectory();
// OpenDirectoryListener methods // OpenDirectoryListener methods
virtual void virtual void
DirectoryLockAcquired(DirectoryLock* aLock) override; DirectoryLockAcquired(DirectoryLock* aLock) override;
@ -195,6 +197,8 @@ private:
enum State enum State
{ {
STATE_INIT, STATE_INIT,
STATE_GET_INFO,
STATE_CREATE_QUOTA_MANAGER,
STATE_OPEN_DIRECTORY, STATE_OPEN_DIRECTORY,
STATE_WAIT_FOR_DIRECTORY_LOCK, STATE_WAIT_FOR_DIRECTORY_LOCK,
STATE_ENSURE_ORIGIN_INITIALIZED, STATE_ENSURE_ORIGIN_INITIALIZED,
@ -234,7 +238,7 @@ private:
nsCOMPtr<nsIThread> mInitiatingThread; nsCOMPtr<nsIThread> mInitiatingThread;
nsresult mResult; nsresult mResult;
QuotaInfo mQuotaInfo; QuotaInfo mQuotaInfo;
nsMainThreadPtrHandle<DirectoryLock> mDirectoryLock; RefPtr<DirectoryLock> mDirectoryLock;
State mState; State mState;
Atomic<bool> mCanceled; Atomic<bool> mCanceled;
@ -243,14 +247,35 @@ public:
NS_DECL_NSIRUNNABLE 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 void
Context::QuotaInitRunnable::DirectoryLockAcquired(DirectoryLock* aLock) Context::QuotaInitRunnable::DirectoryLockAcquired(DirectoryLock* aLock)
{ {
MOZ_ASSERT(NS_IsMainThread()); NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
MOZ_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK); MOZ_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK);
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLock);
mDirectoryLock = new nsMainThreadPtrHolder<DirectoryLock>(aLock); mDirectoryLock = aLock;
if (mCanceled) { if (mCanceled) {
Complete(NS_ERROR_ABORT); Complete(NS_ERROR_ABORT);
@ -271,7 +296,7 @@ Context::QuotaInitRunnable::DirectoryLockAcquired(DirectoryLock* aLock)
void void
Context::QuotaInitRunnable::DirectoryLockFailed() Context::QuotaInitRunnable::DirectoryLockFailed()
{ {
MOZ_ASSERT(NS_IsMainThread()); NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
MOZ_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK); MOZ_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK);
MOZ_ASSERT(!mDirectoryLock); MOZ_ASSERT(!mDirectoryLock);
@ -290,13 +315,23 @@ NS_IMPL_ISUPPORTS(mozilla::dom::cache::Context::QuotaInitRunnable, nsIRunnable);
// +-------+-------+ | // +-------+-------+ |
// | | // | |
// +----------v-----------+ | // +----------v-----------+ |
// | OpenDirectory | Resolve(error) | // | GetInfo | Resolve(error) |
// | (Main Thread) +-----------------+ // | (Main Thread) +-----------------+
// +----------+-----------+ | // +----------+-----------+ |
// | | // | |
// +----------v-----------+ | // +----------v-----------+ |
// | CreateQuotaManager | Resolve(error) |
// | (Orig Thread) +-----------------+
// +----------+-----------+ |
// | |
// +----------v-----------+ |
// | OpenDirectory | Resolve(error) |
// | (Orig Thread) +-----------------+
// +----------+-----------+ |
// | |
// +----------v-----------+ |
// | WaitForDirectoryLock | Resolve(error) | // | WaitForDirectoryLock | Resolve(error) |
// | (Main Thread) +-----------------+ // | (Orig Thread) +-----------------+
// +----------+-----------+ | // +----------+-----------+ |
// | | // | |
// +----------v------------+ | // +----------v------------+ |
@ -330,43 +365,61 @@ Context::QuotaInitRunnable::Run()
switch(mState) { switch(mState) {
// ----------------------------------- // -----------------------------------
case STATE_OPEN_DIRECTORY: case STATE_GET_INFO:
{ {
MOZ_ASSERT(NS_IsMainThread()); 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()) { if (mCanceled || QuotaManager::IsShuttingDown()) {
resolver->Resolve(NS_ERROR_ABORT); resolver->Resolve(NS_ERROR_ABORT);
break; break;
} }
QuotaManager* qm = QuotaManager::GetOrCreate(); if (QuotaManager::Get()) {
if (!qm) { 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); resolver->Resolve(NS_ERROR_FAILURE);
break; break;
} }
RefPtr<ManagerId> managerId = mManager->GetManagerId(); OpenDirectory();
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);
break; break;
} }
// ---------------------------------- // ----------------------------------
@ -425,7 +478,7 @@ Context::QuotaInitRunnable::Run()
{ {
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable); NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
mInitAction->CompleteOnInitiatingThread(mResult); mInitAction->CompleteOnInitiatingThread(mResult);
mContext->OnQuotaInit(mResult, mQuotaInfo, mDirectoryLock); mContext->OnQuotaInit(mResult, mQuotaInfo, mDirectoryLock.forget());
mState = STATE_COMPLETE; mState = STATE_COMPLETE;
// Explicitly cleanup here as the destructor could fire on any of // Explicitly cleanup here as the destructor could fire on any of
@ -987,7 +1040,7 @@ Context::DispatchAction(Action* aAction, bool aDoomData)
void void
Context::OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo, Context::OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
nsMainThreadPtrHandle<DirectoryLock>& aDirectoryLock) already_AddRefed<DirectoryLock> aDirectoryLock)
{ {
NS_ASSERT_OWNINGTHREAD(Context); NS_ASSERT_OWNINGTHREAD(Context);

5
dom/cache/Context.h поставляемый
Просмотреть файл

@ -190,7 +190,8 @@ private:
void Start(); void Start();
void DispatchAction(Action* aAction, bool aDoomData = false); void DispatchAction(Action* aAction, bool aDoomData = false);
void OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo, void OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
nsMainThreadPtrHandle<DirectoryLock>& aDirectoryLock); already_AddRefed<DirectoryLock> aDirectoryLock);
already_AddRefed<ThreadsafeHandle> already_AddRefed<ThreadsafeHandle>
CreateThreadsafeHandle(); CreateThreadsafeHandle();
@ -221,7 +222,7 @@ private:
// when ThreadsafeHandle::AllowToClose() is called. // when ThreadsafeHandle::AllowToClose() is called.
RefPtr<ThreadsafeHandle> mThreadsafeHandle; RefPtr<ThreadsafeHandle> mThreadsafeHandle;
nsMainThreadPtrHandle<DirectoryLock> mDirectoryLock; RefPtr<DirectoryLock> mDirectoryLock;
RefPtr<Context> mNextContext; RefPtr<Context> mNextContext;
public: public:

208
dom/cache/Manager.cpp поставляемый
Просмотреть файл

@ -242,55 +242,61 @@ public:
} }
static void static void
StartAbortOnMainThread(const nsACString& aOrigin) Abort(const nsACString& aOrigin)
{ {
MOZ_ASSERT(NS_IsMainThread()); mozilla::ipc::AssertIsOnBackgroundThread();
// Lock for sBackgroundThread. if (!sFactory) {
StaticMutexAutoLock lock(sMutex);
if (!sBackgroundThread) {
return; return;
} }
// Guaranteed to succeed because we should get abort only before the MOZ_ASSERT(!sFactory->mManagerList.IsEmpty());
// background thread is destroyed.
nsCOMPtr<nsIRunnable> runnable = new AbortRunnable(aOrigin); {
nsresult rv = sBackgroundThread->Dispatch(runnable, ManagerList::ForwardIterator iter(sFactory->mManagerList);
nsIThread::DISPATCH_NORMAL); while (iter.HasMore()) {
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv)); RefPtr<Manager> manager = iter.GetNext();
if (aOrigin.IsVoid() ||
manager->mManagerId->QuotaOrigin() == aOrigin) {
manager->Abort();
}
}
}
} }
static void static void
StartShutdownAllOnMainThread() ShutdownAll()
{ {
MOZ_ASSERT(NS_IsMainThread()); mozilla::ipc::AssertIsOnBackgroundThread();
// Lock for sFactoryShutdown and sBackgroundThread. if (!sFactory) {
StaticMutexAutoLock lock(sMutex);
sFactoryShutdown = true;
if (!sBackgroundThread) {
return; return;
} }
// Guaranteed to succeed because we should be shutdown before the MOZ_ASSERT(!sFactory->mManagerList.IsEmpty());
// background thread is destroyed.
nsCOMPtr<nsIRunnable> runnable = new ShutdownAllRunnable(); {
nsresult rv = sBackgroundThread->Dispatch(runnable, // Note that we are synchronously calling shutdown code here. If any
nsIThread::DISPATCH_NORMAL); // of the shutdown code synchronously decides to delete the Factory
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv)); // 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 static bool
IsShutdownAllCompleteOnMainThread() IsShutdownAllComplete()
{ {
MOZ_ASSERT(NS_IsMainThread()); mozilla::ipc::AssertIsOnBackgroundThread();
StaticMutexAutoLock lock(sMutex); return !sFactory;
// Infer whether we have shutdown using the sBackgroundThread value. We
// guarantee this is nullptr when sFactory is destroyed.
return sFactoryShutdown && !sBackgroundThread;
} }
private: private:
@ -322,12 +328,6 @@ private:
if (sFactoryShutdown) { if (sFactoryShutdown) {
return NS_ERROR_ILLEGAL_DURING_SHUTDOWN; 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 // We cannot use ClearOnShutdown() here because we're not on the main
@ -359,134 +359,21 @@ private:
return; 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; 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 // Singleton created on demand and deleted when last Manager is cleared
// in Remove(). // in Remove().
// PBackground thread only. // PBackground thread only.
static StaticAutoPtr<Factory> sFactory; static StaticAutoPtr<Factory> sFactory;
// protects following static attributes // protects following static attribute
static StaticMutex sMutex; static StaticMutex sMutex;
// Indicate if shutdown has occurred to block re-creation of sFactory. // Indicate if shutdown has occurred to block re-creation of sFactory.
// Must hold sMutex to access. // Must hold sMutex to access.
static bool sFactoryShutdown; 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. // 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. // When a Manager is destroyed it calls Factory::Remove() to clear itself.
// PBackground thread only. // PBackground thread only.
@ -508,9 +395,6 @@ StaticMutex Manager::Factory::sMutex;
// static // static
bool Manager::Factory::sFactoryShutdown = false; bool Manager::Factory::sFactoryShutdown = false;
// static
StaticRefPtr<nsIThread> Manager::Factory::sBackgroundThread;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Abstract class to help implement the various Actions. The vast majority // Abstract class to help implement the various Actions. The vast majority
@ -1531,13 +1415,13 @@ Manager::Get(ManagerId* aManagerId)
// static // static
void 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()) { if (!NS_ProcessNextEvent()) {
NS_WARNING("Something bad happened!"); NS_WARNING("Something bad happened!");
break; break;
@ -1547,11 +1431,11 @@ Manager::ShutdownAllOnMainThread()
// static // static
void 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 void

6
dom/cache/Manager.h поставляемый
Просмотреть файл

@ -131,11 +131,11 @@ public:
static nsresult GetOrCreate(ManagerId* aManagerId, Manager** aManagerOut); static nsresult GetOrCreate(ManagerId* aManagerId, Manager** aManagerOut);
static already_AddRefed<Manager> Get(ManagerId* aManagerId); static already_AddRefed<Manager> Get(ManagerId* aManagerId);
// Synchronously shutdown from main thread. This spins the event loop. // Synchronously shutdown. This spins the event loop.
static void ShutdownAllOnMainThread(); static void ShutdownAll();
// Cancel actions for given origin or all actions if passed string is null. // 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. // Must be called by Listener objects before they are destroyed.
void RemoveListener(Listener* aListener); void RemoveListener(Listener* aListener);

20
dom/cache/QuotaClient.cpp поставляемый
Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/dom/cache/Manager.h" #include "mozilla/dom/cache/Manager.h"
#include "mozilla/dom/quota/QuotaManager.h" #include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/quota/UsageInfo.h" #include "mozilla/dom/quota/UsageInfo.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "nsIFile.h" #include "nsIFile.h"
#include "nsISimpleEnumerator.h" #include "nsISimpleEnumerator.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
@ -23,6 +24,7 @@ using mozilla::dom::quota::Client;
using mozilla::dom::quota::PersistenceType; using mozilla::dom::quota::PersistenceType;
using mozilla::dom::quota::QuotaManager; using mozilla::dom::quota::QuotaManager;
using mozilla::dom::quota::UsageInfo; using mozilla::dom::quota::UsageInfo;
using mozilla::ipc::AssertIsOnBackgroundThread;
static nsresult static nsresult
GetBodyUsage(nsIFile* aDir, UsageInfo* aUsageInfo) GetBodyUsage(nsIFile* aDir, UsageInfo* aUsageInfo)
@ -175,9 +177,9 @@ public:
virtual void virtual void
AbortOperations(const nsACString& aOrigin) override AbortOperations(const nsACString& aOrigin) override
{ {
MOZ_ASSERT(NS_IsMainThread()); AssertIsOnBackgroundThread();
Manager::AbortOnMainThread(aOrigin); Manager::Abort(aOrigin);
} }
virtual void virtual void
@ -195,22 +197,26 @@ public:
} }
virtual void virtual void
PerformIdleMaintenance() override StartIdleMaintenance() override
{ }
virtual void
StopIdleMaintenance() override
{ } { }
virtual void virtual void
ShutdownWorkThreads() override ShutdownWorkThreads() override
{ {
MOZ_ASSERT(NS_IsMainThread()); AssertIsOnBackgroundThread();
// spins the event loop and synchronously shuts down all Managers // spins the event loop and synchronously shuts down all Managers
Manager::ShutdownAllOnMainThread(); Manager::ShutdownAll();
} }
private: private:
~CacheQuotaClient() ~CacheQuotaClient()
{ {
MOZ_ASSERT(NS_IsMainThread()); AssertIsOnBackgroundThread();
} }
NS_INLINE_DECL_REFCOUNTING(CacheQuotaClient, override) NS_INLINE_DECL_REFCOUNTING(CacheQuotaClient, override)
@ -224,6 +230,8 @@ namespace cache {
already_AddRefed<quota::Client> CreateQuotaClient() already_AddRefed<quota::Client> CreateQuotaClient()
{ {
AssertIsOnBackgroundThread();
RefPtr<CacheQuotaClient> ref = new CacheQuotaClient(); RefPtr<CacheQuotaClient> ref = new CacheQuotaClient();
return ref.forget(); return ref.forget();
} }

4
dom/cache/TypeUtils.cpp поставляемый
Просмотреть файл

@ -162,9 +162,9 @@ TypeUtils::ToCacheRequest(CacheRequest& aOut, InternalRequest* aIn,
if (!schemeValid) { if (!schemeValid) {
if (aSchemeAction == TypeErrorOnInvalidScheme) { if (aSchemeAction == TypeErrorOnInvalidScheme) {
NS_NAMED_LITERAL_STRING(label, "Request");
NS_ConvertUTF8toUTF16 urlUTF16(url); NS_ConvertUTF8toUTF16 urlUTF16(url);
aRv.ThrowTypeError<MSG_INVALID_URL_SCHEME>(&label, &urlUTF16); aRv.ThrowTypeError<MSG_INVALID_URL_SCHEME>(NS_LITERAL_STRING("Request"),
urlUTF16);
return; return;
} }
} }

6
dom/cache/test/mochitest/driver.js поставляемый
Просмотреть файл

@ -35,7 +35,11 @@ function runTests(testFile, order) {
// adapted from dom/indexedDB/test/helpers.js // adapted from dom/indexedDB/test/helpers.js
function clearStorage() { function clearStorage() {
return new Promise(function(resolve, reject) { 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() { function clearStorage() {
return new Promise(function(resolve, reject) { 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() { function storageUsage() {
return new Promise(function(resolve, reject) { 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() { function resetStorage() {
return new Promise(function(resolve, reject) { 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() { function clearStorage() {
return new Promise(function(resolve, reject) { 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() { function storageUsage() {
return new Promise(function(resolve, reject) { 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() { function resetStorage() {
return new Promise(function(resolve, reject) { 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() { function resetStorage() {
return new Promise(function(resolve, reject) { 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() { function clearStorage() {
return new Promise(function(resolve, reject) { 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() { function storageUsage() {
return new Promise(function(resolve, reject) { 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() { function resetStorage() {
return new Promise(function(resolve, reject) { 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 поставляемый
Просмотреть файл

@ -92,22 +92,11 @@ function resetQuotaManager() {
var pref = 'dom.quotaManager.testing'; var pref = 'dom.quotaManager.testing';
prefService.getBranch(null).setBoolPref(pref, true); prefService.getBranch(null).setBoolPref(pref, true);
qm.reset(); var request = qm.reset();
request.callback = resolve;
// disable quota manager testing mode // disable quota manager testing mode
//prefService.getBranch(null).setBoolPref(pref, false); //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); DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
ErrorResult ignored;
switch (aState) { switch (aState) {
case CameraControlListener::kHardwareOpen: case CameraControlListener::kHardwareOpen:
DOM_CAMERA_LOGI("DOM OnHardwareStateChange: open\n"); 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); DOM_CAMERA_LOGT("%s:%d : this=%p, state=%u\n", __func__, __LINE__, this, aState);
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
ErrorResult ignored;
nsString state; nsString state;
switch (aState) { switch (aState) {

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

@ -3967,6 +3967,7 @@ gfxFontGroup *CanvasRenderingContext2D::GetCurrentFontStyle()
nsCOMPtr<nsIPresShell> presShell = GetPresShell(); nsCOMPtr<nsIPresShell> presShell = GetPresShell();
bool fontUpdated = SetFontInternal(kDefaultFontStyle, err); bool fontUpdated = SetFontInternal(kDefaultFontStyle, err);
if (err.Failed() || !fontUpdated) { if (err.Failed() || !fontUpdated) {
err.SuppressException();
gfxFontStyle style; gfxFontStyle style;
style.size = kDefaultFontSize; style.size = kDefaultFontSize;
gfxTextPerfMetrics* tp = nullptr; gfxTextPerfMetrics* tp = nullptr;

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

@ -1,5 +1,5 @@
# WebGL Reftests! # 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: # Check that disabling works:
== webgl-disable-test.html?nogl wrapper.html?green.png == 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 += [ MOCHITEST_MANIFESTS += [
'ipc/mochitest.ini',
'test/mochitest.ini', 'test/mochitest.ini',
] ]
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini'] MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']

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

@ -17,36 +17,18 @@ Object.defineProperty(Array.prototype, "remove", {
} }
}); });
function devicestorage_setup() { function devicestorage_setup(callback) {
// 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) {}
SimpleTest.waitForExplicitFinish(); 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() { let script = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('remove_testing_directory.js'));
if (SpecialPowers.isMainProcess()) {
SpecialPowers.setBoolPref("device.storage.enabled", oldVal); script.addMessageListener('directory-removed', function listener () {
SpecialPowers.setBoolPref("device.storage.testing", false); script.removeMessageListener('directory-removed', listener);
SpecialPowers.setBoolPref("device.storage.prompt.testing", false); var prefs = [["device.storage.enabled", true],
} ["device.storage.testing", true],
SimpleTest.finish(); ["device.storage.prompt.testing", true]];
SpecialPowers.pushPrefEnv({"set": prefs}, callback);
});
} }
function getRandomBuffer() { function getRandomBuffer() {
@ -75,7 +57,7 @@ function randomFilename(l) {
function reportErrorAndQuit(e) { function reportErrorAndQuit(e) {
ok(false, "handleError was called : " + e.target.error.name); ok(false, "handleError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
function createTestFiles(storage, paths) { function createTestFiles(storage, paths) {

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

@ -1,6 +1,7 @@
[DEFAULT] [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 support-files = devicestorage_common.js
remove_testing_directory.js
[test_823965.html] [test_823965.html]
# [test_add.html] # [test_add.html]
@ -9,6 +10,7 @@ support-files = devicestorage_common.js
[test_available.html] [test_available.html]
[test_basic.html] [test_basic.html]
[test_dirs.html] [test_dirs.html]
skip-if = e10s # Bug 1063569.
# [test_diskSpace.html] # [test_diskSpace.html]
# Possible race between the time we write a file, and the # Possible race between the time we write a file, and the
# time it takes to be reflected by statfs(). Bug # 791287 # time it takes to be reflected by statfs(). Bug # 791287

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

@ -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"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup(); devicestorage_setup(function () {
var gFileName = "devicestorage/" + randomFilename(12) + "/hi.png"; var gFileName = "devicestorage/" + randomFilename(12) + "/hi.png";
var gData = "My name is Doug Turner (?!?). My IRC nick is DougT. I like Maple cookies." 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); var dreq = storage2.delete(mreq.result.name);
dreq.onerror = function () { dreq.onerror = function () {
ok(true, "The bug has been fixed"); ok(true, "The bug has been fixed");
devicestorage_cleanup(); SimpleTest.finish();
}; };
dreq.onsuccess = function () { dreq.onsuccess = function () {
ok(false, "The bug has been fixed"); ok(false, "The bug has been fixed");
devicestorage_cleanup(); SimpleTest.finish();
}; };
}; };
@ -56,7 +56,7 @@ function getSuccess(e) {
function getError(e) { function getError(e) {
ok(false, "getError was called : " + e.target.error.name); ok(false, "getError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
function addSuccess(e) { function addSuccess(e) {
@ -85,7 +85,7 @@ function addSuccess(e) {
function addError(e) { function addError(e) {
ok(false, "addError was called : " + e.target.error.name); ok(false, "addError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
ok(navigator.getDeviceStorage, "Should have getDeviceStorage"); ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
@ -99,8 +99,9 @@ ok(request, "Should have a non-null request");
request.onsuccess = addSuccess; request.onsuccess = addSuccess;
request.onerror = addError; request.onerror = addError;
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -24,7 +24,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=786922
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup(); devicestorage_setup(function () {
function add(storage, mime) { function add(storage, mime) {
dump("adding: " + mime + "\n"); dump("adding: " + mime + "\n");
@ -40,7 +40,7 @@ var tests = [
function fail(e) { function fail(e) {
ok(false, "onerror was called"); ok(false, "onerror was called");
devicestorage_cleanup(); SimpleTest.finish();
} }
function next(e) { function next(e) {
@ -51,7 +51,7 @@ function next(e) {
var f = tests.pop(); var f = tests.pop();
if (f == undefined) { if (f == undefined) {
devicestorage_cleanup(); SimpleTest.finish();
return; return;
} }
@ -62,8 +62,9 @@ function next(e) {
next(); next();
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -24,7 +24,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=786922
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup(); devicestorage_setup(function () {
function addNamed(storage, mime, fileExtension) { function addNamed(storage, mime, fileExtension) {
dump("adding: " + mime + " " + fileExtension + "\n"); dump("adding: " + mime + " " + fileExtension + "\n");
@ -45,7 +45,7 @@ function fail(e) {
ok(false, "addSuccess was called"); ok(false, "addSuccess was called");
ok(e.target.error.name == "TypeMismatchError", "Error must be TypeMismatchError"); ok(e.target.error.name == "TypeMismatchError", "Error must be TypeMismatchError");
devicestorage_cleanup(); SimpleTest.finish();
} }
function next(e) { function next(e) {
@ -56,7 +56,7 @@ function next(e) {
var f = tests.pop(); var f = tests.pop();
if (f == undefined) { if (f == undefined) {
devicestorage_cleanup(); SimpleTest.finish();
return; return;
} }
@ -67,8 +67,9 @@ function next(e) {
next(); next();
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -22,16 +22,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=834595
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup(); devicestorage_setup(function () {
function availableSuccess(e) { function availableSuccess(e) {
isnot(e.target.result, null, "result should not be null"); isnot(e.target.result, null, "result should not be null");
devicestorage_cleanup(); SimpleTest.finish();
} }
function availableError(e) { function availableError(e) {
ok(false, "availableError was called"); ok(false, "availableError was called");
devicestorage_cleanup(); SimpleTest.finish();
} }
var storage = navigator.getDeviceStorage("pictures"); var storage = navigator.getDeviceStorage("pictures");
@ -42,6 +42,8 @@ ok(request, "Should have a non-null request");
request.onsuccess = availableSuccess; request.onsuccess = availableSuccess;
request.onerror = availableError; request.onerror = availableError;
});
</script> </script>
</pre> </pre>
</body> </body>

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

@ -22,7 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup(); devicestorage_setup(function() {
var gFileName = "devicestorage/" + randomFilename(12) + "/hi.png"; var gFileName = "devicestorage/" + randomFilename(12) + "/hi.png";
var gData = "My name is Doug Turner. My IRC nick is DougT. I like Maple cookies." 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) { function getAfterDeleteSuccess(e) {
ok(false, "file was deleted not successfully"); ok(false, "file was deleted not successfully");
devicestorage_cleanup(); SimpleTest.finish();
} }
function getAfterDeleteError(e) { function getAfterDeleteError(e) {
ok(true, "file was deleted successfully"); ok(true, "file was deleted successfully");
devicestorage_cleanup(); SimpleTest.finish();
} }
function deleteSuccess(e) { function deleteSuccess(e) {
@ -53,7 +53,7 @@ function deleteSuccess(e) {
function deleteError(e) { function deleteError(e) {
ok(false, "deleteError was called : " + e.target.error.name); ok(false, "deleteError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
function getSuccess(e) { function getSuccess(e) {
@ -88,7 +88,7 @@ function readerCallback(e) {
function getError(e) { function getError(e) {
ok(false, "getError was called : " + e.target.error.name); ok(false, "getError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
function addSuccess(e) { function addSuccess(e) {
@ -119,7 +119,7 @@ function addSuccess(e) {
function addError(e) { function addError(e) {
ok(false, "addError was called : " + e.target.error.name); ok(false, "addError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
ok(navigator.getDeviceStorage, "Should have getDeviceStorage"); ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
@ -133,8 +133,9 @@ ok(request, "Should have a non-null request");
request.onsuccess = addSuccess; request.onsuccess = addSuccess;
request.onerror = addError; request.onerror = addError;
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -22,8 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup(); devicestorage_setup(function () {
var freeBytes = -1; var freeBytes = -1;
var stats = 0; var stats = 0;
@ -39,7 +38,7 @@ function stat(s, file_list_length) {
stats = stats + 1; stats = stats + 1;
if (stats == 2) { if (stats == 2) {
devicestorage_cleanup(); SimpleTest.finish();
} }
} }
@ -60,7 +59,7 @@ function addSuccess(e) {
function addError(e) { function addError(e) {
ok(false, "addError was called : " + e.target.error.name); ok(false, "addError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
ok(true, "hi"); ok(true, "hi");
@ -94,8 +93,9 @@ for (var i=0; i < music_files.length; i++) {
request.onerror = addError; request.onerror = addError;
} }
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -22,7 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup(); devicestorage_setup(function () {
function testingStorage() { function testingStorage() {
return navigator.getDeviceStorage("pictures"); return navigator.getDeviceStorage("pictures");
@ -40,7 +40,7 @@ var gFileName = "../owned.png";
function fail(e) { function fail(e) {
ok(false, "addSuccess was called"); ok(false, "addSuccess was called");
dump(request); dump(request);
devicestorage_cleanup(); SimpleTest.finish();
} }
function next(e) { function next(e) {
@ -53,7 +53,7 @@ function next(e) {
var f = tests.pop(); var f = tests.pop();
if (f == undefined) { if (f == undefined) {
devicestorage_cleanup(); SimpleTest.finish();
return; return;
} }
@ -64,10 +64,9 @@ function next(e) {
next(); next();
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -22,14 +22,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup(); devicestorage_setup(function () {
function enumerateSuccess(e) { function enumerateSuccess(e) {
if (e.target.result == null) { if (e.target.result == null) {
ok(files.length == 0, "when the enumeration is done, we shouldn't have any files in this array") 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("We still have length = " + files.length + "\n");
devicestorage_cleanup(); SimpleTest.finish();
return; return;
} }
@ -61,7 +61,7 @@ function enumerateSuccess(e) {
function handleError(e) { function handleError(e) {
ok(false, "handleError was called : " + e.target.error.name); ok(false, "handleError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
function addSuccess(e) { function addSuccess(e) {
@ -76,7 +76,7 @@ function addSuccess(e) {
function addError(e) { function addError(e) {
ok(false, "addError was called : " + e.target.error.name); ok(false, "addError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
var storage = navigator.getDeviceStorage("pictures"); var storage = navigator.getDeviceStorage("pictures");
@ -96,8 +96,9 @@ for (var i=0; i<files.length; i++) {
request.onerror = addError; request.onerror = addError;
} }
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -22,7 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup(); devicestorage_setup(function () {
function enumerateSuccess(e) { function enumerateSuccess(e) {
} }
@ -39,12 +39,12 @@ try {
} }
catch (e) { catch (e) {
ok(true, "Calling continue before enumerateSuccess fires should throw"); ok(true, "Calling continue before enumerateSuccess fires should throw");
devicestorage_cleanup(); SimpleTest.finish();
} }
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -35,7 +35,7 @@ function enumerateSuccess(e) {
if (e.target.result == null) { if (e.target.result == null) {
ok(files.length == 0, "when the enumeration is done, we shouldn't have any files in this array") ok(files.length == 0, "when the enumeration is done, we shouldn't have any files in this array")
devicestorage_cleanup(); SimpleTest.finish();
return; return;
} }
@ -67,7 +67,7 @@ function enumerateSuccess(e) {
function handleError(e) { function handleError(e) {
ok(false, "handleError was called : " + e.target.error.name); ok(false, "handleError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
function addSuccess(e) { function addSuccess(e) {
@ -82,7 +82,7 @@ function addSuccess(e) {
function addError(e) { function addError(e) {
ok(false, "addError was called : " + e.target.error.name); ok(false, "addError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
var storage = navigator.getDeviceStorage("pictures"); var storage = navigator.getDeviceStorage("pictures");

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

@ -23,7 +23,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup() devicestorage_setup(function () {
storage = navigator.getDeviceStorage("pictures"); storage = navigator.getDeviceStorage("pictures");
@ -70,12 +70,11 @@ var cursor = storage.enumerate({"path": "a", "since": new Date(0) });
} catch(e) {throws = true} } catch(e) {throws = true}
ok(!throws, "enumerate object parameter with path"); ok(!throws, "enumerate object parameter with path");
SimpleTest.finish()
});
devicestorage_cleanup()
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -22,23 +22,23 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup(); devicestorage_setup(function () {
function freeSpaceSuccess(e) { function freeSpaceSuccess(e) {
ok(e.target.result > 0, "free bytes should exist and be greater than zero"); ok(e.target.result > 0, "free bytes should exist and be greater than zero");
devicestorage_cleanup(); SimpleTest.finish();
} }
function freeSpaceError(e) { function freeSpaceError(e) {
ok(false, "freeSpaceError was called"); ok(false, "freeSpaceError was called");
devicestorage_cleanup(); SimpleTest.finish();
} }
var storage = navigator.getDeviceStorage("pictures"); var storage = navigator.getDeviceStorage("pictures");
function addError(e) { function addError(e) {
ok(false, "addError was called : " + e.target.error.name); ok(false, "addError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
function addSuccess(e) { function addSuccess(e) {
@ -54,8 +54,9 @@ request = storage.addNamed(createRandomBlob('image/png'), prefix + "/a/b.png");
request.onsuccess = addSuccess; request.onsuccess = addSuccess;
request.onerror = addError; request.onerror = addError;
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </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 file = new Blob(["This is a text file."], {type: "text/plain"});
var appendFile = new Blob([" Another text file."], {type: "text/plain"}); var appendFile = new Blob([" Another text file."], {type: "text/plain"});
devicestorage_setup(); devicestorage_setup(function () {
function deleteSuccess(e) { function deleteSuccess(e) {
devicestorage_cleanup(); SimpleTest.finish();
} }
function deleteError(e) { function deleteError(e) {
ok(false, "deleteError was called : " + e.target.error.name); ok(false, "deleteError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
function appendSuccess(e) { function appendSuccess(e) {
@ -47,7 +47,7 @@ function appendSuccess(e) {
function appendError(e) { function appendError(e) {
ok(false, "appendError was called."); ok(false, "appendError was called.");
devicestorage_cleanup(); SimpleTest.finish();
} }
function addSuccess(e) { function addSuccess(e) {
@ -83,8 +83,9 @@ ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
ok(gStorage, "Should get storage from sdcard"); ok(gStorage, "Should get storage from sdcard");
runtest(); runtest();
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=910412
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup(); devicestorage_setup(function () {
var gFileName = randomFilename(12); var gFileName = randomFilename(12);
@ -46,12 +46,12 @@ function createDirectorySuccess(d) {
function getSuccess(d) { function getSuccess(d) {
ok(d.name === gFileName, "Should get directory - " + gFileName + "."); ok(d.name === gFileName, "Should get directory - " + gFileName + ".");
devicestorage_cleanup(); SimpleTest.finish();
} }
function cbError(e) { function cbError(e) {
ok(false, "Should not arrive here! Error: " + e.name); ok(false, "Should not arrive here! Error: " + e.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
ok(navigator.getDeviceStorage, "Should have getDeviceStorage"); ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
@ -63,8 +63,10 @@ var promise = storage.getRoot();
ok(promise, "Should have a non-null promise"); ok(promise, "Should have a non-null promise");
promise.then(getRootSuccess, cbError); promise.then(getRootSuccess, cbError);
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=910412
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup(); devicestorage_setup(function () {
// The root directory object. // The root directory object.
var gRoot; var gRoot;
@ -59,7 +59,7 @@ function getSuccess(d) {
// Create directory with an existing path. // Create directory with an existing path.
gRoot.createDirectory(gPath).then(function(what) { gRoot.createDirectory(gPath).then(function(what) {
ok(false, "Should not overwrite an existing directory."); ok(false, "Should not overwrite an existing directory.");
devicestorage_cleanup(); SimpleTest.finish();
}, function(e) { }, function(e) {
ok(true, "Creating directory should fail if it already exists."); ok(true, "Creating directory should fail if it already exists.");
@ -73,10 +73,10 @@ function getSuccess(d) {
// Create the parent directory. // Create the parent directory.
d.createDirectory('..').then(function(what) { d.createDirectory('..').then(function(what) {
ok(false, "Should not overwrite an existing directory."); ok(false, "Should not overwrite an existing directory.");
devicestorage_cleanup(); SimpleTest.finish();
}, function(e) { }, function(e) {
ok(true, "Accessing parent directory with '..' is not allowed."); ok(true, "Accessing parent directory with '..' is not allowed.");
devicestorage_cleanup(); SimpleTest.finish();
}); });
break; break;
} }
@ -85,7 +85,7 @@ function getSuccess(d) {
function cbError(e) { function cbError(e) {
ok(false, e.name + " error should not arrive here!"); ok(false, e.name + " error should not arrive here!");
devicestorage_cleanup(); SimpleTest.finish();
} }
ok(navigator.getDeviceStorage, "Should have getDeviceStorage."); ok(navigator.getDeviceStorage, "Should have getDeviceStorage.");
@ -98,8 +98,10 @@ ok(promise, "Should have a non-null promise for getRoot.");
gName = storage.storageName; gName = storage.storageName;
promise.then(getSuccess, cbError); promise.then(getSuccess, cbError);
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=910412
<pre id="test"> <pre id="test">
<script class="testbody" type="application/javascript;version=1.7"> <script class="testbody" type="application/javascript;version=1.7">
devicestorage_setup(); devicestorage_setup(function () {
let gTestCount = 0; let gTestCount = 0;
let gFileReader = new FileReader(); let gFileReader = new FileReader();
@ -84,7 +84,7 @@ let gTestCases = [
function next() { function next() {
if (gTestCount >= gTestCases.length) { if (gTestCount >= gTestCases.length) {
devicestorage_cleanup(); SimpleTest.finish();
return; return;
} }
let c = gTestCases[gTestCount++]; let c = gTestCases[gTestCount++];
@ -122,11 +122,12 @@ storage.getRoot().then(function(dir) {
next(); next();
}, function(e) { }, function(e) {
ok(false, e.name + " error should not arrive here!"); ok(false, e.name + " error should not arrive here!");
devicestorage_cleanup(); SimpleTest.finish();
});
}); });
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -21,7 +21,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=910412
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup(); devicestorage_setup(function () {
SimpleTest.requestCompleteLog(); SimpleTest.requestCompleteLog();
// The root directory object. // The root directory object.
@ -77,7 +78,7 @@ function getSuccess(r) {
break; break;
default: default:
ok(false, "Should not arrive at getSuccess!"); ok(false, "Should not arrive at getSuccess!");
devicestorage_cleanup(); SimpleTest.finish();
break; break;
} }
gTestCount++; gTestCount++;
@ -137,11 +138,11 @@ function getFailure(e) {
testGetFailure(gRoot, "sub1//sub2"); testGetFailure(gRoot, "sub1//sub2");
break; break;
case 17: case 17:
devicestorage_cleanup(); SimpleTest.finish();
break; break;
default: default:
ok(false, "Should not arrive here!"); ok(false, "Should not arrive here!");
devicestorage_cleanup(); SimpleTest.finish();
break; break;
} }
gTestCount++; gTestCount++;
@ -149,12 +150,12 @@ function getFailure(e) {
function cbError(e) { function cbError(e) {
ok(false, "Should not arrive at cbError! Error: " + e.name); ok(false, "Should not arrive at cbError! Error: " + e.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
function cbSuccess(e) { function cbSuccess(e) {
ok(false, "Should not arrive at cbSuccess!"); ok(false, "Should not arrive at cbSuccess!");
devicestorage_cleanup(); SimpleTest.finish();
} }
ok(navigator.getDeviceStorage, "Should have getDeviceStorage."); ok(navigator.getDeviceStorage, "Should have getDeviceStorage.");
@ -173,7 +174,7 @@ function createTestFile(path, callback) {
req.onerror = function(e) { req.onerror = function(e) {
ok(false, "Failed to create " + path + ": " + e.target.error.name); 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); promise.then(getSuccess, cbError);
}); });
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=XXX
<pre id="test"> <pre id="test">
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
devicestorage_setup(); devicestorage_setup(function () {
SimpleTest.requestCompleteLog(); SimpleTest.requestCompleteLog();
// The root directory object. // The root directory object.
@ -62,12 +62,12 @@ function checkContents1(contents) {
function checkContents2(contents) { function checkContents2(contents) {
is(contents[0].name, "c.png", "'sub2' should contain 'c.png'"); is(contents[0].name, "c.png", "'sub2' should contain 'c.png'");
devicestorage_cleanup(); SimpleTest.finish();
} }
function handleError(e) { function handleError(e) {
ok(false, "Should not arrive at handleError! Error: " + e.name); ok(false, "Should not arrive at handleError! Error: " + e.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
var gStorage = navigator.getDeviceStorage("pictures"); var gStorage = navigator.getDeviceStorage("pictures");
@ -87,11 +87,12 @@ createTestFiles(gStorage, ["sub/a.png", "sub/b.png", "sub/sub2/c.png", "sub/sub3
runTests(); runTests();
}, function() { }, function() {
ok(false, "Failed to created test files."); ok(false, "Failed to created test files.");
devicestorage_cleanup(); SimpleTest.finish();
});
}); });
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=934368
<pre id="test"> <pre id="test">
<script class="testbody" type="application/javascript;version=1.7"> <script class="testbody" type="application/javascript;version=1.7">
devicestorage_setup(); devicestorage_setup(function () {
let gStorage = null; let gStorage = null;
let gTestCount = 0; let gTestCount = 0;
@ -93,7 +93,7 @@ function runNextTests() {
function runTests() { function runTests() {
function cbError(e) { function cbError(e) {
ok(false, "Should not arrive at cbError! Error: " + e.name); ok(false, "Should not arrive at cbError! Error: " + e.name);
devicestorage_cleanup(); SimpleTest.finish();
} }
function cbSuccess(r) { function cbSuccess(r) {
@ -116,7 +116,7 @@ function runNextTests() {
testNextRemove(); testNextRemove();
}, function() { }, function() {
ok(false, "Failed to get test files."); ok(false, "Failed to get test files.");
devicestorage_cleanup(); SimpleTest.finish();
}); });
}, cbError); }, cbError);
}; };
@ -124,7 +124,7 @@ function runNextTests() {
runTests(); runTests();
}, function() { }, function() {
ok(false, "Failed to created test files."); ok(false, "Failed to created test files.");
devicestorage_cleanup(); SimpleTest.finish();
}); });
} }
@ -156,7 +156,7 @@ function testNextRemove() {
return; return;
} }
devicestorage_cleanup(); SimpleTest.finish();
} }
ok(navigator.getDeviceStorage, "Should have getDeviceStorage."); ok(navigator.getDeviceStorage, "Should have getDeviceStorage.");
@ -168,8 +168,9 @@ ok(gStorage, "Should have gotten a storage.");
gRemoveDeep = true; gRemoveDeep = true;
runNextTests(); runNextTests();
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

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

@ -23,7 +23,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
<script class="testbody" type="text/javascript"> <script class="testbody" type="text/javascript">
SimpleTest.requestFlakyTimeout("untriaged"); 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 // 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 // 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 // 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") 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("We still have length = " + files.length + "\n");
dump(files + "\n"); dump(files + "\n");
devicestorage_cleanup(); SimpleTest.finish();
return; return;
} }
@ -86,12 +87,12 @@ function addFile(filename, callback) {
} }
getReq.onerror = function(e) { getReq.onerror = function(e) {
ok(false, "getError was called : " + e.target.error.name); ok(false, "getError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
}; };
} }
addReq.onerror = function(e) { addReq.onerror = function(e) {
ok(false, "addError was called : " + e.target.error.name); 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) { req.onerror = function(e) {
ok(false, "delError was called : " + e.target.error.name); ok(false, "delError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
}; };
} }
@ -129,7 +130,7 @@ function afterNewFiles() {
}; };
cursor.onerror = function (e) { cursor.onerror = function (e) {
ok(false, "handleError was called : " + e.target.error.name); ok(false, "handleError was called : " + e.target.error.name);
devicestorage_cleanup(); SimpleTest.finish();
}; };
} }
@ -167,8 +168,9 @@ function addOldFiles() {
addOldFiles(); addOldFiles();
});
</script> </script>
</pre> </pre>
</body> </body>
</html> </html>

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше