Merge mozilla-central to autoland. a=merge CLOSED TREE

This commit is contained in:
Tiberius Oros 2018-08-17 00:37:19 +03:00
commit 127e89f5dd
476 changed files with 23762 additions and 2358 deletions

View File

@ -90,7 +90,7 @@
<div id="ed_contentEncodingError">&contentEncodingError.longDesc;</div>
<div id="ed_unsafeContentType">&unsafeContentType.longDesc;</div>
<div id="ed_nssFailure2">&nssFailure2.longDesc2;</div>
<div id="ed_nssBadCert">&certerror.introPara1;</div>
<div id="ed_nssBadCert">&certerror.introPara2;</div>
<div id="ed_cspBlocked">&cspBlocked.longDesc;</div>
<div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
<div id="ed_corruptedContentErrorv2">&corruptedContentErrorv2.longDesc;</div>

View File

@ -477,6 +477,7 @@ support-files =
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_e10s_chrome_process.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
skip-if = (os == 'linux' && debug) || (os == 'osx' && debug) # Bug 1444565
[browser_e10s_javascript.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_blockHPKP.js]

View File

@ -244,13 +244,23 @@ function getBaseUriForChromeUri(chromeUri) {
return fileUri.resolve(".");
}
function trackChromeUri(uri) {
gChromeMap.set(getBaseUriForChromeUri(uri), uri);
}
// formautofill registers resource://formautofill/ and
// chrome://formautofill/content/ dynamically at runtime.
// Bug 1480276 is about addressing this without this hard-coding.
trackResourcePrefix("formautofill");
trackChromeUri("chrome://formautofill/content/");
function parseManifest(manifestUri) {
return fetchFile(manifestUri.spec).then(data => {
for (let line of data.split("\n")) {
let [type, ...argv] = line.split(/\s+/);
if (type == "content" || type == "skin" || type == "locale") {
let chromeUri = `chrome://${argv[0]}/${type}/`;
gChromeMap.set(getBaseUriForChromeUri(chromeUri), chromeUri);
trackChromeUri(chromeUri);
} else if (type == "override" || type == "overlay") {
// Overlays aren't really overrides, but behave the same in
// that the overlay is only referenced if the original xul
@ -271,6 +281,35 @@ function parseManifest(manifestUri) {
});
}
// If the given URI is a webextension manifest, extract the scripts
// for any embedded APIs. Returns the passed in URI if the manifest
// is not a webextension manifest, null otherwise.
async function parseJsonManifest(uri) {
let raw = await fetchFile(uri.spec);
let data;
try {
data = JSON.parse(raw);
} catch (ex) {
return uri;
}
// Simplistic test for whether this is a webextension manifest:
if (data.manifest_version !== 2) {
return uri;
}
if (data.experiment_apis) {
for (let api of Object.values(data.experiment_apis)) {
if (api.parent && api.parent.script) {
let script = uri.resolve(api.parent.script);
gReferencesFromCode.set(script, null);
}
}
}
return null;
}
function addCodeReference(url, fromURI) {
let from = convertToCodeURI(fromURI.spec);
@ -546,11 +585,15 @@ add_task(async function checkAllTheFiles() {
// NOTE that this must be done before filtering out devtools paths
// so that all chrome paths can be recorded.
let manifestURIs = [];
let jsonManifests = [];
uris = uris.filter(uri => {
let path = uri.pathQueryRef;
if (path.endsWith(".manifest")) {
manifestURIs.push(uri);
return false;
} else if (path.endsWith("/manifest.json")) {
jsonManifests.push(uri);
return false;
}
return true;
@ -559,6 +602,15 @@ add_task(async function checkAllTheFiles() {
// Wait for all manifest to be parsed
await throttledMapPromises(manifestURIs, parseManifest);
// manifest.json is a common name, it is used for WebExtension manifests
// but also for other things. To tell them apart, we have to actually
// read the contents. This will populate gExtensionRoots with all
// embedded extension APIs, and return any manifest.json files that aren't
// webextensions.
let nonWebextManifests = (await Promise.all(jsonManifests.map(parseJsonManifest)))
.filter(uri => !!uri);
uris.push(...nonWebextManifests);
addActorModules();
// We build a list of promises that get resolved when their respective

View File

@ -14,7 +14,7 @@ let gWhitelist = [{
type: "single-quote"
}, {
file: "netError.dtd",
key: "certerror.introPara1",
key: "certerror.introPara2",
type: "single-quote"
}, {
file: "netError.dtd",

View File

@ -218,6 +218,7 @@ skip-if = os == 'mac' # Save as PDF not supported on Mac OS X
[browser_ext_themes_icons.js]
[browser_ext_themes_validation.js]
[browser_ext_url_overrides_newtab.js]
skip-if = (os == 'linux' && debug) || (os == 'win' && debug) # Bug 1465508
[browser_ext_user_events.js]
[browser_ext_webRequest.js]
[browser_ext_webNavigation_frameId0.js]

View File

@ -2,6 +2,10 @@
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
// There are shutdown issues for which multiple rejections are left uncaught.
// See bug 1018184 for resolving these issues.
PromiseTestUtils.whitelistRejectionsGlobally(/File closed/);
ChromeUtils.defineModuleGetter(this, "BrowserToolboxProcess",
"resource://devtools/client/framework/ToolboxProcess.jsm");
@ -111,6 +115,8 @@ add_task(async function test_addon_debugging_netmonitor_panel() {
// Call a function defined in the target extension to make assertions
// on the network requests collected by the netmonitor panel.
await jsterm.execute(`testNetworkRequestReceived(${JSON.stringify(requests)});`);
await toolbox.destroy();
/* eslint-enable no-undef */
};
@ -119,11 +125,8 @@ add_task(async function test_addon_debugging_netmonitor_panel() {
addonID: EXTENSION_ID,
});
await extension.awaitFinish("netmonitor_request_logged");
let onToolboxClose = browserToolboxProcess.once("close");
await browserToolboxProcess.close();
await extension.awaitFinish("netmonitor_request_logged");
await onToolboxClose;
info("Addon Toolbox closed");

View File

@ -1790,6 +1790,10 @@ FormAutofillStorage.prototype = {
_saveImmediately() {
return this._store._save();
},
_finalize() {
return this._store.finalize();
},
};
// The singleton exposed by this module.

View File

@ -0,0 +1,145 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/* globals ExtensionAPI */
const STYLESHEET_URI = "chrome://formautofill/content/formautofill.css";
const CACHED_STYLESHEETS = new WeakMap();
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.defineModuleGetter(this, "FormAutofill",
"resource://formautofill/FormAutofill.jsm");
ChromeUtils.defineModuleGetter(this, "formAutofillParent",
"resource://formautofill/FormAutofillParent.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "resProto",
"@mozilla.org/network/protocol;1?name=resource",
"nsISubstitutingProtocolHandler");
const RESOURCE_HOST = "formautofill";
function insertStyleSheet(domWindow, url) {
let doc = domWindow.document;
let styleSheetAttr = `href="${url}" type="text/css"`;
let styleSheet = doc.createProcessingInstruction("xml-stylesheet", styleSheetAttr);
doc.insertBefore(styleSheet, doc.documentElement);
if (CACHED_STYLESHEETS.has(domWindow)) {
CACHED_STYLESHEETS.get(domWindow).push(styleSheet);
} else {
CACHED_STYLESHEETS.set(domWindow, [styleSheet]);
}
}
function onMaybeOpenPopup(evt) {
let domWindow = evt.target.ownerGlobal;
if (CACHED_STYLESHEETS.has(domWindow)) {
// This window already has autofill stylesheets.
return;
}
insertStyleSheet(domWindow, STYLESHEET_URI);
}
function isAvailable() {
let availablePref = Services.prefs.getCharPref("extensions.formautofill.available");
if (availablePref == "on") {
return true;
} else if (availablePref == "detect") {
let locale = Services.locale.getRequestedLocale();
let region = Services.prefs.getCharPref("browser.search.region", "");
let supportedCountries = Services.prefs.getCharPref("extensions.formautofill.supportedCountries")
.split(",");
if (!Services.prefs.getBoolPref("extensions.formautofill.supportRTL") &&
Services.locale.isAppLocaleRTL) {
return false;
}
return locale == "en-US" && supportedCountries.includes(region);
}
return false;
}
this.formautofill = class extends ExtensionAPI {
onStartup() {
// We have to do this before actually determining if we're enabled, since
// there are scripts inside of the core browser code that depend on the
// FormAutofill JSMs being registered.
let uri = Services.io.newURI("chrome/res/", null, this.extension.rootURI);
resProto.setSubstitution(RESOURCE_HOST, uri);
let aomStartup = Cc["@mozilla.org/addons/addon-manager-startup;1"]
.getService(Ci.amIAddonManagerStartup);
const manifestURI = Services.io.newURI("manifest.json", null, this.extension.rootURI);
this.chromeHandle = aomStartup.registerChrome(manifestURI, [
["content", "formautofill", "chrome/content/"],
["locale", "formautofill", "en-US", "en-US/locale/en-US/"],
]);
if (!isAvailable()) {
Services.prefs.clearUserPref("dom.forms.autocomplete.formautofill");
// reset the sync related prefs incase the feature was previously available
// but isn't now.
Services.prefs.clearUserPref("services.sync.engine.addresses.available");
Services.prefs.clearUserPref("services.sync.engine.creditcards.available");
Services.telemetry.scalarSet("formautofill.availability", false);
return;
}
// This pref is used for web contents to detect the autocomplete feature.
// When it's true, "element.autocomplete" will return tokens we currently
// support -- otherwise it'll return an empty string.
Services.prefs.setBoolPref("dom.forms.autocomplete.formautofill", true);
Services.telemetry.scalarSet("formautofill.availability", true);
// This pref determines whether the "addresses"/"creditcards" sync engine is
// available (ie, whether it is shown in any UI etc) - it *does not* determine
// whether the engine is actually enabled or not.
Services.prefs.setBoolPref("services.sync.engine.addresses.available", true);
if (FormAutofill.isAutofillCreditCardsAvailable) {
Services.prefs.setBoolPref("services.sync.engine.creditcards.available", true);
} else {
Services.prefs.clearUserPref("services.sync.engine.creditcards.available");
}
// Listen for the autocomplete popup message to lazily append our stylesheet related to the popup.
Services.mm.addMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
formAutofillParent.init().catch(Cu.reportError);
/* eslint-disable no-unused-vars */
Services.ppmm.loadProcessScript("data:,new " + function() {
ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
}, true);
/* eslint-enable no-unused-vars */
Services.mm.loadFrameScript("chrome://formautofill/content/FormAutofillFrameScript.js", true, true);
}
onShutdown() {
resProto.setSubstitution(RESOURCE_HOST, null);
this.chromeHandle.destruct();
this.chromeHandle = null;
Services.mm.removeMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
let enumerator = Services.wm.getEnumerator("navigator:browser");
while (enumerator.hasMoreElements()) {
let win = enumerator.getNext();
let domWindow = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
let cachedStyleSheets = CACHED_STYLESHEETS.get(domWindow);
if (!cachedStyleSheets) {
continue;
}
while (cachedStyleSheets.length !== 0) {
cachedStyleSheets.pop().remove();
}
}
}
};

View File

@ -0,0 +1,8 @@
/* eslint-env webextensions */
"use strict";
browser.runtime.onUpdateAvailable.addListener(details => {
// By listening to but ignoring this event, any updates will
// be delayed until the next browser restart.
});

View File

@ -1,159 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/* exported startup, shutdown, install, uninstall */
const STYLESHEET_URI = "chrome://formautofill/content/formautofill.css";
const CACHED_STYLESHEETS = new WeakMap();
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.defineModuleGetter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm");
ChromeUtils.defineModuleGetter(this, "AddonManagerPrivate",
"resource://gre/modules/AddonManager.jsm");
ChromeUtils.defineModuleGetter(this, "FormAutofill",
"resource://formautofill/FormAutofill.jsm");
ChromeUtils.defineModuleGetter(this, "formAutofillParent",
"resource://formautofill/FormAutofillParent.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "resProto",
"@mozilla.org/network/protocol;1?name=resource",
"nsISubstitutingProtocolHandler");
const RESOURCE_HOST = "formautofill";
function insertStyleSheet(domWindow, url) {
let doc = domWindow.document;
let styleSheetAttr = `href="${url}" type="text/css"`;
let styleSheet = doc.createProcessingInstruction("xml-stylesheet", styleSheetAttr);
doc.insertBefore(styleSheet, doc.documentElement);
if (CACHED_STYLESHEETS.has(domWindow)) {
CACHED_STYLESHEETS.get(domWindow).push(styleSheet);
} else {
CACHED_STYLESHEETS.set(domWindow, [styleSheet]);
}
}
function onMaybeOpenPopup(evt) {
let domWindow = evt.target.ownerGlobal;
if (CACHED_STYLESHEETS.has(domWindow)) {
// This window already has autofill stylesheets.
return;
}
insertStyleSheet(domWindow, STYLESHEET_URI);
}
function addUpgradeListener(instanceID) {
AddonManager.addUpgradeListener(instanceID, upgrade => {
// don't install the upgrade by doing nothing here.
// The upgrade will be installed upon next restart.
});
}
function isAvailable() {
let availablePref = Services.prefs.getCharPref("extensions.formautofill.available");
if (availablePref == "on") {
return true;
} else if (availablePref == "detect") {
let locale = Services.locale.getRequestedLocale();
let region = Services.prefs.getCharPref("browser.search.region", "");
let supportedCountries = Services.prefs.getCharPref("extensions.formautofill.supportedCountries")
.split(",");
if (!Services.prefs.getBoolPref("extensions.formautofill.supportRTL") &&
Services.locale.isAppLocaleRTL) {
return false;
}
return locale == "en-US" && supportedCountries.includes(region);
}
return false;
}
function startup(data) {
// We have to do this before actually determining if we're enabled, since
// there are scripts inside of the core browser code that depend on the
// FormAutofill JSMs being registered.
resProto.setSubstitution(RESOURCE_HOST,
Services.io.newURI("chrome/res/", null, data.resourceURI));
if (!isAvailable()) {
Services.prefs.clearUserPref("dom.forms.autocomplete.formautofill");
// reset the sync related prefs incase the feature was previously available
// but isn't now.
Services.prefs.clearUserPref("services.sync.engine.addresses.available");
Services.prefs.clearUserPref("services.sync.engine.creditcards.available");
Services.telemetry.scalarSet("formautofill.availability", false);
return;
}
if (data.hasOwnProperty("instanceID") && data.instanceID) {
if (AddonManagerPrivate.isDBLoaded()) {
addUpgradeListener(data.instanceID);
} else {
// Wait for the extension database to be loaded so we don't cause its init.
Services.obs.addObserver(function xpiDatabaseLoaded() {
Services.obs.removeObserver(xpiDatabaseLoaded, "xpi-database-loaded");
addUpgradeListener(data.instanceID);
}, "xpi-database-loaded");
}
} else {
throw Error("no instanceID passed to bootstrap startup");
}
// This pref is used for web contents to detect the autocomplete feature.
// When it's true, "element.autocomplete" will return tokens we currently
// support -- otherwise it'll return an empty string.
Services.prefs.setBoolPref("dom.forms.autocomplete.formautofill", true);
Services.telemetry.scalarSet("formautofill.availability", true);
// This pref determines whether the "addresses"/"creditcards" sync engine is
// available (ie, whether it is shown in any UI etc) - it *does not* determine
// whether the engine is actually enabled or not.
Services.prefs.setBoolPref("services.sync.engine.addresses.available", true);
if (FormAutofill.isAutofillCreditCardsAvailable) {
Services.prefs.setBoolPref("services.sync.engine.creditcards.available", true);
} else {
Services.prefs.clearUserPref("services.sync.engine.creditcards.available");
}
// Listen for the autocomplete popup message to lazily append our stylesheet related to the popup.
Services.mm.addMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
formAutofillParent.init().catch(Cu.reportError);
/* eslint-disable no-unused-vars */
Services.ppmm.loadProcessScript("data:,new " + function() {
ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
}, true);
/* eslint-enable no-unused-vars */
Services.mm.loadFrameScript("chrome://formautofill/content/FormAutofillFrameScript.js", true, true);
}
function shutdown() {
resProto.setSubstitution(RESOURCE_HOST, null);
Services.mm.removeMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
let enumerator = Services.wm.getEnumerator("navigator:browser");
while (enumerator.hasMoreElements()) {
let win = enumerator.getNext();
let domWindow = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
let cachedStyleSheets = CACHED_STYLESHEETS.get(domWindow);
if (!cachedStyleSheets) {
continue;
}
while (cachedStyleSheets.length !== 0) {
cachedStyleSheets.pop().remove();
}
}
}
function install() {}
function uninstall() {}

View File

@ -9,9 +9,9 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title data-localization="addNewAddressTitle"/>
<link rel="stylesheet" href="chrome://formautofill-shared/skin/editDialog.css"/>
<link rel="stylesheet" href="chrome://formautofill-shared/skin/editAddress.css"/>
<link rel="stylesheet" href="chrome://formautofill/skin/editDialog.css"/>
<link rel="stylesheet" href="resource://formautofill/editDialog-shared.css"/>
<link rel="stylesheet" href="resource://formautofill/editAddress.css"/>
<link rel="stylesheet" href="resource://formautofill/editDialog.css"/>
<script src="chrome://formautofill/content/l10n.js"></script>
<script src="chrome://formautofill/content/editDialog.js"></script>
<script src="chrome://formautofill/content/autofillEditForms.js"></script>

View File

@ -9,9 +9,9 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title data-localization="addNewCreditCardTitle"/>
<link rel="stylesheet" href="chrome://formautofill-shared/skin/editDialog.css"/>
<link rel="stylesheet" href="chrome://formautofill-shared/skin/editCreditCard.css"/>
<link rel="stylesheet" href="chrome://formautofill/skin/editDialog.css"/>
<link rel="stylesheet" href="resource://formautofill/editDialog-shared.css"/>
<link rel="stylesheet" href="resource://formautofill/editCreditCard.css"/>
<link rel="stylesheet" href="resource://formautofill/editDialog.css"/>
<script src="chrome://formautofill/content/l10n.js"></script>
<script src="chrome://formautofill/content/editDialog.js"></script>
<script src="chrome://formautofill/content/autofillEditForms.js"></script>

View File

@ -1,32 +0,0 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
#filter substitution
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>formautofill@mozilla.org</em:id>
<em:version>1.0</em:version>
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<em:multiprocessCompatible>true</em:multiprocessCompatible>
<!-- Target Application this extension can install into,
with minimum and maximum supported versions. -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>@MOZ_APP_VERSION@</em:minVersion>
<em:maxVersion>@MOZ_APP_MAXVERSION@</em:maxVersion>
</Description>
</em:targetApplication>
<!-- Front End MetaData -->
<em:name>Form Autofill</em:name>
<em:description>Autofill forms with saved profiles</em:description>
</Description>
</RDF>

View File

@ -3,16 +3,9 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
[features/formautofill@mozilla.org] chrome.jar:
% resource formautofill %res/
res/ (*.jsm)
res/phonenumberutils/ (phonenumberutils/*.jsm)
res/addressmetadata/ (addressmetadata/*)
res/ (skin/shared/*)
% content formautofill %content/
content/ (content/*)
% skin formautofill classic/1.0 %skin/linux/ os=LikeUnix
% skin formautofill classic/1.0 %skin/osx/ os=Darwin
% skin formautofill classic/1.0 %skin/windows/ os=WINNT
% skin formautofill-shared classic/1.0 %skin/shared/
skin/ (skin/*)

View File

@ -0,0 +1,26 @@
{
"manifest_version": 2,
"name": "Form Autofill",
"version": "1.0",
"applications": {
"gecko": {
"id": "formautofill@mozilla.org"
}
},
"background": {
"scripts": ["background.js"]
},
"experiment_apis": {
"formautofill": {
"schema": "schema.json",
"parent": {
"scopes": ["addon_parent"],
"script": "api.js",
"events": ["startup"]
}
}
}
}

View File

@ -10,12 +10,27 @@ DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION']
DIRS += ['locales']
FINAL_TARGET_FILES.features['formautofill@mozilla.org'] += [
'bootstrap.js'
'api.js',
'background.js',
'manifest.json',
'schema.json',
]
FINAL_TARGET_PP_FILES.features['formautofill@mozilla.org'] += [
'install.rdf.in'
]
if CONFIG['OS_ARCH'] == 'Linux':
FINAL_TARGET_FILES.features['formautofill@mozilla.org'].chrome.res += [
'skin/linux/autocomplete-item.css',
'skin/linux/editDialog.css',
]
elif CONFIG['OS_ARCH'] == 'Darwin':
FINAL_TARGET_FILES.features['formautofill@mozilla.org'].chrome.res += [
'skin/osx/autocomplete-item.css',
'skin/osx/editDialog.css',
]
elif CONFIG['OS_ARCH'] == 'WINNT':
FINAL_TARGET_FILES.features['formautofill@mozilla.org'].chrome.res += [
'skin/windows/autocomplete-item.css',
'skin/windows/editDialog.css',
]
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']

View File

@ -0,0 +1 @@
[]

View File

@ -8,6 +8,9 @@ ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/ObjectUtils.jsm");
ChromeUtils.import("resource://gre/modules/FormLikeFactory.jsm");
ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
ChromeUtils.import("resource://testing-common/AddonTestUtils.jsm");
ChromeUtils.import("resource://testing-common/ExtensionXPCShellUtils.jsm");
ChromeUtils.import("resource://testing-common/FileTestUtils.jsm");
ChromeUtils.import("resource://testing-common/MockDocument.jsm");
ChromeUtils.import("resource://testing-common/TestUtils.jsm");
@ -17,9 +20,8 @@ ChromeUtils.defineModuleGetter(this, "DownloadPaths",
ChromeUtils.defineModuleGetter(this, "FileUtils",
"resource://gre/modules/FileUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "resProto",
"@mozilla.org/network/protocol;1?name=resource",
"nsISubstitutingProtocolHandler");
ChromeUtils.defineModuleGetter(this, "ExtensionParent",
"resource://gre/modules/ExtensionParent.jsm");
do_get_profile();
@ -31,26 +33,38 @@ Services.scriptloader.loadSubScript("resource://testing-common/sinon-2.3.2.js",
/* globals sinon */
// ================================================
// Load our bootstrap extension manifest so we can access our chrome/resource URIs.
const EXTENSION_ID = "formautofill@mozilla.org";
let extensionDir = Services.dirsvc.get("GreD", Ci.nsIFile);
extensionDir.append("browser");
extensionDir.append("features");
extensionDir.append(EXTENSION_ID);
let bootstrapFile = extensionDir.clone();
bootstrapFile.append("bootstrap.js");
let bootstrapURI = Services.io.newFileURI(bootstrapFile).spec;
// If the unpacked extension doesn't exist, use the packed version.
if (!extensionDir.exists()) {
extensionDir = extensionDir.parent;
extensionDir.append(EXTENSION_ID + ".xpi");
let jarURI = Services.io.newFileURI(extensionDir);
bootstrapURI = "jar:" + jarURI.spec + "!/bootstrap.js";
}
Components.manager.addBootstrappedManifestLocation(extensionDir);
let resURI = Services.io.newURI("chrome/res/", null, Services.io.newURI(bootstrapURI));
resProto.setSubstitution("formautofill", resURI);
AddonTestUtils.init(this);
async function loadExtension() {
AddonTestUtils.createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
await AddonTestUtils.promiseStartupManager();
let extensionPath = Services.dirsvc.get("GreD", Ci.nsIFile);
extensionPath.append("browser");
extensionPath.append("features");
extensionPath.append(EXTENSION_ID);
if (!extensionPath.exists()) {
extensionPath.leafName = `${EXTENSION_ID}.xpi`;
}
let startupPromise = new Promise(resolve => {
const {apiManager} = ExtensionParent;
function onReady(event, extension) {
if (extension.id == EXTENSION_ID) {
apiManager.off("ready", onReady);
resolve();
}
}
apiManager.on("ready", onReady);
});
await AddonManager.installTemporaryAddon(extensionPath);
await startupPromise;
}
// Returns a reference to a temporary file that is guaranteed not to exist and
// is cleaned up later. See FileTestUtils.getTempFile for details.
@ -64,6 +78,15 @@ async function initProfileStorage(fileName, records, collectionName = "addresses
let profileStorage = new FormAutofillStorage(path);
await profileStorage.initialize();
// AddonTestUtils inserts its own directory provider that manages TmpD.
// It removes that directory at shutdown, which races with shutdown
// handing in JSONFile/DeferredTask (which is used by FormAutofillStorage).
// Avoid the race by explicitly finalizing any formautofill JSONFile
// instances created manually by individual tests when the test finishes.
registerCleanupFunction(function finalizeAutofillStorage() {
return profileStorage._finalize();
});
if (!records || !Array.isArray(records)) {
return profileStorage;
}
@ -99,9 +122,11 @@ function verifySectionFieldDetails(sections, expectedResults) {
});
}
function runHeuristicsTest(patterns, fixturePathPrefix) {
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
async function runHeuristicsTest(patterns, fixturePathPrefix) {
add_task(async function setup() {
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
});
patterns.forEach(testPattern => {
add_task(async function() {
@ -194,4 +219,6 @@ add_task(async function head_initialize() {
Services.prefs.clearUserPref("extensions.formautofill.section.enabled");
Services.prefs.clearUserPref("dom.forms.autocomplete.formautofill");
});
await loadExtension();
});

View File

@ -4,7 +4,11 @@
"use strict";
let {FormAutofillParent} = ChromeUtils.import("resource://formautofill/FormAutofillParent.jsm", {});
let FormAutofillParent;
add_task(async function setup() {
({FormAutofillParent} = ChromeUtils.import("resource://formautofill/FormAutofillParent.jsm", {}));
});
add_task(async function test_activeStatus_init() {
let formAutofillParent = new FormAutofillParent();

View File

@ -1,7 +1,5 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
const SUPPORT_COUNTRIES_TESTCASES = [
{
country: "US",
@ -17,6 +15,10 @@ const SUPPORT_COUNTRIES_TESTCASES = [
},
];
add_task(async function setup() {
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
});
add_task(async function test_initalState() {
// addressData should not exist
Assert.equal(AddressDataLoader._addressData, undefined);

View File

@ -5,8 +5,11 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
let {MasterPassword} = ChromeUtils.import("resource://formautofill/MasterPassword.jsm", {});
let MasterPassword;
add_task(async function setup() {
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
({MasterPassword} = ChromeUtils.import("resource://formautofill/MasterPassword.jsm", {}));
});
const TESTCASES = [
{

View File

@ -4,7 +4,9 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
add_task(async function setup() {
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
});
const TESTCASES = [
{

View File

@ -4,7 +4,9 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
add_task(async function seutp() {
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
});
const TESTCASES = [
{

View File

@ -4,11 +4,15 @@
"use strict";
const {FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {});
ChromeUtils.defineModuleGetter(this, "Preferences",
"resource://gre/modules/Preferences.jsm");
ChromeUtils.import("resource://gre/modules/CreditCard.jsm");
let FormAutofillStorage;
add_task(async function setup() {
({FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {}));
});
const TEST_STORE_FILE_NAME = "test-credit-card.json";
const COLLECTION_NAME = "creditCards";

View File

@ -1,6 +1,8 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
add_task(async function() {
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
});
const TESTCASES = [
{

View File

@ -1,6 +1,8 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
add_task(async function() {
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
});
const TESTCASES = [
{

View File

@ -4,7 +4,9 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
add_task(async function() {
ChromeUtils.import("resource://formautofill/FormAutofillHandler.jsm");
});
const DEFAULT_ADDRESS_RECORD = {
"guid": "123",

View File

@ -1,7 +1,9 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
add_task(async function() {
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
});
add_task(async function test_isAddressField_isCreditCardField() {
const TEST_CASES = {

View File

@ -1,6 +1,8 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
add_task(async function() {
ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
});
const TESTCASES = [
{

View File

@ -1,6 +1,8 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
add_task(async function() {
ChromeUtils.import("resource://formautofill/FormAutofillHeuristics.jsm");
});
const TESTCASES = [
{

View File

@ -4,10 +4,14 @@
"use strict";
let {FormAutofillParent} = ChromeUtils.import("resource://formautofill/FormAutofillParent.jsm", {});
ChromeUtils.import("resource://formautofill/MasterPassword.jsm");
ChromeUtils.import("resource://gre/modules/CreditCard.jsm");
let FormAutofillParent;
add_task(async function setup() {
({FormAutofillParent} = ChromeUtils.import("resource://formautofill/FormAutofillParent.jsm", {}));
ChromeUtils.import("resource://formautofill/MasterPassword.jsm");
});
const TEST_ADDRESS_1 = {
"given-name": "Timothy",
"additional-name": "John",

View File

@ -4,13 +4,10 @@
"use strict";
// Load bootstrap.js into a sandbox to be able to test `isAvailable`
let sandbox = {};
Services.scriptloader.loadSubScript(bootstrapURI, sandbox, "utf-8");
info("bootstrapURI: " + bootstrapURI);
const DOM_ENABLED_PREF = "dom.forms.autocomplete.formautofill";
add_task(async function test_defaultTestEnvironment() {
Assert.ok(sandbox.isAvailable());
Assert.ok(Services.prefs.getBoolPref(DOM_ENABLED_PREF));
});
add_task(async function test_unsupportedRegion() {
@ -19,7 +16,11 @@ add_task(async function test_unsupportedRegion() {
registerCleanupFunction(function cleanupRegion() {
Services.prefs.clearUserPref("browser.search.region");
});
Assert.ok(!sandbox.isAvailable());
let addon = await AddonManager.getAddonByID(EXTENSION_ID);
await addon.reload();
Assert.ok(!Services.prefs.getBoolPref(DOM_ENABLED_PREF));
});
add_task(async function test_supportedRegion() {
@ -28,5 +29,9 @@ add_task(async function test_supportedRegion() {
registerCleanupFunction(function cleanupRegion() {
Services.prefs.clearUserPref("browser.search.region");
});
Assert.ok(sandbox.isAvailable());
let addon = await AddonManager.getAddonByID(EXTENSION_ID);
await addon.reload();
Assert.ok(Services.prefs.getBoolPref(DOM_ENABLED_PREF));
});

View File

@ -4,7 +4,9 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillNameUtils.jsm");
add_task(async function setup() {
ChromeUtils.import("resource://formautofill/FormAutofillNameUtils.jsm");
});
// Test cases is initially copied from
// https://cs.chromium.org/chromium/src/components/autofill/core/browser/autofill_data_util_unittest.cc

View File

@ -1,6 +1,8 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
add_task(async function seutp() {
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
});
const TESTCASES = [
{

View File

@ -1,7 +1,5 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
const TESTCASES = [
{
description: "Form containing 8 fields with autocomplete attribute.",
@ -61,9 +59,14 @@ const TESTCASES = [
];
let markedFieldId = [];
FormAutofillContent._markAsAutofillField = function(field) {
markedFieldId.push(field.id);
};
add_task(async function setup() {
ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
FormAutofillContent._markAsAutofillField = function(field) {
markedFieldId.push(field.id);
};
});
TESTCASES.forEach(testcase => {
add_task(async function() {

View File

@ -5,7 +5,11 @@
"use strict";
const {MockRegistrar} =
ChromeUtils.import("resource://testing-common/MockRegistrar.jsm", {});
let {MasterPassword} = ChromeUtils.import("resource://formautofill/MasterPassword.jsm", {});
let MasterPassword;
add_task(async function setup() {
({MasterPassword} = ChromeUtils.import("resource://formautofill/MasterPassword.jsm", {}));
});
const TESTCASES = [{
description: "With master password set",
@ -67,10 +71,10 @@ registerCleanupFunction(() => {
});
TESTCASES.forEach(testcase => {
let token = MasterPassword._token;
add_task(async function test_encrypt_decrypt() {
info("Starting testcase: " + testcase.description);
let token = MasterPassword._token;
token.initPassword(testcase.masterPassword);
// Test only: Force the token login without asking for master password

View File

@ -4,7 +4,11 @@
"use strict";
const {FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {});
let FormAutofillStorage;
add_task(async function setup() {
({FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {}));
});
const TEST_STORE_FILE_NAME = "test-profile.json";

View File

@ -4,7 +4,9 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillNameUtils.jsm");
add_task(async function() {
ChromeUtils.import("resource://formautofill/FormAutofillNameUtils.jsm");
});
// Test cases initially copied from
// https://cs.chromium.org/chromium/src/components/autofill/core/browser/autofill_data_util_unittest.cc

View File

@ -1,6 +1,8 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
add_task(async function setup() {
ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
});
const MOCK_DOC = MockDocument.createTestDocument("http://localhost:8080/test/",
`<form id="form1">

View File

@ -1,6 +1,8 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
add_task(async function setup() {
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
});
add_task(async function test_parseAddressFormat() {
const TEST_CASES = [

View File

@ -4,8 +4,10 @@
"use strict";
ChromeUtils.import("resource://formautofill/phonenumberutils/PhoneNumber.jsm");
ChromeUtils.import("resource://formautofill/phonenumberutils/PhoneNumberNormalizer.jsm");
add_task(async function setup() {
ChromeUtils.import("resource://formautofill/phonenumberutils/PhoneNumber.jsm");
ChromeUtils.import("resource://formautofill/phonenumberutils/PhoneNumberNormalizer.jsm");
});
function IsPlain(dial, expected) {
let result = PhoneNumber.IsPlain(dial);

View File

@ -1,8 +1,10 @@
"use strict";
/* global AddressResult, CreditCardResult */
// eslint-disable-next-line no-unused-vars
ChromeUtils.import("resource://formautofill/ProfileAutoCompleteResult.jsm");
add_task(async function setup() {
// eslint-disable-next-line no-unused-vars
ChromeUtils.import("resource://formautofill/ProfileAutoCompleteResult.jsm");
});
let matchingProfiles = [{
guid: "test-guid-1",
@ -341,15 +343,15 @@ let creditCardTestCases = [{
},
}];
let testSets = [{
collectionConstructor: AddressResult,
testCases: addressTestCases,
}, {
collectionConstructor: CreditCardResult,
testCases: creditCardTestCases,
}];
add_task(async function test_all_patterns() {
let testSets = [{
collectionConstructor: AddressResult,
testCases: addressTestCases,
}, {
collectionConstructor: CreditCardResult,
testCases: creditCardTestCases,
}];
testSets.forEach(({collectionConstructor, testCases}) => {
testCases.forEach(testCase => {
info("Starting testcase: " + testCase.description);

View File

@ -4,7 +4,11 @@
"use strict";
let {FormAutofillParent} = ChromeUtils.import("resource://formautofill/FormAutofillParent.jsm", {});
let FormAutofillParent;
add_task(async function setup() {
({FormAutofillParent} = ChromeUtils.import("resource://formautofill/FormAutofillParent.jsm", {}));
});
add_task(async function test_profileSavedFieldNames_init() {
let formAutofillParent = new FormAutofillParent();

View File

@ -4,7 +4,10 @@
"use strict";
const {FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {});
let FormAutofillStorage;
add_task(async function setup() {
({FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {}));
});
const TEST_STORE_FILE_NAME = "test-tombstones.json";

View File

@ -4,7 +4,10 @@
"use strict";
const {FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {});
let FormAutofillStorage;
add_task(async function setup() {
({FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {}));
});
const TEST_STORE_FILE_NAME = "test-tombstones.json";

View File

@ -13,8 +13,11 @@ ChromeUtils.import("resource://services-sync/service.js");
ChromeUtils.import("resource://services-sync/constants.js");
ChromeUtils.import("resource://testing-common/services/sync/utils.js");
let {sanitizeStorageObject, AutofillRecord, AddressesEngine} =
ChromeUtils.import("resource://formautofill/FormAutofillSync.jsm", {});
let sanitizeStorageObject, AutofillRecord, AddressesEngine;
add_task(async function() {
({sanitizeStorageObject, AutofillRecord, AddressesEngine} =
ChromeUtils.import("resource://formautofill/FormAutofillSync.jsm", {}));
});
Services.prefs.setCharPref("extensions.formautofill.loglevel", "Trace");

View File

@ -1,7 +1,9 @@
"use strict";
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
add_task(async function setup() {
ChromeUtils.import("resource://formautofill/FormAutofillUtils.jsm");
});
add_task(async function test_getCategoriesFromFieldNames() {
const TEST_CASES = [

View File

@ -4,7 +4,10 @@
"use strict";
const {FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {});
let FormAutofillStorage;
add_task(async function setup() {
({FormAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {}));
});
const TEST_STORE_FILE_NAME = "test-profile.json";
@ -901,6 +904,8 @@ add_task(async function test_computeAddressFields() {
profileStorage.addresses.remove(guid);
});
await profileStorage._finalize();
});
add_task(async function test_normalizeAddressFields() {
@ -918,6 +923,8 @@ add_task(async function test_normalizeAddressFields() {
profileStorage.addresses.remove(guid);
});
await profileStorage._finalize();
});
add_task(async function test_computeCreditCardFields() {
@ -935,6 +942,8 @@ add_task(async function test_computeCreditCardFields() {
profileStorage.creditCards.remove(guid);
});
await profileStorage._finalize();
});
add_task(async function test_normalizeCreditCardFields() {
@ -952,4 +961,6 @@ add_task(async function test_normalizeCreditCardFields() {
profileStorage.creditCards.remove(guid);
});
await profileStorage._finalize();
});

View File

@ -150,11 +150,11 @@
<!ENTITY certerror.longpagetitle1 "Your connection is not secure">
<!ENTITY certerror.longpagetitle2 "Warning: Potential Security Risk Ahead">
<!-- Localization note (certerror.introPara, certerror.introPara1) - The text content of the span tag
<!-- Localization note (certerror.introPara, certerror.introPara2) - The text content of the span tag
will be replaced at runtime with the name of the server to which the user
was trying to connect. -->
<!ENTITY certerror.introPara "The owner of <span class='hostname'/> has configured their website improperly. To protect your information from being stolen, &brandShortName; has not connected to this website.">
<!ENTITY certerror.introPara1 "&brandShortName; detected a potential security threat and did not continue to <span class='hostname'/>. If you visit this site, attackers could try to steal information like your passwords, emails, or credit cards.">
<!ENTITY certerror.introPara2 "&brandShortName; detected a potential security threat and did not continue to <span class='hostname'/>. If you visit this site, attackers could try to steal information like your passwords, emails, or credit card details.">
<!ENTITY certerror.expiredCert.secondPara "This issue is most likely because your computer clock is set to the wrong time, which would prevent &brandShortName; from connecting securely.">

View File

@ -36,15 +36,6 @@ def GeckoBinary(linkage='dependent', mozglue=None):
elif linkage != None:
error('`linkage` must be "dependent", "standalone" or None')
if CONFIG['LIBFUZZER']:
assert mozglue is not None, 'libfuzzer depends on "mozglue"'
USE_LIBS += [
'fuzzer'
]
LOCAL_INCLUDES += [
'/tools/fuzzing/libfuzzer'
]
if mozglue:
LDFLAGS += CONFIG['MOZ_GLUE_WRAP_LDFLAGS']
if mozglue == 'program':

View File

@ -4,7 +4,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
option('--enable-nodejs',
option('--disable-nodejs',
help='Require Node.js to build')
@ -62,10 +62,19 @@ def nodejs_version(node):
def nodejs_suitability(require, node, version):
MIN_NODE_VERSION = Version('8.11')
MAYBE_FILE_A_BUG = '''
If you believe this is a bug, <https://mzl.la/2vLbXAv> is a good way
to file. Executing `mach bootstrap --no-system changes` should
install a compatible version in ~/.mozbuild on most platforms.
More details: <https://bit.ly/2BbyD1E>
'''
if not node:
msg = ('could not find Node.js executable; ensure `node` or `nodejs` '
'is in PATH or set NODEJS in environment to point to an '
'executable')
'executable.%s' % (MAYBE_FILE_A_BUG)
)
if require:
raise FatalCheckError(msg)
@ -75,7 +84,7 @@ def nodejs_suitability(require, node, version):
return
if not version:
msg = 'could not resolve Node.js version'
msg = 'could not resolve Node.js version.%s' % (MAYBE_FILE_A_BUG)
if require:
raise FatalCheckError(msg)
else:
@ -84,8 +93,8 @@ def nodejs_suitability(require, node, version):
return
if version < MIN_NODE_VERSION:
msg = 'NODEJS must point to node %s or newer; %s found' % (
MIN_NODE_VERSION, version)
msg = 'NODEJS must point to node %s or newer; %s found. %s' % (
MIN_NODE_VERSION, version, MAYBE_FILE_A_BUG)
if require:
raise FatalCheckError(msg)

View File

@ -28,43 +28,43 @@ const NetworkMonitorActor = ActorClassWithSpec(networkMonitorSpec, {
* To be removed, specify the ID of the Web console actor.
* This is used to fake emitting an event from it to prevent changing RDP
* behavior.
* @param nsIMessageManager messageManager (optional)
* Passed only when it is instanciated across processes. This is the manager to
* use to communicate with the other process.
* @param object stackTraceCollector (optional)
* When the actor runs in the same process than the requests we are inspecting,
* the web console actor hands over a shared instance to the stack trace
* collector.
* @param nsIMessageManager messageManager
* This is the manager to use to communicate with the console actor. When both
* netmonitor and console actor runs in the same process, this is an instance
* of MockMessageManager instead of a real message manager.
*/
initialize(conn, filters, parentID, messageManager, stackTraceCollector) {
initialize(conn, filters, parentID, messageManager) {
Actor.prototype.initialize.call(this, conn);
this.parentID = parentID;
this.messageManager = messageManager;
this.stackTraceCollector = stackTraceCollector;
// Immediately start watching for new request according to `filters`.
// NetworkMonitor will call `onNetworkEvent` method.
this.netMonitor = new NetworkMonitor(filters, this);
this.netMonitor.init();
if (this.messageManager) {
this.stackTraces = new Set();
this.onStackTraceAvailable = this.onStackTraceAvailable.bind(this);
this.messageManager.addMessageListener("debug:request-stack-available",
this.onStackTraceAvailable);
this.onRequestContent = this.onRequestContent.bind(this);
this.messageManager.addMessageListener("debug:request-content",
this.onRequestContent);
this.onSetPreference = this.onSetPreference.bind(this);
this.messageManager.addMessageListener("debug:netmonitor-preference",
this.onSetPreference);
this.onGetNetworkEventActor = this.onGetNetworkEventActor.bind(this);
this.messageManager.addMessageListener("debug:get-network-event-actor",
this.onGetNetworkEventActor);
this.destroy = this.destroy.bind(this);
this.messageManager.addMessageListener("debug:destroy-network-monitor",
this.destroy);
this.stackTraces = new Set();
this.onStackTraceAvailable = this.onStackTraceAvailable.bind(this);
this.messageManager.addMessageListener("debug:request-stack-available",
this.onStackTraceAvailable);
this.onRequestContent = this.onRequestContent.bind(this);
this.messageManager.addMessageListener("debug:request-content",
this.onRequestContent);
this.onSetPreference = this.onSetPreference.bind(this);
this.messageManager.addMessageListener("debug:netmonitor-preference",
this.onSetPreference);
this.onGetNetworkEventActor = this.onGetNetworkEventActor.bind(this);
this.messageManager.addMessageListener("debug:get-network-event-actor",
this.onGetNetworkEventActor);
this.onDestroyMessage = this.onDestroyMessage.bind(this);
this.messageManager.addMessageListener("debug:destroy-network-monitor",
this.onDestroyMessage);
},
onDestroyMessage({ data }) {
if (data.actorID == this.parentID) {
this.destroy();
}
},
@ -76,8 +76,8 @@ const NetworkMonitorActor = ActorClassWithSpec(networkMonitorSpec, {
this.netMonitor = null;
}
this.stackTraces.clear();
if (this.messageManager) {
this.stackTraces.clear();
this.messageManager.removeMessageListener("debug:request-stack-available",
this.onStackTraceAvailable);
this.messageManager.removeMessageListener("debug:request-content",
@ -87,7 +87,7 @@ const NetworkMonitorActor = ActorClassWithSpec(networkMonitorSpec, {
this.messageManager.removeMessageListener("debug:get-network-event-actor",
this.onGetNetworkEventActor);
this.messageManager.removeMessageListener("debug:destroy-network-monitor",
this.destroy);
this.onDestroyMessage);
this.messageManager = null;
}
},
@ -101,11 +101,7 @@ const NetworkMonitorActor = ActorClassWithSpec(networkMonitorSpec, {
}
},
getRequestContentForURL(url) {
const actor = this._networkEventActorsByURL.get(url);
if (!actor) {
return null;
}
getRequestContentForActor(actor) {
const content = actor._response.content;
if (actor._discardResponseBody || actor._truncated || !content || !content.size) {
// Do not return the stylesheet text if there is no meaningful content or if it's
@ -133,7 +129,10 @@ const NetworkMonitorActor = ActorClassWithSpec(networkMonitorSpec, {
onRequestContent(msg) {
const { url } = msg.data;
const content = this.getRequestContentForURL(url);
const actor = this._networkEventActorsByURL.get(url);
// Always reply with a message, but with a null `content` if this instance
// did not processed this request
const content = actor ? this.getRequestContentForActor(actor) : null;
this.messageManager.sendAsyncMessage("debug:request-content", {
url,
content,
@ -151,7 +150,10 @@ const NetworkMonitorActor = ActorClassWithSpec(networkMonitorSpec, {
onGetNetworkEventActor({ data }) {
const actor = this.getNetworkEventActor(data.channelId);
this.messageManager.sendAsyncMessage("debug:get-network-event-actor", actor.form());
this.messageManager.sendAsyncMessage("debug:get-network-event-actor", {
channelId: data.channelId,
actor: actor.form()
});
},
getNetworkEventActor(channelId) {
@ -175,13 +177,9 @@ const NetworkMonitorActor = ActorClassWithSpec(networkMonitorSpec, {
const actor = this.getNetworkEventActor(channelId);
this._netEvents.set(channelId, actor);
if (this.messageManager) {
event.cause.stacktrace = this.stackTraces.has(channelId);
if (event.cause.stacktrace) {
this.stackTraces.delete(channelId);
}
} else {
event.cause.stacktrace = this.stackTraceCollector.getStackTrace(channelId);
event.cause.stacktrace = this.stackTraces.has(channelId);
if (event.cause.stacktrace) {
this.stackTraces.delete(channelId);
}
actor.init(event);

View File

@ -30,6 +30,7 @@ loader.lazyRequireGetter(this, "addWebConsoleCommands", "devtools/server/actors/
loader.lazyRequireGetter(this, "formatCommand", "devtools/server/actors/webconsole/commands", true);
loader.lazyRequireGetter(this, "isCommand", "devtools/server/actors/webconsole/commands", true);
loader.lazyRequireGetter(this, "validCommands", "devtools/server/actors/webconsole/commands", true);
loader.lazyRequireGetter(this, "createMessageManagerMocks", "devtools/server/actors/webconsole/message-manager-mock", true);
loader.lazyRequireGetter(this, "CONSOLE_WORKER_IDS", "devtools/server/actors/webconsole/utils", true);
loader.lazyRequireGetter(this, "WebConsoleUtils", "devtools/server/actors/webconsole/utils", true);
loader.lazyRequireGetter(this, "EnvironmentActor", "devtools/server/actors/environment", true);
@ -325,22 +326,13 @@ WebConsoleActor.prototype =
this.consoleServiceListener.destroy();
this.consoleServiceListener = null;
}
if (this.networkMonitorActor) {
this.networkMonitorActor.destroy();
this.networkMonitorActor = null;
}
if (this.networkMonitorActorId) {
const messageManager = this.parentActor.messageManager;
if (messageManager) {
if (this.netmonitors) {
for (const { messageManager } of this.netmonitors) {
messageManager.sendAsyncMessage("debug:destroy-network-monitor", {
actorId: this.networkMonitorActorId
actorID: this.actorID
});
}
this.networkMonitorActorId = null;
}
if (this.networkMonitorChildActor) {
this.networkMonitorChildActor.destroy();
this.networkMonitorChildActor = null;
this.netmonitors = null;
}
if (this.consoleAPIListener) {
this.consoleAPIListener.destroy();
@ -589,20 +581,6 @@ WebConsoleActor.prototype =
startListeners: async function(request) {
const startedListeners = [];
const window = !this.parentActor.isRootActor ? this.window : null;
let messageManager = null;
// Check if the actor is running in a child process (but only if
// Services.appinfo exists, to prevent startListeners to fail
// when the target is a Worker).
const processBoundary = Services.appinfo && (
Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT
);
// Retrieve a message manager from the parent actor if this actor is
// not currently running in the main process.
if (processBoundary) {
messageManager = this.parentActor.messageManager;
}
while (request.listeners.length > 0) {
const listener = request.listeners.shift();
@ -634,19 +612,33 @@ WebConsoleActor.prototype =
if (isWorker) {
break;
}
if (!this.networkMonitorActorId && !this.networkMonitorActor) {
// Create a StackTraceCollector that's going to be shared both by
// the NetworkMonitorActor running in the same process for service worker
// requests, as well with the NetworkMonitorActor running in the parent
// process. It will communicate via message manager for this one.
this.stackTraceCollector = new StackTraceCollector({ window },
messageManager);
this.stackTraceCollector.init();
if (!this.netmonitors) {
// Instanciate fake message managers used for service worker's netmonitor
// when running in the content process, and for netmonitor running in the
// same process when running in the parent process.
// `createMessageManagerMocks` returns a couple of connected messages
// managers that pass messages to each other to simulate the process
// boundary. We will use the first one for the webconsole-actor and the
// second one will be used by the netmonitor-actor.
const [ mmMockParent, mmMockChild ] = createMessageManagerMocks();
if (messageManager && processBoundary) {
// Maintain the list of message manager we should message to/listen from
// to support the netmonitor instances, also records actorID of each
// NetworkMonitorActor.
// Array of `{ messageManager, parentProcess }`.
// Where `parentProcess` is true for the netmonitor actor instanciated in the
// parent process.
this.netmonitors = [];
// Check if the actor is running in a content process
const isInContentProcess =
Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT &&
this.parentActor.messageManager;
if (isInContentProcess) {
// Start a network monitor in the parent process to listen to
// most requests than happen in parent
this.networkMonitorActorId = await this.conn.spawnActorInParentProcess(
// most requests that happen in parent. This one will communicate through
// `messageManager`.
await this.conn.spawnActorInParentProcess(
this.actorID, {
module: "devtools/server/actors/network-monitor",
constructor: "NetworkMonitorActor",
@ -655,17 +647,34 @@ WebConsoleActor.prototype =
this.actorID
],
});
// Spawn also one in the child to listen to service workers
this.networkMonitorChildActor = new NetworkMonitorActor(this.conn,
{ window },
this.actorID,
null,
this.stackTraceCollector);
} else {
this.networkMonitorActor = new NetworkMonitorActor(this.conn, { window },
this.actorID, null, this.stackTraceCollector);
this.netmonitors.push({
messageManager: this.parentActor.messageManager,
parentProcess: true
});
}
// When the console actor runs in the parent process, Netmonitor can be ran
// in the process and communicate through `messageManagerMock`.
// And while it runs in the content process, we also spawn one in the content
// to listen to requests that happen in the content process (for instance
// service workers requests)
new NetworkMonitorActor(this.conn,
{ window },
this.actorID,
mmMockParent);
this.netmonitors.push({
messageManager: mmMockChild,
parentProcess: !isInContentProcess
});
// Create a StackTraceCollector that's going to be shared both by
// the NetworkMonitorActor running in the same process for service worker
// requests, as well with the NetworkMonitorActor running in the parent
// process. It will communicate via message manager for this one.
this.stackTraceCollector = new StackTraceCollector({ window },
this.netmonitors);
this.stackTraceCollector.init();
}
startedListeners.push(listener);
break;
@ -764,22 +773,13 @@ WebConsoleActor.prototype =
stoppedListeners.push(listener);
break;
case "NetworkActivity":
if (this.networkMonitorActor) {
this.networkMonitorActor.destroy();
this.networkMonitorActor = null;
}
if (this.networkMonitorActorId) {
const messageManager = this.parentActor.messageManager;
if (messageManager) {
if (this.netmonitors) {
for (const { messageManager } of this.netmonitors) {
messageManager.sendAsyncMessage("debug:destroy-network-monitor", {
actorId: this.networkMonitorActorId
actorID: this.actorID
});
}
this.networkMonitorActorId = null;
}
if (this.networkMonitorChildActor) {
this.networkMonitorChildActor.destroy();
this.networkMonitorChildActor = null;
this.netmonitors = null;
}
if (this.stackTraceCollector) {
this.stackTraceCollector.destroy();
@ -1252,31 +1252,19 @@ WebConsoleActor.prototype =
for (const key in request.preferences) {
this._prefs[key] = request.preferences[key];
if (key == "NetworkMonitor.saveRequestAndResponseBodies") {
if (this.networkMonitorActor) {
this.networkMonitorActor.netMonitor.saveRequestAndResponseBodies =
this._prefs[key];
}
if (this.networkMonitorChildActor) {
this.networkMonitorChildActor.netMonitor.saveRequestAndResponseBodies =
this._prefs[key];
}
if (this.networkMonitorActorId) {
const messageManager = this.parentActor.messageManager;
messageManager.sendAsyncMessage("debug:netmonitor-preference",
{ saveRequestAndResponseBodies: this._prefs[key] });
}
} else if (key == "NetworkMonitor.throttleData") {
if (this.networkMonitorActor) {
this.networkMonitorActor.netMonitor.throttleData = this._prefs[key];
}
if (this.networkMonitorChildActor) {
this.networkMonitorChildActor.netMonitor.throttleData = this._prefs[key];
}
if (this.networkMonitorActorId) {
const messageManager = this.parentActor.messageManager;
messageManager.sendAsyncMessage("debug:netmonitor-preference",
{ throttleData: this._prefs[key] });
if (this.netmonitors) {
if (key == "NetworkMonitor.saveRequestAndResponseBodies") {
for (const { messageManager } of this.netmonitors) {
messageManager.sendAsyncMessage("debug:netmonitor-preference", {
saveRequestAndResponseBodies: this._prefs[key]
});
}
} else if (key == "NetworkMonitor.throttleData") {
for (const { messageManager } of this.netmonitors) {
messageManager.sendAsyncMessage("debug:netmonitor-preference", {
throttleData: this._prefs[key]
});
}
}
}
}
@ -1818,26 +1806,30 @@ WebConsoleActor.prototype =
* The URL of the request to search for.
*/
getRequestContentForURL(url) {
// When running in Parent Process, call the NetworkMonitorActor directly.
if (this.networkMonitorActor) {
return this.networkMonitorActor.getRequestContentForURL(url);
} else if (this.networkMonitorActorId) {
// Otherwise, if the netmonitor is started, but on the parent process,
// pipe the data through the message manager
const messageManager = this.parentActor.messageManager;
return new Promise(resolve => {
const onMessage = ({ data }) => {
if (data.url == url) {
if (!this.netmonitors) {
return null;
}
return new Promise(resolve => {
let messagesReceived = 0;
const onMessage = ({ data }) => {
if (data.url != url) {
return;
}
messagesReceived++;
// Either use the first response with a content, or return a null content
// if we received the responses from all the message managers.
if (data.content || messagesReceived == this.netmonitors.length) {
for (const { messageManager } of this.netmonitors) {
messageManager.removeMessageListener("debug:request-content", onMessage);
resolve(data.content);
}
};
resolve(data.content);
}
};
for (const { messageManager } of this.netmonitors) {
messageManager.addMessageListener("debug:request-content", onMessage);
messageManager.sendAsyncMessage("debug:request-content", { url });
});
}
// Finally, if the netmonitor is not started at all, return null
return null;
}
});
},
/**
@ -1883,30 +1875,28 @@ WebConsoleActor.prototype =
NetUtil.asyncFetch(channel, () => {});
// When running in Parent Process, call the NetworkMonitorActor directly.
if (!this.netmonitors) {
return null;
}
const { channelId } = channel;
if (this.networkMonitorActor) {
const actor = this.networkMonitorActor.getNetworkEventActor(channelId);
return {
eventActor: actor.form()
};
} else if (this.networkMonitorActorId) {
// Otherwise, if the netmonitor is started, but on the parent process,
// pipe the data through the message manager
const messageManager = this.parentActor.messageManager;
return new Promise(resolve => {
const onMessage = ({ data }) => {
// Only query the NetworkMonitorActor running in the parent process, where the
// request will be done. There always is one listener running in the parent process,
// see startListeners.
const netmonitor = this.netmonitors.filter(({ parentProcess }) => parentProcess)[0];
const { messageManager } = netmonitor;
return new Promise(resolve => {
const onMessage = ({ data }) => {
if (data.channelId == channelId) {
messageManager.removeMessageListener("debug:get-network-event-actor",
onMessage);
resolve({
eventActor: data
eventActor: data.actor
});
};
messageManager.addMessageListener("debug:get-network-event-actor", onMessage);
messageManager.sendAsyncMessage("debug:get-network-event-actor", { channelId });
});
}
return null;
}
};
messageManager.addMessageListener("debug:get-network-event-actor", onMessage);
messageManager.sendAsyncMessage("debug:get-network-event-actor", { channelId });
});
},
/**

View File

@ -0,0 +1,68 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/**
* Implements a fake MessageManager class that allows to use the message
* manager API within the same process. This implementation will forward
* messages within the same process.
*
* It helps having the same codepath for actors being evaluated in the same
* process *and* in a remote one.
*/
function MessageManagerMock() {
this._listeners = new Map();
}
MessageManagerMock.prototype = {
addMessageListener(name, listener) {
let listeners = this._listeners.get(name);
if (!listeners) {
listeners = [];
this._listeners.set(name, listeners);
}
if (!listeners.includes(listener)) {
listeners.push(listener);
}
},
removeMessageListener(name, listener) {
const listeners = this._listeners.get(name);
const idx = listeners.indexOf(listener);
listeners.splice(idx, 1);
},
sendAsyncMessage(name, data) {
this.other.internalSendAsyncMessage(name, data);
},
internalSendAsyncMessage(name, data) {
const listeners = this._listeners.get(name);
if (!listeners) {
return;
}
const message = {
target: this,
data
};
for (const listener of listeners) {
if (typeof listener === "object" &&
typeof listener.receiveMessage === "function") {
listener.receiveMessage(message);
} else if (typeof listener === "function") {
listener(message);
}
}
},
};
/**
* Create two MessageManager mocks, connected to each others.
* Calling sendAsyncMessage on the first will dispatch messages on the second one,
* and the other way around
*/
exports.createMessageManagerMocks = function() {
const a = new MessageManagerMock();
const b = new MessageManagerMock();
a.other = b;
b.other = a;
return [a, b];
};

View File

@ -8,6 +8,7 @@ DevToolsModules(
'commands.js',
'content-process-forward.js',
'listeners.js',
'message-manager-mock.js',
'screenshot.js',
'utils.js',
'worker-listeners.js',

View File

@ -198,22 +198,6 @@ var NetworkHelper = {
return null;
},
/**
* Gets the web appId that is associated with request.
*
* @param nsIHttpChannel request
* @returns number|null
* The appId for the given request, if available.
*/
getAppIdForRequest: function(request) {
try {
return this.getRequestLoadContext(request).appId;
} catch (ex) {
// request loadContent is not always available.
}
return null;
},
/**
* Gets the topFrameElement that is associated with request. This
* works in single-process and multiprocess contexts. It may cross

View File

@ -17,12 +17,15 @@ loader.lazyRequireGetter(this, "DevToolsUtils",
"devtools/shared/DevToolsUtils");
loader.lazyRequireGetter(this, "flags",
"devtools/shared/flags");
loader.lazyRequireGetter(this, "NetworkThrottleManager",
"devtools/shared/webconsole/throttle", true);
loader.lazyRequireGetter(this, "CacheEntry",
"devtools/shared/platform/cache-entry", true);
loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
loader.lazyServiceGetter(this, "gActivityDistributor",
"@mozilla.org/network/http-activity-distributor;1",
"nsIHttpActivityDistributor");
const {NetworkThrottleManager} = require("devtools/shared/webconsole/throttle");
const {CacheEntry} = require("devtools/shared/platform/cache-entry");
// Network logging
// The maximum uint32 value.
@ -47,7 +50,7 @@ const HTTP_TEMPORARY_REDIRECT = 307;
*/
function matchRequest(channel, filters) {
// Log everything if no filter is specified
if (!filters.outerWindowID && !filters.window && !filters.appId) {
if (!filters.outerWindowID && !filters.window) {
return true;
}
@ -93,13 +96,6 @@ function matchRequest(channel, filters) {
}
}
if (filters.appId) {
const appId = NetworkHelper.getAppIdForRequest(channel);
if (appId && appId == filters.appId) {
return true;
}
}
return false;
}
@ -177,33 +173,33 @@ ChannelEventSinkFactory.getService = function() {
return Cc[SINK_CONTRACT_ID].getService(Ci.nsIChannelEventSink).wrappedJSObject;
};
function StackTraceCollector(filters, messageManager) {
function StackTraceCollector(filters, netmonitors) {
this.filters = filters;
this.stacktracesById = new Map();
this.messageManager = messageManager;
this.netmonitors = netmonitors;
}
StackTraceCollector.prototype = {
init() {
Services.obs.addObserver(this, "http-on-opening-request");
ChannelEventSinkFactory.getService().registerCollector(this);
if (this.messageManager) {
this.onGetStack = this.onGetStack.bind(this);
this.messageManager.addMessageListener("debug:request-stack", this.onGetStack);
this.onGetStack = this.onGetStack.bind(this);
for (const { messageManager } of this.netmonitors) {
messageManager.addMessageListener("debug:request-stack", this.onGetStack);
}
},
destroy() {
Services.obs.removeObserver(this, "http-on-opening-request");
ChannelEventSinkFactory.getService().unregisterCollector(this);
if (this.messageManager) {
this.messageManager.removeMessageListener("debug:request-stack", this.onGetStack);
for (const { messageManager } of this.netmonitors) {
messageManager.removeMessageListener("debug:request-stack", this.onGetStack);
}
},
_saveStackTrace(channel, stacktrace) {
if (this.messageManager) {
this.messageManager.sendAsyncMessage("debug:request-stack-available", {
for (const { messageManager } of this.netmonitors) {
messageManager.sendAsyncMessage("debug:request-stack-available", {
channelId: channel.channelId,
stacktrace: stacktrace && stacktrace.length > 0
});
@ -263,9 +259,10 @@ StackTraceCollector.prototype = {
},
onGetStack(msg) {
const messageManager = msg.target;
const channelId = msg.data;
const stack = this.getStackTrace(channelId);
this.messageManager.sendAsyncMessage("debug:request-stack", {
messageManager.sendAsyncMessage("debug:request-stack", {
channelId,
stack,
});
@ -769,7 +766,6 @@ NetworkResponseListener.prototype = {
* Object with the filters to use for network requests:
* - window (nsIDOMWindow): filter network requests by the associated
* window object.
* - appId (number): filter requests by the appId.
* - outerWindowID (number): filter requests by their top frame's outerWindowID.
* Filters are optional. If any of these filters match the request is
* logged (OR is applied). If no filter is provided then all requests are

View File

@ -181,6 +181,11 @@ private:
nsAttrValue mValue;
};
#ifdef _MSC_VER
// Disable MSVC warning 'nonstandard extension used: zero-sized array in struct/union'
#pragma warning(push)
#pragma warning(disable:4200)
#endif
class Impl
{
public:
@ -213,6 +218,10 @@ private:
// Allocated in the same buffer as `Impl`.
InternalAttr mBuffer[0];
};
#ifdef _MSC_VER
#pragma warning(pop)
#endif
mozilla::Span<InternalAttr> NonMappedAttrs()
{

View File

@ -22642,17 +22642,25 @@ DeleteDatabaseOp::LoadPreviousVersion(nsIFile* aDatabaseFile)
#ifdef DEBUG
{
nsCOMPtr<mozIStorageStatement> stmt;
MOZ_ALWAYS_SUCCEEDS(
connection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT name "
"FROM database"
), getter_AddRefs(stmt)));
rv = connection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT name "
"FROM database"
), getter_AddRefs(stmt));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
bool hasResult;
MOZ_ALWAYS_SUCCEEDS(stmt->ExecuteStep(&hasResult));
rv = stmt->ExecuteStep(&hasResult);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsString databaseName;
MOZ_ALWAYS_SUCCEEDS(stmt->GetString(0, databaseName));
rv = stmt->GetString(0, databaseName);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
MOZ_ASSERT(mCommonParams.metadata().name() == databaseName);
}

View File

@ -221,6 +221,11 @@ skip-if = toolkit == 'android' # bug 1091965
[test_periodicWave.html]
[test_periodicWaveDisableNormalization.html]
[test_periodicWaveBandLimiting.html]
[test_retrospective-exponentialRampToValueAtTime.html]
[test_retrospective-linearRampToValueAtTime.html]
[test_retrospective-setTargetAtTime.html]
[test_retrospective-setValueAtTime.html]
[test_retrospective-setValueCurveAtTime.html]
[test_ScriptProcessorCollected1.html]
[test_scriptProcessorNode.html]
[test_scriptProcessorNodeChannelCount.html]

View File

@ -0,0 +1,51 @@
<!doctype html>
<meta charset=utf-8>
<title>Test exponentialRampToValue with end time in the past</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
function do_test(t, context) {
var source = context.createConstantSource();
source.start();
var test = context.createGain();
test.gain.exponentialRampToValueAtTime(0.1, 0.5*context.currentTime);
test.gain.exponentialRampToValueAtTime(0.9, 2.0);
var reference = context.createGain();
reference.gain.exponentialRampToValueAtTime(0.1, context.currentTime);
reference.gain.exponentialRampToValueAtTime(0.9, 2.0);
source.connect(test);
source.connect(reference);
var merger = context.createChannelMerger();
test.connect(merger, 0, 0);
reference.connect(merger, 0, 1);
var processor = context.createScriptProcessor(0, 2, 0);
merger.connect(processor);
processor.onaudioprocess =
t.step_func_done((e) => {
source.stop();
processor.onaudioprocess = null;
var testValue = e.inputBuffer.getChannelData(0)[0];
var referenceValue = e.inputBuffer.getChannelData(1)[0];
assert_equals(testValue, referenceValue,
"value matches expected");
});
}
async_test(function(t) {
var context = new AudioContext;
(function waitForTimeAdvance() {
if (context.currentTime == 0) {
t.step_timeout(waitForTimeAdvance, 0);
} else {
do_test(t, context);
}
})();
});
</script>

View File

@ -0,0 +1,51 @@
<!doctype html>
<meta charset=utf-8>
<title>Test linearRampToValue with end time in the past</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
function do_test(t, context) {
var source = context.createConstantSource();
source.start();
var test = context.createGain();
test.gain.linearRampToValueAtTime(0.1, 0.5*context.currentTime);
test.gain.linearRampToValueAtTime(0.9, 2.0);
var reference = context.createGain();
reference.gain.linearRampToValueAtTime(0.1, context.currentTime);
reference.gain.linearRampToValueAtTime(0.9, 2.0);
source.connect(test);
source.connect(reference);
var merger = context.createChannelMerger();
test.connect(merger, 0, 0);
reference.connect(merger, 0, 1);
var processor = context.createScriptProcessor(0, 2, 0);
merger.connect(processor);
processor.onaudioprocess =
t.step_func_done((e) => {
source.stop();
processor.onaudioprocess = null;
var testValue = e.inputBuffer.getChannelData(0)[0];
var referenceValue = e.inputBuffer.getChannelData(1)[0];
assert_equals(testValue, referenceValue,
"value matches expected");
});
}
async_test(function(t) {
var context = new AudioContext;
(function waitForTimeAdvance() {
if (context.currentTime == 0) {
t.step_timeout(waitForTimeAdvance, 0);
} else {
do_test(t, context);
}
})();
});
</script>

View File

@ -0,0 +1,51 @@
<!doctype html>
<meta charset=utf-8>
<title>Test setTargetAtTime with start time in the past</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
function do_test(t, context) {
var source = context.createConstantSource();
source.start();
var test = context.createGain();
test.gain.setTargetAtTime(0.1, 0.5*context.currentTime, 0.1);
test.gain.linearRampToValueAtTime(0.9, 2.0);
var reference = context.createGain();
reference.gain.setTargetAtTime(0.1, context.currentTime, 0.1);
reference.gain.linearRampToValueAtTime(0.9, 2.0);
source.connect(test);
source.connect(reference);
var merger = context.createChannelMerger();
test.connect(merger, 0, 0);
reference.connect(merger, 0, 1);
var processor = context.createScriptProcessor(0, 2, 0);
merger.connect(processor);
processor.onaudioprocess =
t.step_func_done((e) => {
source.stop();
processor.onaudioprocess = null;
var testValue = e.inputBuffer.getChannelData(0)[0];
var referenceValue = e.inputBuffer.getChannelData(1)[0];
assert_equals(testValue, referenceValue,
"value matches expected");
});
}
async_test(function(t) {
var context = new AudioContext;
(function waitForTimeAdvance() {
if (context.currentTime == 0) {
t.step_timeout(waitForTimeAdvance, 0);
} else {
do_test(t, context);
}
})();
});
</script>

View File

@ -0,0 +1,54 @@
<!DOCTYPE html>
<title>Test setValueAtTime with startTime in the past</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
function do_test(t, context) {
var source = context.createConstantSource();
source.start();
// Use a ramp of slope 1/sample to measure time.
// The end value is the extent of exact precision in single precision float.
const rampEnd = Math.pow(2, 24);
const rampEndSeconds = rampEnd / context.sampleRate;
var test = context.createGain();
test.gain.setValueAtTime(0.0, 0.5*context.currentTime);
test.gain.linearRampToValueAtTime(rampEnd, rampEndSeconds);
var reference = context.createGain();
reference.gain.setValueAtTime(0.0, context.currentTime);
reference.gain.linearRampToValueAtTime(rampEnd, rampEndSeconds);
source.connect(test);
source.connect(reference);
var merger = context.createChannelMerger();
test.connect(merger, 0, 0);
reference.connect(merger, 0, 1);
var processor = context.createScriptProcessor(0, 2, 0);
merger.connect(processor);
processor.onaudioprocess =
t.step_func_done((e) => {
source.stop();
processor.onaudioprocess = null;
var testValue = e.inputBuffer.getChannelData(0)[0];
var referenceValue = e.inputBuffer.getChannelData(1)[0];
assert_equals(testValue, referenceValue,
"ramp value matches expected");
});
}
async_test(function(t) {
var context = new AudioContext;
(function waitForTimeAdvance() {
if (context.currentTime == 0) {
t.step_timeout(waitForTimeAdvance, 0);
} else {
do_test(t, context);
}
})();
});
</script>

View File

@ -0,0 +1,49 @@
<!doctype html>
<meta charset=utf-8>
<title>Test SetValueCurve with start time in the past</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
function do_test(t, context) {
var source = context.createConstantSource();
source.start();
var test = context.createGain();
test.gain.setValueCurveAtTime(new Float32Array([1.0, 0.1]), 0.0, 1.0);
var reference = context.createGain();
reference.gain.setValueCurveAtTime(new Float32Array([1.0, 0.1]), 0.5*context.currentTime, 1.0);
source.connect(test);
source.connect(reference);
var merger = context.createChannelMerger();
test.connect(merger, 0, 0);
reference.connect(merger, 0, 1);
var processor = context.createScriptProcessor(0, 2, 0);
merger.connect(processor);
processor.onaudioprocess =
t.step_func_done((e) => {
source.stop();
processor.onaudioprocess = null;
var testValue = e.inputBuffer.getChannelData(0)[0];
var referenceValue = e.inputBuffer.getChannelData(1)[0];
assert_equals(testValue, referenceValue,
"value matches expected");
});
}
async_test(function(t) {
var context = new AudioContext;
(function waitForTimeAdvance() {
if (context.currentTime == 0) {
t.step_timeout(waitForTimeAdvance, 0);
} else {
do_test(t, context);
}
})();
});
</script>

View File

@ -4537,7 +4537,7 @@ EditorBase::ClearSelection()
}
already_AddRefed<Element>
EditorBase::CreateHTMLContent(nsAtom* aTag)
EditorBase::CreateHTMLContent(const nsAtom* aTag)
{
MOZ_ASSERT(aTag);

View File

@ -1046,7 +1046,7 @@ protected: // May be called by friends.
*
* @param aTag Tag you want.
*/
already_AddRefed<Element> CreateHTMLContent(nsAtom* aTag);
already_AddRefed<Element> CreateHTMLContent(const nsAtom* aTag);
/**
* Creates text node which is marked as "maybe modified frequently".

View File

@ -1467,7 +1467,7 @@ HTMLEditor::RebuildDocumentFromSource(const nsAString& aSourceString)
}
RefPtr<Element> divElement =
CreateElementWithDefaults(NS_LITERAL_STRING("div"));
CreateElementWithDefaults(*nsGkAtoms::div);
if (NS_WARN_IF(!divElement)) {
return NS_ERROR_FAILURE;
}
@ -2805,58 +2805,52 @@ HTMLEditor::GetSelectedElement(Selection& aSelection,
}
already_AddRefed<Element>
HTMLEditor::CreateElementWithDefaults(const nsAString& aTagName)
HTMLEditor::CreateElementWithDefaults(const nsAtom& aTagName)
{
MOZ_ASSERT(!aTagName.IsEmpty());
// NOTE: Despite of public method, this can be called for internal use.
nsAutoString tagName(aTagName);
ToLowerCase(tagName);
nsAutoString realTagName;
const nsAtom* realTagName =
IsLinkTag(aTagName) || IsNamedAnchorTag(aTagName) ? nsGkAtoms::a :
&aTagName;
if (IsLinkTag(tagName) || IsNamedAnchorTag(tagName)) {
realTagName.Assign('a');
} else {
realTagName = tagName;
}
// We don't use editor's CreateElement because we don't want to go through
// the transaction system
// New call to use instead to get proper HTML element, bug 39919
RefPtr<nsAtom> realTagAtom = NS_Atomize(realTagName);
RefPtr<Element> newElement = CreateHTMLContent(realTagAtom);
RefPtr<Element> newElement = CreateHTMLContent(realTagName);
if (!newElement) {
return nullptr;
}
// Mark the new element dirty, so it will be formatted
ErrorResult rv;
// XXX Don't we need to check the error result of setting _moz_dirty attr?
IgnoredErrorResult rv;
newElement->SetAttribute(NS_LITERAL_STRING("_moz_dirty"), EmptyString(), rv);
// Set default values for new elements
if (tagName.EqualsLiteral("table")) {
if (realTagName == nsGkAtoms::table) {
newElement->SetAttribute(NS_LITERAL_STRING("cellpadding"),
NS_LITERAL_STRING("2"), rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
return nullptr;
}
newElement->SetAttribute(NS_LITERAL_STRING("cellspacing"),
NS_LITERAL_STRING("2"), rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
return nullptr;
}
newElement->SetAttribute(NS_LITERAL_STRING("border"),
NS_LITERAL_STRING("1"), rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
return nullptr;
}
} else if (tagName.EqualsLiteral("td")) {
} else if (realTagName == nsGkAtoms::td) {
nsresult rv =
SetAttributeOrEquivalent(
newElement, nsGkAtoms::valign, NS_LITERAL_STRING("top"), true);
NS_ENSURE_SUCCESS(rv, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
}
// ADD OTHER TAGS HERE
@ -2867,12 +2861,20 @@ NS_IMETHODIMP
HTMLEditor::CreateElementWithDefaults(const nsAString& aTagName,
Element** aReturn)
{
NS_ENSURE_TRUE(!aTagName.IsEmpty() && aReturn, NS_ERROR_NULL_POINTER);
if (NS_WARN_IF(aTagName.IsEmpty()) || NS_WARN_IF(!aReturn)) {
return NS_ERROR_INVALID_ARG;
}
*aReturn = nullptr;
nsCOMPtr<Element> newElement = CreateElementWithDefaults(aTagName);
NS_ENSURE_TRUE(newElement, NS_ERROR_FAILURE);
RefPtr<nsAtom> tagName = GetLowerCaseNameAtom(aTagName);
if (NS_WARN_IF(!tagName)) {
return NS_ERROR_INVALID_ARG;
}
RefPtr<Element> newElement = CreateElementWithDefaults(*tagName);
if (NS_WARN_IF(!newElement)) {
return NS_ERROR_FAILURE;
}
newElement.forget(aReturn);
return NS_OK;
}

View File

@ -180,6 +180,22 @@ public:
*/
nsresult OnInputLineBreak();
/**
* CreateElementWithDefaults() creates new element whose name is
* aTagName with some default attributes are set. Note that this is a
* public utility method. I.e., just creates element, not insert it
* into the DOM tree.
* NOTE: This is available for internal use too since this does not change
* the DOM tree nor undo transactions, and does not refer Selection,
* HTMLEditRules, etc.
*
* @param aTagName The new element's tag name. If the name is
* one of "href", "anchor" or "namedanchor",
* this creates an <a> element.
* @return Newly created element.
*/
already_AddRefed<Element> CreateElementWithDefaults(const nsAtom& aTagName);
/**
* Indent or outdent content around Selection.
*/
@ -1477,10 +1493,7 @@ protected: // Shouldn't be used by friend classes
const nsAString& aValue);
typedef enum { eInserted, eAppended } InsertedOrAppended;
void DoContentInserted(nsIContent* aChild, InsertedOrAppended);
// XXX Shouldn't this used by external classes instead of nsIHTMLEditor's
// method?
already_AddRefed<Element> CreateElementWithDefaults(
const nsAString& aTagName);
/**
* Returns an anonymous Element of type aTag,
* child of aParentContent. If aIsCreatedHidden is true, the class

View File

@ -1536,12 +1536,16 @@ InsertTagCommand::DoCommand(const char* aCmdName, nsISupports* refCon)
return NS_ERROR_FAILURE;
}
RefPtr<Element> newElement;
nsresult rv = htmlEditor->CreateElementWithDefaults(
nsDependentAtomString(mTagName), getter_AddRefs(newElement));
NS_ENSURE_SUCCESS(rv, rv);
return htmlEditor->InsertElementAtSelection(newElement, true);
RefPtr<Element> newElement =
htmlEditor->CreateElementWithDefaults(*mTagName);
if (NS_WARN_IF(!newElement)) {
return NS_ERROR_FAILURE;
}
nsresult rv = htmlEditor->InsertElementAtSelection(newElement, true);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
NS_IMETHODIMP
@ -1591,22 +1595,32 @@ InsertTagCommand::DoCommandParams(const char *aCommandName,
return NS_ERROR_NOT_IMPLEMENTED;
}
RefPtr<Element> elem;
rv = htmlEditor->CreateElementWithDefaults(nsDependentAtomString(mTagName),
getter_AddRefs(elem));
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<Element> newElement =
htmlEditor->CreateElementWithDefaults(*mTagName);
if (NS_WARN_IF(!newElement)) {
return NS_ERROR_FAILURE;
}
ErrorResult err;
elem->SetAttribute(attributeType, attribute, err);
newElement->SetAttribute(attributeType, attribute, err);
if (NS_WARN_IF(err.Failed())) {
return err.StealNSResult();
}
// do actual insertion
if (mTagName == nsGkAtoms::a) {
return htmlEditor->InsertLinkAroundSelection(elem);
rv = htmlEditor->InsertLinkAroundSelection(newElement);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
return htmlEditor->InsertElementAtSelection(elem, true);
rv = htmlEditor->InsertElementAtSelection(newElement, true);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
NS_IMETHODIMP

View File

@ -109,8 +109,7 @@ HTMLEditor::InsertCell(Element* aCell,
}
RefPtr<Element> newCell =
CreateElementWithDefaults(aIsHeader ? NS_LITERAL_STRING("th") :
NS_LITERAL_STRING("tb"));
CreateElementWithDefaults(aIsHeader ? *nsGkAtoms::th : *nsGkAtoms::td);
if (NS_WARN_IF(!newCell)) {
return NS_ERROR_FAILURE;
}
@ -202,10 +201,8 @@ HTMLEditor::InsertTableCell(int32_t aNumber,
AutoTransactionsConserveSelection dontChangeSelection(*this);
for (int32_t i = 0; i < aNumber; i++) {
RefPtr<Element> newCell;
rv = CreateElementWithDefaults(NS_LITERAL_STRING("td"),
getter_AddRefs(newCell));
if (NS_SUCCEEDED(rv) && newCell) {
RefPtr<Element> newCell = CreateElementWithDefaults(*nsGkAtoms::td);
if (newCell) {
if (aAfter) {
cellOffset++;
}
@ -214,6 +211,8 @@ HTMLEditor::InsertTableCell(int32_t aNumber,
if (NS_FAILED(rv)) {
break;
}
} else {
rv = NS_ERROR_FAILURE;
}
}
// XXX This is perhaps the result of the last call of
@ -625,13 +624,16 @@ HTMLEditor::InsertTableRow(int32_t aNumber,
for (int32_t row = 0; row < aNumber; row++) {
// Create a new row
nsCOMPtr<Element> newRow = CreateElementWithDefaults(trStr);
NS_ENSURE_TRUE(newRow, NS_ERROR_FAILURE);
RefPtr<Element> newRow = CreateElementWithDefaults(*nsGkAtoms::tr);
if (NS_WARN_IF(!newRow)) {
return NS_ERROR_FAILURE;
}
for (int32_t i = 0; i < cellsInRow; i++) {
nsCOMPtr<Element> newCell =
CreateElementWithDefaults(NS_LITERAL_STRING("td"));
NS_ENSURE_TRUE(newCell, NS_ERROR_FAILURE);
RefPtr<Element> newCell = CreateElementWithDefaults(*nsGkAtoms::td);
if (NS_WARN_IF(!newCell)) {
return NS_ERROR_FAILURE;
}
// Don't use transaction system yet! (not until entire row is
// inserted)

View File

@ -5,7 +5,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPIDL_SOURCES += [
'nsIAutoConfig.idl',
'nsIReadConfig.idl',
]

View File

@ -1,26 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
%{C++
#define NS_AUTOCONFIG_CID\
{ 0xe036c738,\
0x1dd1,\
0x11b2,\
{ 0x93, 0x92, 0x9d, 0x94, 0xaa, 0x74, 0xb0, 0xc5 }\
}
#define NS_AUTOCONFIG_CONTRACTID \
"@mozilla.org/autoconfiguration;1"
%}
[uuid (80DB54AE-13F2-11d5-BE44-00108335A220)]
interface nsIAutoConfig : nsISupports {
attribute string configURL;
};

View File

@ -33,7 +33,7 @@ mozilla::LazyLogModule MCD("MCD");
// nsISupports Implementation
NS_IMPL_ISUPPORTS(nsAutoConfig, nsIAutoConfig, nsITimerCallback, nsIStreamListener,
NS_IMPL_ISUPPORTS(nsAutoConfig, nsITimerCallback, nsIStreamListener,
nsIObserver, nsIRequestObserver, nsISupportsWeakReference,
nsINamed)
@ -63,28 +63,10 @@ nsAutoConfig::~nsAutoConfig()
{
}
// attribute string configURL
NS_IMETHODIMP nsAutoConfig::GetConfigURL(char **aConfigURL)
void
nsAutoConfig::SetConfigURL(const char *aConfigURL)
{
if (!aConfigURL)
return NS_ERROR_NULL_POINTER;
if (mConfigURL.IsEmpty()) {
*aConfigURL = nullptr;
return NS_OK;
}
*aConfigURL = ToNewCString(mConfigURL);
if (!*aConfigURL)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP nsAutoConfig::SetConfigURL(const char *aConfigURL)
{
if (!aConfigURL)
return NS_ERROR_NULL_POINTER;
mConfigURL.Assign(aConfigURL);
return NS_OK;
}
NS_IMETHODIMP

View File

@ -6,7 +6,6 @@
#ifndef nsAutoConfig_h
#define nsAutoConfig_h
#include "nsIAutoConfig.h"
#include "nsITimer.h"
#include "nsIFile.h"
#include "nsINamed.h"
@ -17,18 +16,16 @@
#include "nsWeakReference.h"
#include "nsString.h"
class nsAutoConfig : public nsIAutoConfig,
public nsITimerCallback,
public nsIStreamListener,
public nsIObserver,
public nsSupportsWeakReference,
public nsINamed
class nsAutoConfig final : public nsITimerCallback,
public nsIStreamListener,
public nsIObserver,
public nsSupportsWeakReference,
public nsINamed
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIAUTOCONFIG
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIOBSERVER
@ -38,6 +35,8 @@ class nsAutoConfig : public nsIAutoConfig,
nsAutoConfig();
nsresult Init();
void SetConfigURL(const char* aConfigURL);
protected:
virtual ~nsAutoConfig();

View File

@ -4,24 +4,19 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ModuleUtils.h"
#include "nsAutoConfig.h"
#include "nsReadConfig.h"
#include "nsIAppStartupNotifier.h"
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsAutoConfig, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsReadConfig, Init)
NS_DEFINE_NAMED_CID(NS_AUTOCONFIG_CID);
NS_DEFINE_NAMED_CID(NS_READCONFIG_CID);
static const mozilla::Module::CIDEntry kAutoConfigCIDs[] = {
{ &kNS_AUTOCONFIG_CID, false, nullptr, nsAutoConfigConstructor },
{ &kNS_READCONFIG_CID, false, nullptr, nsReadConfigConstructor },
{ nullptr }
};
static const mozilla::Module::ContractIDEntry kAutoConfigContracts[] = {
{ NS_AUTOCONFIG_CONTRACTID, &kNS_AUTOCONFIG_CID },
{ NS_READCONFIG_CONTRACTID, &kNS_READCONFIG_CID },
{ nullptr }
};

View File

@ -10,7 +10,6 @@
#include "nsIAppStartup.h"
#include "nsContentUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsIAutoConfig.h"
#include "nsIComponentManager.h"
#include "nsIFile.h"
#include "nsIObserverService.h"
@ -233,14 +232,14 @@ nsresult nsReadConfig::readConfigFile()
if (NS_SUCCEEDED(rv) && !urlName.IsEmpty()) {
// Instantiating nsAutoConfig object if the pref is present
mAutoConfig = do_CreateInstance(NS_AUTOCONFIG_CONTRACTID, &rv);
if (NS_FAILED(rv))
return NS_ERROR_OUT_OF_MEMORY;
mAutoConfig = new nsAutoConfig();
rv = mAutoConfig->SetConfigURL(urlName.get());
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
rv = mAutoConfig->Init();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mAutoConfig->SetConfigURL(urlName.get());
}
return NS_OK;

View File

@ -6,14 +6,14 @@
#ifndef nsReadConfig_h
#define nsReadConfig_h
#include "nsCOMPtr.h"
#include "mozilla/RefPtr.h"
#include "nsIReadConfig.h"
#include "nsIAutoConfig.h"
#include "nsAutoConfig.h"
#include "nsIObserver.h"
class nsReadConfig : public nsIReadConfig,
public nsIObserver
class nsReadConfig final : public nsIReadConfig,
public nsIObserver
{
public:
@ -35,7 +35,7 @@ class nsReadConfig : public nsIReadConfig,
bool isEncoded, bool isBinDir);
bool mRead;
private:
nsCOMPtr<nsIAutoConfig> mAutoConfig;
RefPtr<nsAutoConfig> mAutoConfig;
};
#endif

View File

@ -23,15 +23,6 @@ LOCAL_INCLUDES += [
'/xpcom/base',
]
if CONFIG['LIBFUZZER']:
USE_LIBS += [
'fuzzer',
'mozglue'
]
LOCAL_INCLUDES += [
'/tools/fuzzing/libfuzzer',
]
# DELAYLOAD_DLLS in this block ensures that the DLL blocklist is functional
if CONFIG['OS_ARCH'] == 'WINNT':
DELAYLOAD_DLLS += [

View File

@ -31,13 +31,12 @@ DoWhileEmitter::emitBody(const Maybe<uint32_t>& doPos, const Maybe<uint32_t>& bo
return false;
}
// Emit an annotated nop so IonBuilder can recognize the 'do' loop.
if (!bce_->newSrcNote(SRC_WHILE, &noteIndex_))
return false;
// We need a nop here to make it possible to set a breakpoint on `do`.
if (!bce_->emit1(JSOP_NOP))
return false;
if (!bce_->newSrcNote(SRC_WHILE, &noteIndex2_))
// Emit an annotated nop so IonBuilder can recognize the 'do' loop.
if (!bce_->newSrcNote3(SRC_DO_WHILE, 0, 0, &noteIndex_))
return false;
loopInfo_.emplace(bce_, StatementKind::DoLoop);
@ -84,18 +83,13 @@ DoWhileEmitter::emitEnd()
// Update the annotations with the update and back edge positions, for
// IonBuilder.
//
// Be careful: We must set noteIndex2_ before_ noteIndex in case the
// noteIndex_ note gets bigger. Otherwise noteIndex2_ can point wrong
// position.
if (!bce_->setSrcNoteOffset(noteIndex2_, SrcNote::DoWhile2::BackJumpOffset,
loopInfo_->loopEndOffsetFromLoopHead()))
if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::DoWhile::CondOffset,
loopInfo_->continueTargetOffsetFromLoopHead()))
{
return false;
}
// +1 for NOP in emitBody.
if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::DoWhile1::CondOffset,
loopInfo_->continueTargetOffsetFromLoopHead() + 1))
if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::DoWhile::BackJumpOffset,
loopInfo_->loopEndOffsetFromLoopHead()))
{
return false;
}

View File

@ -35,10 +35,8 @@ class MOZ_STACK_CLASS DoWhileEmitter
{
BytecodeEmitter* bce_;
// The source note indices for 2 SRC_WHILE's.
// FIXME: Add SRC_DO_WHILE (bug 1477896).
// The source note index for SRC_DO_WHILE.
unsigned noteIndex_ = 0;
unsigned noteIndex2_ = 0;
mozilla::Maybe<LoopControl> loopInfo_;

View File

@ -64,23 +64,13 @@ class SrcNote {
Count,
};
};
// SRC_WHILE for do-while: Source note for JSOP_NOP at the top of do-while
// loop
// FIXME: Add SRC_DO_WHILE (bug 1477896).
class DoWhile1 {
// SRC_DO_WHILE: Source note for JSOP_LOOPHEAD at the top of do-while loop
class DoWhile {
public:
enum Fields {
// The offset of the condition ops from JSOP_NOP.
// The offset of the condition ops from JSOP_LOOPHEAD.
CondOffset,
Count,
};
};
// SRC_WHILE for do-while: Source note for JSOP_LOOPHEAD at the top of
// do-while loop
// FIXME: Add SRC_DO_WHILE (bug 1477896).
class DoWhile2 {
public:
enum Fields {
// The offset of JSOP_IFNE at the end of the loop from
// JSOP_LOOPHEAD.
BackJumpOffset,
@ -171,12 +161,6 @@ class SrcNote {
};
};
// FIXME: Add SRC_DO_WHILE (bug 1477896).
static_assert(unsigned(SrcNote::While::Count) == unsigned(SrcNote::DoWhile1::Count),
"SRC_WHILE can be shared between while and do-while");
static_assert(unsigned(SrcNote::While::Count) == unsigned(SrcNote::DoWhile2::Count),
"SRC_WHILE can be shared between while and do-while");
#define FOR_EACH_SRC_NOTE_TYPE(M) \
M(SRC_NULL, "null", 0) /* Terminates a note vector. */ \
M(SRC_IF, "if", 0) /* JSOP_IFEQ bytecode is from an if-then. */ \
@ -184,6 +168,7 @@ static_assert(unsigned(SrcNote::While::Count) == unsigned(SrcNote::DoWhile2::Cou
M(SRC_COND, "cond", 0) /* JSOP_IFEQ is from conditional ?: operator. */ \
M(SRC_FOR, "for", SrcNote::For::Count) \
M(SRC_WHILE, "while", SrcNote::While::Count) \
M(SRC_DO_WHILE, "do-while", SrcNote::DoWhile::Count) \
M(SRC_FOR_IN, "for-in", SrcNote::ForIn::Count) \
M(SRC_FOR_OF, "for-of", SrcNote::ForOf::Count) \
M(SRC_CONTINUE, "continue", 0) /* JSOP_GOTO is a continue. */ \
@ -201,7 +186,6 @@ static_assert(unsigned(SrcNote::While::Count) == unsigned(SrcNote::DoWhile2::Cou
M(SRC_COLSPAN, "colspan", SrcNote::ColSpan::Count) \
M(SRC_NEWLINE, "newline", 0) /* Bytecode follows a source newline. */ \
M(SRC_SETLINE, "setline", SrcNote::SetLine::Count) \
M(SRC_UNUSED21, "unused21", 0) /* Unused. */ \
M(SRC_UNUSED22, "unused22", 0) /* Unused. */ \
M(SRC_UNUSED23, "unused23", 0) /* Unused. */ \
M(SRC_XDELTA, "xdelta", 0) /* 24-31 are for extended delta notes. */

View File

@ -264,17 +264,8 @@ ControlFlowGenerator::snoopControlFlow(JSOp op)
switch (op) {
case JSOP_NOP: {
jssrcnote* sn = GetSrcNote(gsn, script, pc);
if (sn) {
// do { } while (cond)
if (SN_TYPE(sn) == SRC_WHILE)
return processDoWhileLoop(sn);
// Build a mapping such that given a basic block, whose successor
// has a phi
// for (; ; update?)
if (SN_TYPE(sn) == SRC_FOR)
return processForLoop(op, sn);
}
if (sn && SN_TYPE(sn) == SRC_FOR)
return processForLoop(op, sn);
break;
}
@ -312,6 +303,13 @@ ControlFlowGenerator::snoopControlFlow(JSOp op)
break;
}
case JSOP_LOOPHEAD: {
jssrcnote* sn = GetSrcNote(gsn, script, pc);
if (sn && SN_TYPE(sn) == SRC_DO_WHILE)
return processDoWhileLoop(sn);
break;
}
case JSOP_TABLESWITCH: {
jssrcnote* sn = GetSrcNote(gsn, script, pc);
return processTableSwitch(op, sn);
@ -1505,24 +1503,22 @@ ControlFlowGenerator::ControlStatus
ControlFlowGenerator::processDoWhileLoop(jssrcnote* sn)
{
// do { } while() loops have the following structure:
// NOP ; SRC_WHILE (offset to COND)
// LOOPHEAD ; SRC_WHILE (offset to IFNE)
// NOP
// LOOPHEAD ; SRC_DO_WHILE (offsets to COND and IFNE)
// LOOPENTRY
// ... ; body
// ...
// COND ; start of condition
// ...
// IFNE -> ; goes to LOOPHEAD
int condition_offset = GetSrcNoteOffset(sn, SrcNote::DoWhile1::CondOffset);
int condition_offset = GetSrcNoteOffset(sn, SrcNote::DoWhile::CondOffset);
jsbytecode* conditionpc = pc + condition_offset;
jssrcnote* sn2 = GetSrcNote(gsn, script, pc + 1);
int offset = GetSrcNoteOffset(sn2, SrcNote::DoWhile2::BackJumpOffset);
jsbytecode* ifne = pc + offset + 1;
int offset = GetSrcNoteOffset(sn, SrcNote::DoWhile::BackJumpOffset);
jsbytecode* ifne = pc + offset;
MOZ_ASSERT(ifne > pc);
// Verify that the IFNE goes back to a loophead op.
jsbytecode* loopHead = GetNextPc(pc);
jsbytecode* loopHead = pc;
MOZ_ASSERT(JSOp(*loopHead) == JSOP_LOOPHEAD);
MOZ_ASSERT(loopHead == ifne + GetJumpOffset(ifne));

View File

@ -667,7 +667,6 @@ bool
JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm, const VMFunction& f)
{
MOZ_ASSERT(functionWrappers_);
MOZ_ASSERT(functionWrappers_->initialized());
uint32_t wrapperOffset = startTrampolineCode(masm);

View File

@ -646,7 +646,6 @@ bool
JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm, const VMFunction& f)
{
MOZ_ASSERT(functionWrappers_);
MOZ_ASSERT(functionWrappers_->initialized());
uint32_t wrapperOffset = startTrampolineCode(masm);

View File

@ -2752,20 +2752,24 @@ SrcNotes(JSContext* cx, HandleScript script, Sprinter* sp)
}
break;
case SRC_WHILE:
case SRC_FOR_IN:
case SRC_FOR_OF:
static_assert(unsigned(SrcNote::ForIn::BackJumpOffset) == unsigned(SrcNote::ForOf::BackJumpOffset),
"SrcNote::{ForIn,ForOf}::BackJumpOffset should be same");
static_assert(unsigned(SrcNote::While::BackJumpOffset) == unsigned(SrcNote::ForIn::BackJumpOffset),
"SrcNote::{While,ForIn,ForOf}::BackJumpOffset should be same");
static_assert(unsigned(SrcNote::While::BackJumpOffset) == unsigned(SrcNote::ForOf::BackJumpOffset),
"SrcNote::{While,ForIn,ForOf}::BackJumpOffset should be same");
if (!sp->jsprintf(" backjump %u",
unsigned(GetSrcNoteOffset(sn, SrcNote::ForIn::BackJumpOffset))))
unsigned(GetSrcNoteOffset(sn, SrcNote::While::BackJumpOffset))))
{
return false;
}
break;
case SRC_WHILE:
if (!sp->jsprintf(" offset %u",
unsigned(GetSrcNoteOffset(sn, SrcNote::While::BackJumpOffset))))
case SRC_DO_WHILE:
if (!sp->jsprintf(" cond %u backjump %u",
unsigned(GetSrcNoteOffset(sn, SrcNote::DoWhile::CondOffset)),
unsigned(GetSrcNoteOffset(sn, SrcNote::DoWhile::BackJumpOffset))))
{
return false;
}

View File

@ -322,7 +322,7 @@ InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
HandleFunction callee, HandleObject envChain)
{
MOZ_ASSERT(callee->isGenerator() || callee->isAsync());
RootedScript script(cx, JSFunction::getOrCreateScript(cx, callee));
RootedScript script(cx, callee->nonLazyScript());
InterpreterFrame* prev = regs.fp();
jsbytecode* prevpc = regs.pc;
Value* prevsp = regs.sp;

View File

@ -289,11 +289,11 @@ public:
// Like putNew(), but should be only used when the table is known to be big
// enough for the insertion, and hashing cannot fail. Typically this is used
// to populate an empty map with known-unique keys after reserving space with
// init(), e.g.
// reserve(), e.g.
//
// using HM = HashMap<int,char>;
// HM h;
// if (!h.init(3)) {
// if (!h.reserve(3)) {
// MOZ_CRASH("OOM");
// }
// h.putNewInfallible(1, 'a'); // unique key
@ -603,11 +603,11 @@ public:
// Like putNew(), but should be only used when the table is known to be big
// enough for the insertion, and hashing cannot fail. Typically this is used
// to populate an empty set with known-unique elements after reserving space
// with init(), e.g.
// with reserve(), e.g.
//
// using HS = HashMap<int>;
// HS h;
// if (!h.init(3)) {
// if (!h.reserve(3)) {
// MOZ_CRASH("OOM");
// }
// h.putNewInfallible(1); // unique element
@ -1444,7 +1444,7 @@ public:
{
if (mRekeyed) {
mTable.mGen++;
mTable.checkOverRemoved();
mTable.infallibleRehashIfOverloaded();
}
if (mRemoved) {
@ -1636,17 +1636,6 @@ public:
return table;
}
static Entry* maybeCreateTable(AllocPolicy& aAllocPolicy, uint32_t aCapacity)
{
Entry* table = aAllocPolicy.template maybe_pod_malloc<Entry>(aCapacity);
if (table) {
for (uint32_t i = 0; i < aCapacity; i++) {
new (&table[i]) Entry();
}
}
return table;
}
static void destroyTable(AllocPolicy& aAllocPolicy,
Entry* aOldTable,
uint32_t aCapacity)
@ -1708,29 +1697,6 @@ private:
return (aHash1 - aDoubleHash.mHash2) & aDoubleHash.mSizeMask;
}
// True if the current load is equal to or exceeds the maximum.
bool overloaded()
{
static_assert(sMaxCapacity <= UINT32_MAX / sMaxAlphaNumerator,
"multiplication below could overflow");
// Note: if capacity() is zero, this will always succeed, which is
// what we want.
return mEntryCount + mRemovedCount >=
capacity() * sMaxAlphaNumerator / sAlphaDenominator;
}
// Would the table be underloaded if it had the given capacity and entryCount?
static bool wouldBeUnderloaded(uint32_t aCapacity, uint32_t aEntryCount)
{
static_assert(sMaxCapacity <= UINT32_MAX / sMinAlphaNumerator,
"multiplication below could overflow");
return aCapacity > sMinCapacity &&
aEntryCount <= aCapacity * sMinAlphaNumerator / sAlphaDenominator;
}
bool underloaded() { return wouldBeUnderloaded(capacity(), mEntryCount); }
static MOZ_ALWAYS_INLINE bool match(Entry& aEntry, const Lookup& aLookup)
{
return HashPolicy::match(HashPolicy::getKey(aEntry.get()), aLookup);
@ -1796,8 +1762,8 @@ private:
// This is a copy of lookup() hardcoded to the assumptions:
// 1. the lookup is for an add;
// 2. the key, whose |keyHash| has been passed is not in the table.
Entry& findFreeEntry(HashNumber aKeyHash)
// 2. the key, whose |keyHash| has been passed, is not in the table.
Entry& findNonLiveEntry(HashNumber aKeyHash)
{
MOZ_ASSERT(!(aKeyHash & sCollisionBit));
MOZ_ASSERT(mTable);
@ -1869,7 +1835,7 @@ private:
for (Entry* src = oldTable; src < end; ++src) {
if (src->isLive()) {
HashNumber hn = src->getKeyHash();
findFreeEntry(hn).setLive(
findNonLiveEntry(hn).setLive(
hn, std::move(const_cast<typename Entry::NonConstT&>(src->get())));
}
@ -1881,34 +1847,34 @@ private:
return Rehashed;
}
bool shouldCompressTable()
RebuildStatus rehashIfOverloaded(
FailureBehavior aReportFailure = ReportFailure)
{
static_assert(sMaxCapacity <= UINT32_MAX / sMaxAlphaNumerator,
"multiplication below could overflow");
// Note: if capacity() is zero, this will always succeed, which is
// what we want.
bool overloaded = mEntryCount + mRemovedCount >=
capacity() * sMaxAlphaNumerator / sAlphaDenominator;
if (!overloaded) {
return NotOverloaded;
}
// Succeed if a quarter or more of all entries are removed. Note that this
// always succeeds if capacity() == 0 (i.e. entry storage has not been
// allocated), which is what we want, because it means changeTableSize()
// will allocate the requested capacity rather than doubling it.
return mRemovedCount >= (capacity() >> 2);
}
RebuildStatus checkOverloaded(FailureBehavior aReportFailure = ReportFailure)
{
if (!overloaded()) {
return NotOverloaded;
}
uint32_t newCapacity = shouldCompressTable()
? rawCapacity()
: rawCapacity() * 2;
bool manyRemoved = mRemovedCount >= (capacity() >> 2);
uint32_t newCapacity = manyRemoved ? rawCapacity() : rawCapacity() * 2;
return changeTableSize(newCapacity, aReportFailure);
}
// Infallibly rehash the table if we are overloaded with removals.
void checkOverRemoved()
void infallibleRehashIfOverloaded()
{
if (overloaded()) {
if (checkOverloaded(DontReportFailure) == RehashFailed) {
rehashTableInPlace();
}
if (rehashIfOverloaded(DontReportFailure) == RehashFailed) {
rehashTableInPlace();
}
}
@ -1928,9 +1894,15 @@ private:
#endif
}
void checkUnderloaded()
void shrinkIfUnderloaded()
{
if (underloaded()) {
static_assert(sMaxCapacity <= UINT32_MAX / sMinAlphaNumerator,
"multiplication below could overflow");
bool underloaded =
capacity() > sMinCapacity &&
mEntryCount <= capacity() * sMinAlphaNumerator / sAlphaDenominator;
if (underloaded) {
(void)changeTableSize(capacity() / 2, DontReportFailure);
}
}
@ -1989,7 +1961,7 @@ private:
MOZ_ASSERT(mTable);
HashNumber keyHash = prepareHash(aLookup);
Entry* entry = &findFreeEntry(keyHash);
Entry* entry = &findNonLiveEntry(keyHash);
MOZ_ASSERT(entry);
if (entry->isRemoved()) {
@ -2019,7 +1991,7 @@ public:
}
// Resize the table down to the smallest capacity that doesn't overload the
// table. Since we call checkUnderloaded() on every remove, you only need
// table. Since we call shrinkIfUnderloaded() on every remove, you only need
// to call this after a bulk removal of items done without calling remove().
void compact()
{
@ -2180,7 +2152,7 @@ public:
aPtr.mKeyHash |= sCollisionBit;
} else {
// Preserve the validity of |aPtr.mEntry|.
RebuildStatus status = checkOverloaded();
RebuildStatus status = rehashIfOverloaded();
if (status == RehashFailed) {
return false;
}
@ -2188,7 +2160,7 @@ public:
return false;
}
if (status == Rehashed) {
aPtr.mEntry = &findFreeEntry(aPtr.mKeyHash);
aPtr.mEntry = &findNonLiveEntry(aPtr.mKeyHash);
}
}
@ -2223,7 +2195,7 @@ public:
if (!EnsureHash<HashPolicy>(aLookup)) {
return false;
}
if (checkOverloaded() == RehashFailed) {
if (rehashIfOverloaded() == RehashFailed) {
return false;
}
putNewInfallible(aLookup, std::forward<Args>(aArgs)...);
@ -2261,7 +2233,7 @@ public:
MOZ_ASSERT(aPtr.found());
MOZ_ASSERT(aPtr.mGeneration == generation());
remove(*aPtr.mEntry);
checkUnderloaded();
shrinkIfUnderloaded();
}
void rekeyWithoutRehash(Ptr aPtr, const Lookup& aLookup, const Key& aKey)
@ -2279,7 +2251,7 @@ public:
void rekeyAndMaybeRehash(Ptr aPtr, const Lookup& aLookup, const Key& aKey)
{
rekeyWithoutRehash(aPtr, aLookup, aKey);
checkOverRemoved();
infallibleRehashIfOverloaded();
}
};

View File

@ -46,12 +46,6 @@
#endif
extern "C" {
/* workaround for bug 1306642 */
#if defined(_MSC_VER) && defined(__clang__)
#pragma clang diagnostic warning "-Wdll-attribute-on-redeclaration"
#pragma clang diagnostic warning "-Winconsistent-dllimport"
#endif
/* These definitions are usually provided through the
* sanitizer/asan_interface.h header installed by ASan.
*/

View File

@ -247,6 +247,37 @@ public final class GeckoRuntimeSettings implements Parcelable {
mSettings.mDisplayDensityOverride = density;
return this;
}
/** Set whether or not known malware sites should be blocked.
*
* Note: For each blocked site, {@link NavigationDelegate#onLoadError}
* with error category {@link NavigationDelegate#ERROR_CATEGORY_SAFEBROWSING}
* is called.
*
* @param enabled A flag determining whether or not to block malware
* sites.
* @return The builder instance.
*/
public @NonNull Builder blockMalware(boolean enabled) {
mSettings.mSafebrowsingMalware.set(enabled);
return this;
}
/**
* Set whether or not known phishing sites should be blocked.
*
* Note: For each blocked site, {@link NavigationDelegate#onLoadError}
* with error category {@link NavigationDelegate#ERROR_CATEGORY_SAFEBROWSING}
* is called.
*
* @param enabled A flag determining whether or not to block phishing
* sites.
* @return The builder instance.
*/
public @NonNull Builder blockPhishing(boolean enabled) {
mSettings.mSafebrowsingPhishing.set(enabled);
return this;
}
}
/* package */ GeckoRuntime runtime;
@ -305,6 +336,10 @@ public final class GeckoRuntimeSettings implements Parcelable {
TrackingProtectionDelegate.CATEGORY_AD));
/* package */ Pref<Boolean> mConsoleOutput = new Pref<Boolean>(
"geckoview.console.enabled", false);
/* package */ Pref<Boolean> mSafebrowsingMalware = new Pref<Boolean>(
"browser.safebrowsing.malware.enabled", true);
/* package */ Pref<Boolean> mSafebrowsingPhishing = new Pref<Boolean>(
"browser.safebrowsing.phishing.enabled", true);
/* package */ boolean mNativeCrashReporting;
/* package */ boolean mJavaCrashReporting;
@ -314,7 +349,8 @@ public final class GeckoRuntimeSettings implements Parcelable {
private final Pref<?>[] mPrefs = new Pref<?>[] {
mCookieBehavior, mCookieLifetime, mConsoleOutput,
mJavaScript, mRemoteDebugging, mTrackingProtection, mWebFonts
mJavaScript, mRemoteDebugging, mSafebrowsingMalware,
mSafebrowsingPhishing, mTrackingProtection, mWebFonts,
};
/* package */ GeckoRuntimeSettings() {
@ -623,12 +659,60 @@ public final class GeckoRuntimeSettings implements Parcelable {
/**
* Get whether or not web console messages are sent to logcat.
*
* @return This GeckoRuntimeSettings instance.
* @return True if console output is enabled.
*/
public boolean getConsoleOutputEnabled() {
return mConsoleOutput.get();
}
/**
* Set whether or not known malware sites should be blocked.
*
* Note: For each blocked site, {@link NavigationDelegate#onLoadError}
* with error category {@link NavigationDelegate#ERROR_CATEGORY_SAFEBROWSING}
* is called.
*
* @param enabled A flag determining whether or not to block malware sites.
* @return The GeckoRuntimeSettings instance.
*/
public @NonNull GeckoRuntimeSettings setBlockMalware(boolean enabled) {
mSafebrowsingMalware.set(enabled);
return this;
}
/**
* Get whether or not known malware sites are blocked.
*
* @return True if malware site blocking is enabled.
*/
public boolean getBlockMalware() {
return mSafebrowsingMalware.get();
}
/**
* Set whether or not known phishing sites should be blocked.
*
* Note: For each blocked site, {@link NavigationDelegate#onLoadError}
* with error category {@link NavigationDelegate#ERROR_CATEGORY_SAFEBROWSING}
* is called.
*
* @param enabled A flag determining whether or not to block phishing sites.
* @return The GeckoRuntimeSettings instance.
*/
public @NonNull GeckoRuntimeSettings setBlockPhishing(boolean enabled) {
mSafebrowsingPhishing.set(enabled);
return this;
}
/**
* Get whether or not known phishing sites are blocked.
*
* @return True if phishing site blocking is enabled.
*/
public boolean getBlockPhishing() {
return mSafebrowsingPhishing.get();
}
@Override // Parcelable
public int describeContents() {
return 0;

View File

@ -7,19 +7,13 @@
var EXPORTED_SYMBOLS = ["GeckoViewSettings"];
ChromeUtils.import("resource://gre/modules/GeckoViewModule.jsm");
ChromeUtils.import("resource://gre/modules/GeckoViewUtils.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetters(this, {
SafeBrowsing: "resource://gre/modules/SafeBrowsing.jsm",
Services: "resource://gre/modules/Services.jsm",
});
/* global SafeBrowsing:false */
GeckoViewUtils.addLazyGetter(this, "SafeBrowsing", {
module: "resource://gre/modules/SafeBrowsing.jsm",
init: sb => sb.init(),
});
XPCOMUtils.defineLazyGetter(
this, "DESKTOP_USER_AGENT",
function() {
@ -42,6 +36,8 @@ class GeckoViewSettings extends GeckoViewModule {
onInit() {
this._useTrackingProtection = false;
this._useDesktopMode = false;
// Required for safe browsing and tracking protection.
SafeBrowsing.init();
}
onSettingsUpdate() {
@ -49,7 +45,6 @@ class GeckoViewSettings extends GeckoViewModule {
debug `onSettingsUpdate: ${settings}`;
this.displayMode = settings.displayMode;
this.useTrackingProtection = !!settings.useTrackingProtection;
this.useDesktopMode = !!settings.useDesktopMode;
}
@ -57,15 +52,6 @@ class GeckoViewSettings extends GeckoViewModule {
return this.browser.isRemoteBrowser;
}
get useTrackingProtection() {
return this._useTrackingProtection;
}
set useTrackingProtection(aUse) {
aUse && SafeBrowsing;
this._useTrackingProtection = aUse;
}
onUserAgentRequest(aSubject, aTopic, aData) {
debug `onUserAgentRequest`;

View File

@ -1374,7 +1374,7 @@ pref("dom.event.highrestimestamp.enabled", true);
pref("dom.event.coalesce_mouse_move", true);
#if defined(NIGHTLY_BUILD) && !defined(ANDROID)
pref("dom.ua_widget.enabled", true);
pref("dom.ua_widget.enabled", false);
#else
pref("dom.ua_widget.enabled", false);
#endif

View File

@ -9,6 +9,7 @@
#include "mozilla/Move.h"
#include "SandboxLogging.h"
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

View File

@ -170,57 +170,6 @@ android-x86/opt:
- linux64-sccache
- linux64-node
android-x86-fuzzing/debug:
description: "Android x86 Fuzzing Debug"
index:
product: mobile
job-name: android-x86-fuzzing-debug
treeherder:
platform: android-4-2-x86/debug
symbol: Bf
worker-type: aws-provisioner-v1/gecko-{level}-b-android
worker:
docker-image: {in-tree: android-build}
max-run-time: 7200
env:
GRADLE_USER_HOME: "/builds/worker/workspace/build/src/mobile/android/gradle/dotgradle-offline"
TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android-x86/releng.manifest"
artifacts:
- name: public/android/R
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/app/R
type: directory
- name: public/android/maven
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/maven/
type: directory
- name: public/build/geckoview-androidTest.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview/outputs/apk/androidTest/officialWithGeckoBinariesNoMinApi/debug/geckoview-official-withGeckoBinaries-noMinApi-debug-androidTest.apk
type: file
- name: public/build/geckoview_example.apk
path: /builds/worker/workspace/build/src/obj-firefox/gradle/build/mobile/android/geckoview_example/outputs/apk/officialWithGeckoBinariesNoMinApi/debug/geckoview_example-official-withGeckoBinaries-noMinApi-debug.apk
type: file
- name: public/build
path: /builds/worker/artifacts/
type: directory
run:
using: mozharness
actions: [get-secrets build multi-l10n update]
config:
- builds/releng_base_android_64_builds.py
script: "mozharness/scripts/fx_desktop_build.py"
secrets: true
custom-build-variant-cfg: x86-fuzzing-debug
tooltool-downloads: internal
toolchains:
- android-gradle-dependencies
- android-ndk-linux
- android-sdk-linux
- linux64-clang
- linux64-rust-android
- linux64-rust-size
- linux64-cbindgen
- linux64-sccache
- linux64-node
android-x86-nightly/opt:
description: "Android 4.2 x86 Nightly"
attributes:

View File

@ -225,4 +225,4 @@ channel on irc.mozilla.org. Dont ask if you can ask a question, just
ask, and please wait for an answer as we might not be in your timezone.
[subscribe]: https://lists.mozilla.org/listinfo/tools-marionette
[archive]: https://groups.google.com/group/mozilla.tools.marionette
[archive]: https://lists.mozilla.org/pipermail/tools-marionette/

View File

@ -649,4 +649,4 @@ There is also an IRC channel to talk about using and developing
geckodriver in #ateam on irc.mozilla.org.
[subscribe]: https://lists.mozilla.org/listinfo/tools-marionette
[archive]: https://groups.google.com/group/mozilla.tools.marionette
[archive]: https://lists.mozilla.org/pipermail/tools-marionette/

View File

@ -67,4 +67,4 @@ channel on irc.mozilla.org. Dont ask if you may ask a question; just go ahea
and ask, and please wait for an answer as we might not be in your timezone.
.. _subscribe: https://lists.mozilla.org/listinfo/tools-marionette
.. _archive: https://groups.google.com/group/mozilla.tools.marionette
.. _archive: https://lists.mozilla.org/pipermail/tools-marionette/

View File

@ -118,6 +118,11 @@ XPCOMUtils.defineLazyGetter(FileTestUtils, "_globalTemporaryDirectory",
for (let path of gPathsToRemove) {
await this.tolerantRemove(path);
}
if (!(await OS.File.exists(dir.path))) {
return;
}
// Detect any extra files, like the ".part" files of downloads.
let iterator = new OS.File.DirectoryIterator(dir.path);
try {

Some files were not shown because too many files have changed in this diff Show More