зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central. r=merge a=merge
MozReview-Commit-ID: BGCq2q6xO1S
This commit is contained in:
Коммит
a3b6b15cef
|
@ -601,9 +601,13 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
||||||
if (!mDocument)
|
if (!mDocument)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Wait until an update, we have started, or an interruptible reflow is
|
||||||
|
// finished.
|
||||||
if (mObservingState == eRefreshProcessing ||
|
if (mObservingState == eRefreshProcessing ||
|
||||||
mObservingState == eRefreshProcessingForUpdate)
|
mObservingState == eRefreshProcessingForUpdate ||
|
||||||
|
mPresShell->IsReflowInterrupted()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Any generic notifications should be queued if we're processing content
|
// Any generic notifications should be queued if we're processing content
|
||||||
// insertions or generic notifications.
|
// insertions or generic notifications.
|
||||||
|
|
|
@ -87,6 +87,8 @@ RootAccessibleWrap::GetInternalUnknown()
|
||||||
void
|
void
|
||||||
RootAccessibleWrap::DocumentActivated(DocAccessible* aDocument)
|
RootAccessibleWrap::DocumentActivated(DocAccessible* aDocument)
|
||||||
{
|
{
|
||||||
|
// This check will never work with e10s enabled, in other words, as of
|
||||||
|
// Firefox 57.
|
||||||
if (Compatibility::IsDolphin() &&
|
if (Compatibility::IsDolphin() &&
|
||||||
nsCoreUtils::IsTabDocument(aDocument->DocumentNode())) {
|
nsCoreUtils::IsTabDocument(aDocument->DocumentNode())) {
|
||||||
uint32_t count = mChildDocuments.Length();
|
uint32_t count = mChildDocuments.Length();
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
pref("startup.homepage_override_url", "");
|
pref("startup.homepage_override_url", "");
|
||||||
pref("startup.homepage_welcome_url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/firstrun/");
|
pref("startup.homepage_welcome_url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%a2/firstrun/");
|
||||||
pref("startup.homepage_welcome_url.additional", "");
|
pref("startup.homepage_welcome_url.additional", "");
|
||||||
// The time interval between checks for a new version (in seconds)
|
// The time interval between checks for a new version (in seconds)
|
||||||
pref("app.update.interval", 28800); // 8 hours
|
pref("app.update.interval", 28800); // 8 hours
|
||||||
|
|
|
@ -12,6 +12,10 @@ var Cu = Components.utils;
|
||||||
const DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC =
|
const DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC =
|
||||||
"distribution-customization-complete";
|
"distribution-customization-complete";
|
||||||
|
|
||||||
|
const PREF_CACHED_FILE_EXISTENCE = "distribution.iniFile.exists.value";
|
||||||
|
const PREF_CACHED_FILE_APPVERSION = "distribution.iniFile.exists.appversion";
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
|
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
|
||||||
|
@ -20,37 +24,65 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||||
"resource://gre/modules/PlacesUtils.jsm");
|
"resource://gre/modules/PlacesUtils.jsm");
|
||||||
|
|
||||||
this.DistributionCustomizer = function DistributionCustomizer() {
|
this.DistributionCustomizer = function DistributionCustomizer() {
|
||||||
// For parallel xpcshell testing purposes allow loading the distribution.ini
|
|
||||||
// file from the profile folder through an hidden pref.
|
|
||||||
let loadFromProfile = Services.prefs.getBoolPref("distribution.testing.loadFromProfile", false);
|
|
||||||
let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
|
||||||
getService(Ci.nsIProperties);
|
|
||||||
try {
|
|
||||||
let iniFile = loadFromProfile ? dirSvc.get("ProfD", Ci.nsIFile)
|
|
||||||
: dirSvc.get("XREAppDist", Ci.nsIFile);
|
|
||||||
if (loadFromProfile) {
|
|
||||||
iniFile.leafName = "distribution";
|
|
||||||
}
|
|
||||||
iniFile.append("distribution.ini");
|
|
||||||
if (iniFile.exists())
|
|
||||||
this._iniFile = iniFile;
|
|
||||||
} catch (ex) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DistributionCustomizer.prototype = {
|
DistributionCustomizer.prototype = {
|
||||||
_iniFile: null,
|
get _iniFile() {
|
||||||
|
// For parallel xpcshell testing purposes allow loading the distribution.ini
|
||||||
|
// file from the profile folder through an hidden pref.
|
||||||
|
let loadFromProfile = Services.prefs.getBoolPref("distribution.testing.loadFromProfile", false);
|
||||||
|
let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
||||||
|
getService(Ci.nsIProperties);
|
||||||
|
|
||||||
|
let iniFile;
|
||||||
|
try {
|
||||||
|
iniFile = loadFromProfile ? dirSvc.get("ProfD", Ci.nsIFile)
|
||||||
|
: dirSvc.get("XREAppDist", Ci.nsIFile);
|
||||||
|
if (loadFromProfile) {
|
||||||
|
iniFile.leafName = "distribution";
|
||||||
|
}
|
||||||
|
iniFile.append("distribution.ini");
|
||||||
|
} catch (ex) {}
|
||||||
|
|
||||||
|
this.__defineGetter__("_iniFile", () => iniFile);
|
||||||
|
return iniFile;
|
||||||
|
},
|
||||||
|
|
||||||
|
get _hasDistributionIni() {
|
||||||
|
if (Services.prefs.prefHasUserValue(PREF_CACHED_FILE_EXISTENCE)) {
|
||||||
|
let knownForVersion = Services.prefs.getStringPref(PREF_CACHED_FILE_APPVERSION, "unknown");
|
||||||
|
if (knownForVersion == AppConstants.MOZ_APP_VERSION) {
|
||||||
|
return Services.prefs.getBoolPref(PREF_CACHED_FILE_EXISTENCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let fileExists = this._iniFile.exists();
|
||||||
|
Services.prefs.setBoolPref(PREF_CACHED_FILE_EXISTENCE, fileExists);
|
||||||
|
Services.prefs.setStringPref(PREF_CACHED_FILE_APPVERSION, AppConstants.MOZ_APP_VERSION);
|
||||||
|
|
||||||
|
this.__defineGetter__("_hasDistributionIni", () => fileExists);
|
||||||
|
return fileExists;
|
||||||
|
},
|
||||||
|
|
||||||
get _ini() {
|
get _ini() {
|
||||||
let ini = null;
|
let ini = null;
|
||||||
try {
|
try {
|
||||||
if (this._iniFile) {
|
if (this._hasDistributionIni) {
|
||||||
ini = Cc["@mozilla.org/xpcom/ini-parser-factory;1"].
|
ini = Cc["@mozilla.org/xpcom/ini-parser-factory;1"].
|
||||||
getService(Ci.nsIINIParserFactory).
|
getService(Ci.nsIINIParserFactory).
|
||||||
createINIParser(this._iniFile);
|
createINIParser(this._iniFile);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Unable to parse INI.
|
if (e.result == Cr.NS_ERROR_FILE_NOT_FOUND) {
|
||||||
Cu.reportError("Unable to parse distribution.ini");
|
// We probably had cached the file existence as true,
|
||||||
|
// but it no longer exists. We could set the new cache
|
||||||
|
// value here, but let's just invalidate the cache and
|
||||||
|
// let it be cached by a single code path on the next check.
|
||||||
|
Services.prefs.clearUserPref(PREF_CACHED_FILE_EXISTENCE);
|
||||||
|
} else {
|
||||||
|
// Unable to parse INI.
|
||||||
|
Cu.reportError("Unable to parse distribution.ini");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.__defineGetter__("_ini", () => ini);
|
this.__defineGetter__("_ini", () => ini);
|
||||||
return this._ini;
|
return this._ini;
|
||||||
|
|
|
@ -86,6 +86,7 @@ do_register_cleanup(function() {
|
||||||
distDir.append("distribution");
|
distDir.append("distribution");
|
||||||
distDir.remove(true);
|
distDir.remove(true);
|
||||||
Assert.ok(!distDir.exists());
|
Assert.ok(!distDir.exists());
|
||||||
|
Services.prefs.clearUserPref("distribution.testing.loadFromProfile");
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function() {
|
add_task(async function() {
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that DistributionCustomizer correctly caches the existence
|
||||||
|
* of the distribution.ini file and just rechecks it after a version
|
||||||
|
* update.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const PREF_CACHED_FILE_EXISTENCE = "distribution.iniFile.exists.value";
|
||||||
|
const PREF_CACHED_FILE_APPVERSION = "distribution.iniFile.exists.appversion";
|
||||||
|
const PREF_LOAD_FROM_PROFILE = "distribution.testing.loadFromProfile";
|
||||||
|
|
||||||
|
const gTestDir = do_get_cwd();
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||||
|
|
||||||
|
add_task(async function() {
|
||||||
|
// Start with a clean slate of the prefs that control this feature.
|
||||||
|
Services.prefs.clearUserPref(PREF_CACHED_FILE_APPVERSION);
|
||||||
|
Services.prefs.clearUserPref(PREF_CACHED_FILE_EXISTENCE);
|
||||||
|
setupTest();
|
||||||
|
|
||||||
|
let {DistributionCustomizer} = Cu.import("resource:///modules/distribution.js", {});
|
||||||
|
let distribution = new DistributionCustomizer();
|
||||||
|
|
||||||
|
copyDistributionToProfile();
|
||||||
|
|
||||||
|
// Check that checking for distribution.ini returns the right value and sets up
|
||||||
|
// the cached prefs.
|
||||||
|
let exists = distribution._hasDistributionIni;
|
||||||
|
|
||||||
|
Assert.ok(exists);
|
||||||
|
Assert.equal(Services.prefs.getBoolPref(PREF_CACHED_FILE_EXISTENCE, undefined),
|
||||||
|
true);
|
||||||
|
Assert.equal(Services.prefs.getStringPref(PREF_CACHED_FILE_APPVERSION, "unknown"),
|
||||||
|
AppConstants.MOZ_APP_VERSION);
|
||||||
|
|
||||||
|
// Check that calling _hasDistributionIni again will use the cached value. We do
|
||||||
|
// this by deleting the file and expecting it to still return true instead of false.
|
||||||
|
// Also, we need to delete _hasDistributionIni from the object because the getter
|
||||||
|
// was replaced with a stored value.
|
||||||
|
deleteDistribution();
|
||||||
|
delete distribution._hasDistributionIni;
|
||||||
|
|
||||||
|
exists = distribution._hasDistributionIni;
|
||||||
|
Assert.ok(exists);
|
||||||
|
|
||||||
|
// Now let's invalidate the PREF_CACHED_FILE_EXISTENCE pref to make sure the
|
||||||
|
// value gets recomputed correctly.
|
||||||
|
Services.prefs.clearUserPref(PREF_CACHED_FILE_EXISTENCE);
|
||||||
|
delete distribution._hasDistributionIni;
|
||||||
|
exists = distribution._hasDistributionIni;
|
||||||
|
|
||||||
|
// It now should return false, as well as storing false in the pref.
|
||||||
|
Assert.ok(!exists);
|
||||||
|
Assert.equal(Services.prefs.getBoolPref(PREF_CACHED_FILE_EXISTENCE, undefined),
|
||||||
|
false);
|
||||||
|
|
||||||
|
// Check now that it will use the new cached value instead of returning true in
|
||||||
|
// the presence of the file.
|
||||||
|
copyDistributionToProfile();
|
||||||
|
delete distribution._hasDistributionIni;
|
||||||
|
exists = distribution._hasDistributionIni;
|
||||||
|
|
||||||
|
Assert.ok(!exists);
|
||||||
|
|
||||||
|
// Now let's do the same, but invalidating the App Version, as if a version
|
||||||
|
// update occurred.
|
||||||
|
Services.prefs.setStringPref(PREF_CACHED_FILE_APPVERSION, "older version");
|
||||||
|
delete distribution._hasDistributionIni;
|
||||||
|
exists = distribution._hasDistributionIni;
|
||||||
|
|
||||||
|
Assert.ok(exists);
|
||||||
|
Assert.equal(Services.prefs.getBoolPref(PREF_CACHED_FILE_EXISTENCE, undefined),
|
||||||
|
true);
|
||||||
|
Assert.equal(Services.prefs.getStringPref(PREF_CACHED_FILE_APPVERSION, "unknown"),
|
||||||
|
AppConstants.MOZ_APP_VERSION);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper functions
|
||||||
|
*/
|
||||||
|
function copyDistributionToProfile() {
|
||||||
|
// Copy distribution.ini file to the profile dir.
|
||||||
|
let distroDir = gProfD.clone();
|
||||||
|
distroDir.leafName = "distribution";
|
||||||
|
let iniFile = distroDir.clone();
|
||||||
|
iniFile.append("distribution.ini");
|
||||||
|
if (iniFile.exists()) {
|
||||||
|
iniFile.remove(false);
|
||||||
|
print("distribution.ini already exists, did some test forget to cleanup?");
|
||||||
|
}
|
||||||
|
|
||||||
|
let testDistributionFile = gTestDir.clone();
|
||||||
|
testDistributionFile.append("distribution.ini");
|
||||||
|
testDistributionFile.copyTo(distroDir, "distribution.ini");
|
||||||
|
Assert.ok(testDistributionFile.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteDistribution() {
|
||||||
|
let distroDir = gProfD.clone();
|
||||||
|
distroDir.leafName = "distribution";
|
||||||
|
let iniFile = distroDir.clone();
|
||||||
|
iniFile.append("distribution.ini");
|
||||||
|
iniFile.remove(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupTest() {
|
||||||
|
// Set special pref to load distribution.ini from the profile folder.
|
||||||
|
Services.prefs.setBoolPref(PREF_LOAD_FROM_PROFILE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
do_register_cleanup(function() {
|
||||||
|
deleteDistribution();
|
||||||
|
Services.prefs.clearUserPref(PREF_LOAD_FROM_PROFILE);
|
||||||
|
});
|
|
@ -6,5 +6,6 @@ support-files =
|
||||||
distribution.ini
|
distribution.ini
|
||||||
data/engine-de-DE.xml
|
data/engine-de-DE.xml
|
||||||
|
|
||||||
[test_distribution.js]
|
|
||||||
[test_browserGlue_migration_loop_cleanup.js]
|
[test_browserGlue_migration_loop_cleanup.js]
|
||||||
|
[test_distribution.js]
|
||||||
|
[test_distribution_cachedexistence.js]
|
||||||
|
|
|
@ -175,7 +175,7 @@ PluginContent.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
_getPluginInfo(pluginElement) {
|
_getPluginInfo(pluginElement) {
|
||||||
if (pluginElement instanceof Ci.nsIDOMHTMLAnchorElement) {
|
if (ChromeUtils.getClassName(pluginElement) === "HTMLAnchorElement") {
|
||||||
// Anchor elements are our place holders, and we only have them for Flash
|
// Anchor elements are our place holders, and we only have them for Flash
|
||||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||||
return {
|
return {
|
||||||
|
@ -649,7 +649,7 @@ PluginContent.prototype = {
|
||||||
let doc = plugin.ownerDocument;
|
let doc = plugin.ownerDocument;
|
||||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||||
let permissionString;
|
let permissionString;
|
||||||
if (plugin instanceof Ci.nsIDOMHTMLAnchorElement) {
|
if (ChromeUtils.getClassName(plugin) === "HTMLAnchorElement") {
|
||||||
// We only have replacement content for Flash installs
|
// We only have replacement content for Flash installs
|
||||||
permissionString = pluginHost.getPermissionStringForType(FLASH_MIME_TYPE);
|
permissionString = pluginHost.getPermissionStringForType(FLASH_MIME_TYPE);
|
||||||
} else {
|
} else {
|
||||||
|
@ -681,10 +681,9 @@ PluginContent.prototype = {
|
||||||
onOverlayClick(event) {
|
onOverlayClick(event) {
|
||||||
let document = event.target.ownerDocument;
|
let document = event.target.ownerDocument;
|
||||||
let plugin = document.getBindingParent(event.target);
|
let plugin = document.getBindingParent(event.target);
|
||||||
let contentWindow = plugin.ownerGlobal.top;
|
|
||||||
let overlay = this.getPluginUI(plugin, "main");
|
let overlay = this.getPluginUI(plugin, "main");
|
||||||
// Have to check that the target is not the link to update the plugin
|
// Have to check that the target is not the link to update the plugin
|
||||||
if (!(event.originalTarget instanceof contentWindow.HTMLAnchorElement) &&
|
if (!(ChromeUtils.getClassName(event.originalTarget) === "HTMLAnchorElement") &&
|
||||||
(event.originalTarget.getAttribute("anonid") != "closeIcon") &&
|
(event.originalTarget.getAttribute("anonid") != "closeIcon") &&
|
||||||
!overlay.hasAttribute("dismissed") &&
|
!overlay.hasAttribute("dismissed") &&
|
||||||
event.button == 0 &&
|
event.button == 0 &&
|
||||||
|
@ -730,7 +729,7 @@ PluginContent.prototype = {
|
||||||
}
|
}
|
||||||
if (pluginInfo.permissionString == pluginHost.getPermissionStringForType(plugin.actualType)) {
|
if (pluginInfo.permissionString == pluginHost.getPermissionStringForType(plugin.actualType)) {
|
||||||
let overlay = this.getPluginUI(plugin, "main");
|
let overlay = this.getPluginUI(plugin, "main");
|
||||||
if (plugin instanceof Ci.nsIDOMHTMLAnchorElement) {
|
if (ChromeUtils.getClassName(plugin) === "HTMLAnchorElement") {
|
||||||
placeHolderFound = true;
|
placeHolderFound = true;
|
||||||
} else {
|
} else {
|
||||||
pluginFound = true;
|
pluginFound = true;
|
||||||
|
|
|
@ -39,8 +39,6 @@
|
||||||
|
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
|
|
||||||
const DEFAULT_HTTP_VERSION = "HTTP/1.1";
|
|
||||||
|
|
||||||
const Curl = {
|
const Curl = {
|
||||||
/**
|
/**
|
||||||
* Generates a cURL command string which can be used from the command line etc.
|
* Generates a cURL command string which can be used from the command line etc.
|
||||||
|
@ -106,11 +104,6 @@ const Curl = {
|
||||||
command.push("-I");
|
command.push("-I");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add http version.
|
|
||||||
if (data.httpVersion && data.httpVersion != DEFAULT_HTTP_VERSION) {
|
|
||||||
command.push("--" + data.httpVersion.split("/")[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add request headers.
|
// Add request headers.
|
||||||
let headers = data.headers;
|
let headers = data.headers;
|
||||||
if (multipartRequest) {
|
if (multipartRequest) {
|
||||||
|
|
|
@ -747,4 +747,3 @@ var WasmDisassembler = (function () {
|
||||||
return WasmDisassembler;
|
return WasmDisassembler;
|
||||||
}());
|
}());
|
||||||
exports.WasmDisassembler = WasmDisassembler;
|
exports.WasmDisassembler = WasmDisassembler;
|
||||||
//# sourceMappingURL=WasmDis.js.map
|
|
|
@ -1400,4 +1400,3 @@ if (!exports.bytesToString) {
|
||||||
return decodeURIComponent(escape(str));
|
return decodeURIComponent(escape(str));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
//# sourceMappingURL=WasmParser.js.map
|
|
|
@ -77,80 +77,79 @@ ObjectActor.prototype = {
|
||||||
* Returns a grip for this actor for returning in a protocol message.
|
* Returns a grip for this actor for returning in a protocol message.
|
||||||
*/
|
*/
|
||||||
grip: function () {
|
grip: function () {
|
||||||
this.hooks.incrementGripDepth();
|
|
||||||
|
|
||||||
let g = {
|
let g = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"actor": this.actorID
|
"actor": this.actorID
|
||||||
};
|
};
|
||||||
|
|
||||||
// If it's a proxy, lie and tell that it belongs to an invented "Proxy" class.
|
// Check if the object has a wrapper which denies access. It may be a CPOW or a
|
||||||
// The `isProxy` function detects them even behind non-opaque security wrappers,
|
// security wrapper. Change the class so that this will be visible in the UI.
|
||||||
// which is useful to avoid running proxy traps through transparent wrappers.
|
let unwrapped = unwrap(this.obj);
|
||||||
if (isProxy(this.obj)) {
|
if (!unwrapped) {
|
||||||
|
if (DevToolsUtils.isCPOW(this.obj)) {
|
||||||
|
g.class = "CPOW: " + g.class;
|
||||||
|
} else {
|
||||||
|
g.class = "Inaccessible";
|
||||||
|
}
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dead objects also deny access.
|
||||||
|
if (this.obj.class == "DeadObject") {
|
||||||
|
g.class = "DeadObject";
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, increment grip depth and attempt to create a preview.
|
||||||
|
this.hooks.incrementGripDepth();
|
||||||
|
|
||||||
|
// The `isProxy` getter is called on `unwrapped` instead of `this.obj` in order
|
||||||
|
// to detect proxies behind transparent wrappers, and thus avoid running traps.
|
||||||
|
if (unwrapped.isProxy) {
|
||||||
g.class = "Proxy";
|
g.class = "Proxy";
|
||||||
} else {
|
} else {
|
||||||
try {
|
g.class = this.obj.class;
|
||||||
g.class = this.obj.class;
|
g.extensible = this.obj.isExtensible();
|
||||||
g.extensible = this.obj.isExtensible();
|
g.frozen = this.obj.isFrozen();
|
||||||
g.frozen = this.obj.isFrozen();
|
g.sealed = this.obj.isSealed();
|
||||||
g.sealed = this.obj.isSealed();
|
|
||||||
} catch (e) {
|
|
||||||
// Handle cases where the underlying object's calls to isExtensible, etc throw.
|
|
||||||
// This is possible with ProxyObjects like CPOWs. Note these are different from
|
|
||||||
// scripted Proxies created via `new Proxy`, which match isProxy(this.obj) above.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changing the class so that CPOWs will be visible in the UI
|
if (g.class == "Promise") {
|
||||||
let isCPOW = DevToolsUtils.isCPOW(this.obj);
|
g.promiseState = this._createPromiseState();
|
||||||
if (isCPOW) {
|
|
||||||
g.class = "CPOW: " + g.class;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g.class != "DeadObject" && !isCPOW) {
|
// FF40+: Allow to know how many properties an object has to lazily display them
|
||||||
if (g.class == "Promise") {
|
// when there is a bunch.
|
||||||
g.promiseState = this._createPromiseState();
|
if (TYPED_ARRAY_CLASSES.indexOf(g.class) != -1) {
|
||||||
}
|
// Bug 1348761: getOwnPropertyNames is unnecessary slow on TypedArrays
|
||||||
|
let length = DevToolsUtils.getProperty(this.obj, "length");
|
||||||
|
g.ownPropertyLength = length;
|
||||||
|
} else if (g.class != "Proxy") {
|
||||||
|
g.ownPropertyLength = this.obj.getOwnPropertyNames().length;
|
||||||
|
}
|
||||||
|
|
||||||
// FF40+: Allow to know how many properties an object has
|
let raw = this.obj.unsafeDereference();
|
||||||
// to lazily display them when there is a bunch.
|
|
||||||
// Throws on some MouseEvent object in tests.
|
// If Cu is not defined, we are running on a worker thread, where xrays
|
||||||
|
// don't exist.
|
||||||
|
if (Cu) {
|
||||||
|
raw = Cu.unwaiveXrays(raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DevToolsUtils.isSafeJSObject(raw)) {
|
||||||
|
raw = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let previewers = DebuggerServer.ObjectActorPreviewers[g.class] ||
|
||||||
|
DebuggerServer.ObjectActorPreviewers.Object;
|
||||||
|
for (let fn of previewers) {
|
||||||
try {
|
try {
|
||||||
if (TYPED_ARRAY_CLASSES.indexOf(g.class) != -1) {
|
if (fn(this, g, raw)) {
|
||||||
// Bug 1348761: getOwnPropertyNames is unecessary slow on TypedArrays
|
break;
|
||||||
let length = DevToolsUtils.getProperty(this.obj, "length");
|
|
||||||
g.ownPropertyLength = length;
|
|
||||||
} else if (g.class != "Proxy") {
|
|
||||||
g.ownPropertyLength = this.obj.getOwnPropertyNames().length;
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// ignored
|
let msg = "ObjectActor.prototype.grip previewer function";
|
||||||
}
|
DevToolsUtils.reportException(msg, e);
|
||||||
|
|
||||||
let raw = this.obj.unsafeDereference();
|
|
||||||
|
|
||||||
// If Cu is not defined, we are running on a worker thread, where xrays
|
|
||||||
// don't exist.
|
|
||||||
if (Cu) {
|
|
||||||
raw = Cu.unwaiveXrays(raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DevToolsUtils.isSafeJSObject(raw)) {
|
|
||||||
raw = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let previewers = DebuggerServer.ObjectActorPreviewers[g.class] ||
|
|
||||||
DebuggerServer.ObjectActorPreviewers.Object;
|
|
||||||
for (let fn of previewers) {
|
|
||||||
try {
|
|
||||||
if (fn(this, g, raw)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
let msg = "ObjectActor.prototype.grip previewer function";
|
|
||||||
DevToolsUtils.reportException(msg, e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,20 +289,20 @@ ObjectActor.prototype = {
|
||||||
onPrototypeAndProperties: function () {
|
onPrototypeAndProperties: function () {
|
||||||
let ownProperties = Object.create(null);
|
let ownProperties = Object.create(null);
|
||||||
let ownSymbols = [];
|
let ownSymbols = [];
|
||||||
let names;
|
|
||||||
let symbols;
|
// Inaccessible, proxy and dead objects should not be accessed.
|
||||||
try {
|
let unwrapped = unwrap(this.obj);
|
||||||
names = this.obj.getOwnPropertyNames();
|
if (!unwrapped || unwrapped.isProxy || this.obj.class == "DeadObject") {
|
||||||
symbols = this.obj.getOwnPropertySymbols();
|
|
||||||
} catch (ex) {
|
|
||||||
// The above can throw if this.obj points to a dead object.
|
|
||||||
// TODO: we should use Cu.isDeadWrapper() - see bug 885800.
|
|
||||||
return { from: this.actorID,
|
return { from: this.actorID,
|
||||||
prototype: this.hooks.createValueGrip(null),
|
prototype: this.hooks.createValueGrip(null),
|
||||||
ownProperties,
|
ownProperties,
|
||||||
ownSymbols,
|
ownSymbols,
|
||||||
safeGetterValues: Object.create(null) };
|
safeGetterValues: Object.create(null) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let names = this.obj.getOwnPropertyNames();
|
||||||
|
let symbols = this.obj.getOwnPropertySymbols();
|
||||||
|
|
||||||
for (let name of names) {
|
for (let name of names) {
|
||||||
ownProperties[name] = this._propertyDescriptor(name);
|
ownProperties[name] = this._propertyDescriptor(name);
|
||||||
}
|
}
|
||||||
|
@ -340,8 +339,9 @@ ObjectActor.prototype = {
|
||||||
let obj = this.obj;
|
let obj = this.obj;
|
||||||
let level = 0, i = 0;
|
let level = 0, i = 0;
|
||||||
|
|
||||||
// Do not search safe getters in proxy objects.
|
// Do not search safe getters in inaccessible nor proxy objects.
|
||||||
if (isProxy(obj)) {
|
let unwrapped = unwrap(obj);
|
||||||
|
if (!unwrapped || unwrapped.isProxy) {
|
||||||
return safeGetterValues;
|
return safeGetterValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,8 +355,13 @@ ObjectActor.prototype = {
|
||||||
level++;
|
level++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop iterating when the prototype chain ends or a proxy is found.
|
while (obj) {
|
||||||
while (obj && !isProxy(obj)) {
|
// Stop iterating when an inaccessible or a proxy object is found.
|
||||||
|
unwrapped = unwrap(obj);
|
||||||
|
if (!unwrapped || unwrapped.isProxy) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
let getters = this._findSafeGetters(obj);
|
let getters = this._findSafeGetters(obj);
|
||||||
for (let name of getters) {
|
for (let name of getters) {
|
||||||
// Avoid overwriting properties from prototypes closer to this.obj. Also
|
// Avoid overwriting properties from prototypes closer to this.obj. Also
|
||||||
|
@ -2455,38 +2460,33 @@ function arrayBufferGrip(buffer, pool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether the referent of a debuggee object is a scripted proxy.
|
* Removes all the non-opaque security wrappers of a debuggee object.
|
||||||
* Non-opaque security wrappers are unwrapped first before the check.
|
* Returns null if some wrapper can't be removed.
|
||||||
*
|
*
|
||||||
* @param obj Debugger.Object
|
* @param obj Debugger.Object
|
||||||
* The debuggee object to be checked.
|
* The debuggee object to be unwrapped.
|
||||||
*/
|
*/
|
||||||
function isProxy(obj) {
|
function unwrap(obj) {
|
||||||
// Check if the object is a proxy without security wrappers.
|
// Check if `obj` has an opaque wrapper.
|
||||||
if (obj.isProxy) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No need to remove opaque wrappers since they prevent proxy traps from running.
|
|
||||||
if (obj.class === "Opaque") {
|
if (obj.class === "Opaque") {
|
||||||
return false;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to unwrap. If the debugger can't unwrap, then proxy traps won't be
|
// Attempt to unwrap. If this operation is not allowed, it may return null or throw.
|
||||||
// allowed to run either, so the object can be safely assumed to not be a proxy.
|
|
||||||
let unwrapped;
|
let unwrapped;
|
||||||
try {
|
try {
|
||||||
unwrapped = obj.unwrap();
|
unwrapped = obj.unwrap();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return false;
|
unwrapped = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if further unwrapping is not possible.
|
||||||
if (!unwrapped || unwrapped === obj) {
|
if (!unwrapped || unwrapped === obj) {
|
||||||
return false;
|
return unwrapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursively check whether the unwrapped object is a proxy.
|
// Recursively remove additional security wrappers.
|
||||||
return isProxy(unwrapped);
|
return unwrap(unwrapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.ObjectActor = ObjectActor;
|
exports.ObjectActor = ObjectActor;
|
||||||
|
|
|
@ -167,7 +167,7 @@ var DebuggerServer = {
|
||||||
* window (i.e the global style editor). Set this to your main window type,
|
* window (i.e the global style editor). Set this to your main window type,
|
||||||
* for example "navigator:browser".
|
* for example "navigator:browser".
|
||||||
*/
|
*/
|
||||||
chromeWindowType: null,
|
chromeWindowType: "navigator:browser",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allow debugging chrome of (parent or child) processes.
|
* Allow debugging chrome of (parent or child) processes.
|
||||||
|
@ -266,11 +266,13 @@ var DebuggerServer = {
|
||||||
* actors to retrieve them.
|
* actors to retrieve them.
|
||||||
*/
|
*/
|
||||||
registerActors({ root = true, browser = true, tab = true,
|
registerActors({ root = true, browser = true, tab = true,
|
||||||
windowType = "navigator:browser" }) {
|
windowType = null }) {
|
||||||
this.chromeWindowType = windowType;
|
if (windowType) {
|
||||||
|
this.chromeWindowType = windowType;
|
||||||
|
}
|
||||||
|
|
||||||
if (browser) {
|
if (browser) {
|
||||||
this.addBrowserActors(windowType);
|
this.addBrowserActors(this.chromeWindowType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root) {
|
if (root) {
|
||||||
|
@ -420,8 +422,10 @@ var DebuggerServer = {
|
||||||
* restrictPrivileges=true, to prevent exposing them on b2g parent process's
|
* restrictPrivileges=true, to prevent exposing them on b2g parent process's
|
||||||
* root actor.
|
* root actor.
|
||||||
*/
|
*/
|
||||||
addBrowserActors(windowType = "navigator:browser", restrictPrivileges = false) {
|
addBrowserActors(windowType = null, restrictPrivileges = false) {
|
||||||
this.chromeWindowType = windowType;
|
if (windowType) {
|
||||||
|
this.chromeWindowType = windowType;
|
||||||
|
}
|
||||||
this.registerModule("devtools/server/actors/webbrowser");
|
this.registerModule("devtools/server/actors/webbrowser");
|
||||||
|
|
||||||
if (!restrictPrivileges) {
|
if (!restrictPrivileges) {
|
||||||
|
|
|
@ -6,10 +6,13 @@
|
||||||
|
|
||||||
var gServer;
|
var gServer;
|
||||||
var gDebuggee;
|
var gDebuggee;
|
||||||
|
var gDebuggeeHasXrays;
|
||||||
var gClient;
|
var gClient;
|
||||||
var gThreadClient;
|
var gThreadClient;
|
||||||
var gGlobal;
|
var gGlobal;
|
||||||
var gHasXrays;
|
var gGlobalIsInvisible;
|
||||||
|
var gSubsumes;
|
||||||
|
var gIsOpaque;
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
run_test_with_server(DebuggerServer, function () {
|
run_test_with_server(DebuggerServer, function () {
|
||||||
|
@ -31,63 +34,95 @@ async function run_test_with_server(server, callback) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function run_tests_in_principal(principal, title) {
|
async function run_tests_in_principal(debuggeePrincipal, title) {
|
||||||
// Prepare the debuggee.
|
for (gDebuggeeHasXrays of [true, false]) {
|
||||||
gDebuggee = Cu.Sandbox(principal);
|
// Prepare the debuggee.
|
||||||
gDebuggee.__name = title;
|
let fullTitle = gDebuggeeHasXrays ? title + "-with-xrays" : title;
|
||||||
gServer.addTestGlobal(gDebuggee);
|
gDebuggee = Cu.Sandbox(debuggeePrincipal, {wantXrays: gDebuggeeHasXrays});
|
||||||
gDebuggee.eval(function stopMe(arg1, arg2) {
|
gDebuggee.__name = fullTitle;
|
||||||
debugger;
|
gServer.addTestGlobal(gDebuggee);
|
||||||
}.toString());
|
gDebuggee.eval(function stopMe() {
|
||||||
gClient = new DebuggerClient(gServer.connectPipe());
|
debugger;
|
||||||
await gClient.connect();
|
}.toString());
|
||||||
const [,, threadClient] = await attachTestTabAndResume(gClient, title);
|
gClient = new DebuggerClient(gServer.connectPipe());
|
||||||
gThreadClient = threadClient;
|
await gClient.connect();
|
||||||
|
const [,, threadClient] = await attachTestTabAndResume(gClient, fullTitle);
|
||||||
|
gThreadClient = threadClient;
|
||||||
|
|
||||||
// Test objects created in the debuggee.
|
// Test objects created in the debuggee.
|
||||||
await testPrincipal(undefined, false);
|
await testPrincipal(undefined);
|
||||||
|
|
||||||
// Test objects created in a new system principal with Xrays.
|
// Test objects created in a system principal new global.
|
||||||
await testPrincipal(systemPrincipal, true);
|
await testPrincipal(systemPrincipal);
|
||||||
|
|
||||||
// Test objects created in a new system principal without Xrays.
|
// Test objects created in a cross-origin null principal new global.
|
||||||
await testPrincipal(systemPrincipal, false);
|
await testPrincipal(null);
|
||||||
|
|
||||||
// Test objects created in a new null principal with Xrays.
|
if (debuggeePrincipal === null) {
|
||||||
await testPrincipal(null, true);
|
// Test objects created in a same-origin null principal new global.
|
||||||
|
await testPrincipal(Cu.getObjectPrincipal(gDebuggee));
|
||||||
|
}
|
||||||
|
|
||||||
// Test objects created in a new null principal without Xrays.
|
// Finish.
|
||||||
await testPrincipal(null, false);
|
await gClient.close();
|
||||||
|
}
|
||||||
// Finish.
|
|
||||||
await gClient.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPrincipal(principal, wantXrays = true) {
|
async function testPrincipal(globalPrincipal) {
|
||||||
// Create a global object with the specified security principal.
|
// Create a global object with the specified security principal.
|
||||||
// If none is specified, use the debuggee.
|
// If none is specified, use the debuggee.
|
||||||
if (principal !== undefined) {
|
if (globalPrincipal === undefined) {
|
||||||
gGlobal = Cu.Sandbox(principal, {wantXrays});
|
|
||||||
gHasXrays = wantXrays;
|
|
||||||
} else {
|
|
||||||
gGlobal = gDebuggee;
|
gGlobal = gDebuggee;
|
||||||
gHasXrays = false;
|
gSubsumes = true;
|
||||||
|
gIsOpaque = false;
|
||||||
|
gGlobalIsInvisible = false;
|
||||||
|
await test();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let debuggeePrincipal = Cu.getObjectPrincipal(gDebuggee);
|
||||||
|
let sameOrigin = debuggeePrincipal === globalPrincipal;
|
||||||
|
gSubsumes = sameOrigin || debuggeePrincipal === systemPrincipal;
|
||||||
|
for (let globalHasXrays of [true, false]) {
|
||||||
|
gIsOpaque = gSubsumes && globalPrincipal !== systemPrincipal
|
||||||
|
&& (sameOrigin && gDebuggeeHasXrays || globalHasXrays);
|
||||||
|
for (gGlobalIsInvisible of [true, false]) {
|
||||||
|
gGlobal = Cu.Sandbox(globalPrincipal, {
|
||||||
|
wantXrays: globalHasXrays,
|
||||||
|
invisibleToDebugger: gGlobalIsInvisible
|
||||||
|
});
|
||||||
|
await test();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function test() {
|
||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
gThreadClient.addOneTimeListener("paused", async function (event, packet) {
|
gThreadClient.addOneTimeListener("paused", async function (event, packet) {
|
||||||
// Get the grips.
|
// Get the grips.
|
||||||
let [proxyGrip, inheritsProxyGrip] = packet.frame.arguments;
|
let [proxyGrip, inheritsProxyGrip, inheritsProxy2Grip] = packet.frame.arguments;
|
||||||
|
|
||||||
// Check the grip of the proxy object.
|
// Check the grip of the proxy object.
|
||||||
check_proxy_grip(proxyGrip);
|
check_proxy_grip(proxyGrip);
|
||||||
|
|
||||||
// Retrieve the properties of the object which inherits from a proxy,
|
// Check the prototype and properties of the proxy object.
|
||||||
// and check the grip of its prototype.
|
let proxyClient = gThreadClient.pauseGrip(proxyGrip);
|
||||||
let objClient = gThreadClient.pauseGrip(inheritsProxyGrip);
|
let proxyResponse = await proxyClient.getPrototypeAndProperties();
|
||||||
let response = await objClient.getPrototypeAndProperties();
|
check_properties(proxyResponse.ownProperties, true, false);
|
||||||
check_properties(response.ownProperties);
|
check_prototype(proxyResponse.prototype, true, false);
|
||||||
check_prototype(response.prototype);
|
|
||||||
|
// Check the prototype and properties of the object which inherits from the proxy.
|
||||||
|
let inheritsProxyClient = gThreadClient.pauseGrip(inheritsProxyGrip);
|
||||||
|
let inheritsProxyResponse = await inheritsProxyClient.getPrototypeAndProperties();
|
||||||
|
check_properties(inheritsProxyResponse.ownProperties, false, false);
|
||||||
|
check_prototype(inheritsProxyResponse.prototype, false, false);
|
||||||
|
|
||||||
|
// The prototype chain was not iterated if the object was inaccessible, so now check
|
||||||
|
// another object which inherits from the proxy, but was created in the debuggee.
|
||||||
|
let inheritsProxy2Client = gThreadClient.pauseGrip(inheritsProxy2Grip);
|
||||||
|
let inheritsProxy2Response = await inheritsProxy2Client.getPrototypeAndProperties();
|
||||||
|
check_properties(inheritsProxy2Response.ownProperties, false, true);
|
||||||
|
check_prototype(inheritsProxy2Response.prototype, false, true);
|
||||||
|
|
||||||
// Check that none of the above ran proxy traps.
|
// Check that none of the above ran proxy traps.
|
||||||
strictEqual(gGlobal.trapDidRun, false, "No proxy trap did run.");
|
strictEqual(gGlobal.trapDidRun, false, "No proxy trap did run.");
|
||||||
|
@ -105,24 +140,21 @@ function testPrincipal(principal, wantXrays = true) {
|
||||||
gGlobal.eval(`
|
gGlobal.eval(`
|
||||||
var trapDidRun = false;
|
var trapDidRun = false;
|
||||||
var proxy = new Proxy({}, new Proxy({}, {get: (_, trap) => {
|
var proxy = new Proxy({}, new Proxy({}, {get: (_, trap) => {
|
||||||
return function(_, arg) {
|
trapDidRun = true;
|
||||||
trapDidRun = true;
|
throw new Error("proxy trap '" + trap + "' was called.");
|
||||||
throw new Error("proxy trap '" + trap + "' was called.");
|
|
||||||
}
|
|
||||||
}}));
|
}}));
|
||||||
var inheritsProxy = Object.create(proxy, {x:{value:1}});
|
var inheritsProxy = Object.create(proxy, {x:{value:1}});
|
||||||
`);
|
`);
|
||||||
let data = Cu.createObjectIn(gDebuggee, {defineAs: "data"});
|
let data = Cu.createObjectIn(gDebuggee, {defineAs: "data"});
|
||||||
data.proxy = gGlobal.proxy;
|
data.proxy = gGlobal.proxy;
|
||||||
data.inheritsProxy = gGlobal.inheritsProxy;
|
data.inheritsProxy = gGlobal.inheritsProxy;
|
||||||
gDebuggee.eval("stopMe(data.proxy, data.inheritsProxy);");
|
gDebuggee.eval(`
|
||||||
|
var inheritsProxy2 = Object.create(data.proxy, {x:{value:1}});
|
||||||
|
stopMe(data.proxy, data.inheritsProxy, inheritsProxy2);
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSystemPrincipal(obj) {
|
|
||||||
return Cu.getObjectPrincipal(obj) === systemPrincipal;
|
|
||||||
}
|
|
||||||
|
|
||||||
function check_proxy_grip(grip) {
|
function check_proxy_grip(grip) {
|
||||||
const {preview} = grip;
|
const {preview} = grip;
|
||||||
|
|
||||||
|
@ -136,11 +168,11 @@ function check_proxy_grip(grip) {
|
||||||
strictEqual(target, grip.proxyTarget, "<target> contains the [[ProxyTarget]].");
|
strictEqual(target, grip.proxyTarget, "<target> contains the [[ProxyTarget]].");
|
||||||
let handler = preview.ownProperties["<handler>"].value;
|
let handler = preview.ownProperties["<handler>"].value;
|
||||||
strictEqual(handler, grip.proxyHandler, "<handler> contains the [[ProxyHandler]].");
|
strictEqual(handler, grip.proxyHandler, "<handler> contains the [[ProxyHandler]].");
|
||||||
} else if (!isSystemPrincipal(gDebuggee)) {
|
} else if (gIsOpaque) {
|
||||||
// The debuggee is not allowed to remove the security wrappers.
|
// The proxy has opaque security wrappers.
|
||||||
strictEqual(grip.class, "Object", "The grip has an Object class.");
|
strictEqual(grip.class, "Opaque", "The grip has an Opaque class.");
|
||||||
ok(!("ownPropertyLength" in grip), "The grip doesn't know the number of properties.");
|
strictEqual(grip.ownPropertyLength, 0, "The grip has no properties.");
|
||||||
} else if (!gHasXrays || isSystemPrincipal(gGlobal)) {
|
} else if (gSubsumes && !gGlobalIsInvisible) {
|
||||||
// The proxy has non-opaque security wrappers.
|
// The proxy has non-opaque security wrappers.
|
||||||
strictEqual(grip.class, "Proxy", "The grip has a Proxy class.");
|
strictEqual(grip.class, "Proxy", "The grip has a Proxy class.");
|
||||||
ok(!("proxyTarget" in grip), "There is no [[ProxyTarget]] grip.");
|
ok(!("proxyTarget" in grip), "There is no [[ProxyTarget]] grip.");
|
||||||
|
@ -149,37 +181,40 @@ function check_proxy_grip(grip) {
|
||||||
ok(!("<target>" in preview), "The preview has no <target> property.");
|
ok(!("<target>" in preview), "The preview has no <target> property.");
|
||||||
ok(!("<handler>" in preview), "The preview has no <handler> property.");
|
ok(!("<handler>" in preview), "The preview has no <handler> property.");
|
||||||
} else {
|
} else {
|
||||||
// The proxy has opaque security wrappers.
|
// The debuggee is not allowed to remove the security wrappers.
|
||||||
strictEqual(grip.class, "Opaque", "The grip has an Opaque class.");
|
strictEqual(grip.class, "Inaccessible", "The grip has an Inaccessible class.");
|
||||||
strictEqual(grip.ownPropertyLength, 0, "The grip has no properties.");
|
ok(!("ownPropertyLength" in grip), "The grip doesn't know the number of properties.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_properties(props) {
|
function check_properties(props, isProxy, createdInDebuggee) {
|
||||||
let ownPropertiesLength = Reflect.ownKeys(props).length;
|
let ownPropertiesLength = Reflect.ownKeys(props).length;
|
||||||
|
|
||||||
if (!isSystemPrincipal(gDebuggee) && gDebuggee !== gGlobal) {
|
if (createdInDebuggee || !isProxy && gSubsumes && !gGlobalIsInvisible) {
|
||||||
// The debuggee is not allowed to access the object.
|
|
||||||
strictEqual(ownPropertiesLength, 0, "No own property could be retrieved.");
|
|
||||||
} else {
|
|
||||||
// The debuggee can access the properties.
|
// The debuggee can access the properties.
|
||||||
strictEqual(ownPropertiesLength, 1, "1 own property was retrieved.");
|
strictEqual(ownPropertiesLength, 1, "1 own property was retrieved.");
|
||||||
strictEqual(props.x.value, 1, "The property has the right value.");
|
strictEqual(props.x.value, 1, "The property has the right value.");
|
||||||
|
} else {
|
||||||
|
// The debuggee is not allowed to access the object.
|
||||||
|
strictEqual(ownPropertiesLength, 0, "No own property could be retrieved.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_prototype(proto) {
|
function check_prototype(proto, isProxy, createdInDebuggee) {
|
||||||
if (!isSystemPrincipal(gDebuggee) && gDebuggee !== gGlobal) {
|
if (gIsOpaque && !gGlobalIsInvisible && !createdInDebuggee) {
|
||||||
// The debuggee is not allowed to access the object. It sees a null prototype.
|
// The object is or inherits from a proxy with opaque security wrappers.
|
||||||
strictEqual(proto.type, "null", "The prototype is null.");
|
// The debuggee sees `Object.prototype` when retrieving the prototype.
|
||||||
} else if (!gHasXrays || isSystemPrincipal(gGlobal)) {
|
strictEqual(proto.class, "Object", "The prototype has a Object class.");
|
||||||
// The object has no security wrappers or non-opaque ones.
|
} else if (isProxy && gIsOpaque && gGlobalIsInvisible) {
|
||||||
|
// The object is a proxy with opaque security wrappers in an invisible global.
|
||||||
|
// The debuggee sees an inaccessible `Object.prototype` when retrieving the prototype.
|
||||||
|
strictEqual(proto.class, "Inaccessible", "The prototype has an Inaccessible class.");
|
||||||
|
} else if (createdInDebuggee || !isProxy && gSubsumes && !gGlobalIsInvisible) {
|
||||||
|
// The object inherits from a proxy and has no security wrappers or non-opaque ones.
|
||||||
// The debuggee sees the proxy when retrieving the prototype.
|
// The debuggee sees the proxy when retrieving the prototype.
|
||||||
check_proxy_grip(proto);
|
check_proxy_grip(proto);
|
||||||
} else {
|
} else {
|
||||||
// The object has opaque security wrappers.
|
// The debuggee is not allowed to access the object. It sees a null prototype.
|
||||||
// The debuggee sees `Object.prototype` when retrieving the prototype.
|
strictEqual(proto.type, "null", "The prototype is null.");
|
||||||
strictEqual(proto.class, "Object", "The prototype has a Object class.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,7 @@ function doConsoleCalls(aState)
|
||||||
{
|
{
|
||||||
type: "object",
|
type: "object",
|
||||||
actor: /[a-z]/,
|
actor: /[a-z]/,
|
||||||
class: "Object",
|
class: "Inaccessible",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -12,10 +12,7 @@
|
||||||
#include "nsIDOMHTMLDocument.h"
|
#include "nsIDOMHTMLDocument.h"
|
||||||
#include "nsIDOMHTMLElement.h"
|
#include "nsIDOMHTMLElement.h"
|
||||||
#include "nsIDOMHTMLHtmlElement.h"
|
#include "nsIDOMHTMLHtmlElement.h"
|
||||||
#include "nsIDOMHTMLAnchorElement.h"
|
|
||||||
#include "nsIDOMHTMLImageElement.h"
|
#include "nsIDOMHTMLImageElement.h"
|
||||||
#include "nsIDOMHTMLAreaElement.h"
|
|
||||||
#include "nsIDOMHTMLLinkElement.h"
|
|
||||||
#include "nsIDOMWindow.h"
|
#include "nsIDOMWindow.h"
|
||||||
#include "nsICSSDeclaration.h"
|
#include "nsICSSDeclaration.h"
|
||||||
#include "nsIDOMCSSValue.h"
|
#include "nsIDOMCSSValue.h"
|
||||||
|
@ -27,7 +24,13 @@
|
||||||
#include "nsIContentSecurityPolicy.h"
|
#include "nsIContentSecurityPolicy.h"
|
||||||
#include "nsIContentPolicy.h"
|
#include "nsIContentPolicy.h"
|
||||||
#include "imgRequestProxy.h"
|
#include "imgRequestProxy.h"
|
||||||
|
#include "mozilla/dom/HTMLAnchorElement.h"
|
||||||
|
#include "mozilla/dom/HTMLAreaElement.h"
|
||||||
|
#include "mozilla/dom/HTMLLinkElement.h"
|
||||||
|
|
||||||
|
using mozilla::dom::HTMLAnchorElement;
|
||||||
|
using mozilla::dom::HTMLAreaElement;
|
||||||
|
using mozilla::dom::HTMLLinkElement;
|
||||||
using mozilla::dom::Element;
|
using mozilla::dom::Element;
|
||||||
using mozilla::ErrorResult;
|
using mozilla::ErrorResult;
|
||||||
|
|
||||||
|
@ -63,30 +66,24 @@ nsContextMenuInfo::GetAssociatedLink(nsAString& aHRef)
|
||||||
NS_ENSURE_STATE(mAssociatedLink);
|
NS_ENSURE_STATE(mAssociatedLink);
|
||||||
aHRef.Truncate(0);
|
aHRef.Truncate(0);
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMElement> content(do_QueryInterface(mAssociatedLink));
|
nsCOMPtr<nsIContent> content(do_QueryInterface(mAssociatedLink));
|
||||||
nsAutoString localName;
|
nsCOMPtr<nsIContent> linkContent;
|
||||||
if (content) {
|
if (content &&
|
||||||
content->GetLocalName(localName);
|
content->IsAnyOfHTMLElements(nsGkAtoms::a,
|
||||||
}
|
nsGkAtoms::area,
|
||||||
|
nsGkAtoms::link)) {
|
||||||
nsCOMPtr<nsIDOMElement> linkContent;
|
bool hasAttr = content->HasAttr(kNameSpaceID_None, nsGkAtoms::href);
|
||||||
ToLowerCase(localName);
|
|
||||||
if (localName.EqualsLiteral("a") ||
|
|
||||||
localName.EqualsLiteral("area") ||
|
|
||||||
localName.EqualsLiteral("link")) {
|
|
||||||
bool hasAttr;
|
|
||||||
content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
|
|
||||||
if (hasAttr) {
|
if (hasAttr) {
|
||||||
linkContent = content;
|
linkContent = content;
|
||||||
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(linkContent));
|
RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContent(linkContent);
|
||||||
if (anchor) {
|
if (anchor) {
|
||||||
anchor->GetHref(aHRef);
|
anchor->GetHref(aHRef);
|
||||||
} else {
|
} else {
|
||||||
nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(linkContent));
|
RefPtr<HTMLAreaElement> area = HTMLAreaElement::FromContent(linkContent);
|
||||||
if (area) {
|
if (area) {
|
||||||
area->GetHref(aHRef);
|
area->GetHref(aHRef);
|
||||||
} else {
|
} else {
|
||||||
nsCOMPtr<nsIDOMHTMLLinkElement> link(do_QueryInterface(linkContent));
|
RefPtr<HTMLLinkElement> link = HTMLLinkElement::FromContent(linkContent);
|
||||||
if (link) {
|
if (link) {
|
||||||
link->GetHref(aHRef);
|
link->GetHref(aHRef);
|
||||||
}
|
}
|
||||||
|
@ -101,15 +98,12 @@ nsContextMenuInfo::GetAssociatedLink(nsAString& aHRef)
|
||||||
if (!content) {
|
if (!content) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
content->GetLocalName(localName);
|
if (content->IsHTMLElement(nsGkAtoms::a)) {
|
||||||
ToLowerCase(localName);
|
|
||||||
if (localName.EqualsLiteral("a")) {
|
|
||||||
bool hasAttr;
|
bool hasAttr;
|
||||||
content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
|
hasAttr = content->HasAttr(kNameSpaceID_None, nsGkAtoms::href);
|
||||||
if (hasAttr) {
|
if (hasAttr) {
|
||||||
linkContent = content;
|
linkContent = content;
|
||||||
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(
|
RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContent(linkContent);
|
||||||
do_QueryInterface(linkContent));
|
|
||||||
if (anchor) {
|
if (anchor) {
|
||||||
anchor->GetHref(aHRef);
|
anchor->GetHref(aHRef);
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,6 @@
|
||||||
#include "nsStreamUtils.h"
|
#include "nsStreamUtils.h"
|
||||||
#include "nsIController.h"
|
#include "nsIController.h"
|
||||||
#include "nsPICommandUpdater.h"
|
#include "nsPICommandUpdater.h"
|
||||||
#include "nsIDOMHTMLAnchorElement.h"
|
|
||||||
#include "nsIWebBrowserChrome3.h"
|
#include "nsIWebBrowserChrome3.h"
|
||||||
#include "nsITabChild.h"
|
#include "nsITabChild.h"
|
||||||
#include "nsISiteSecurityService.h"
|
#include "nsISiteSecurityService.h"
|
||||||
|
@ -14435,7 +14434,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
|
||||||
|
|
||||||
// If this is an anchor element, grab its type property to use as a hint
|
// If this is an anchor element, grab its type property to use as a hint
|
||||||
nsAutoString typeHint;
|
nsAutoString typeHint;
|
||||||
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(aContent));
|
RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContent(aContent);
|
||||||
if (anchor) {
|
if (anchor) {
|
||||||
anchor->GetType(typeHint);
|
anchor->GetType(typeHint);
|
||||||
NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
|
NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
|
||||||
|
|
|
@ -22,44 +22,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AbortController)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||||
NS_INTERFACE_MAP_END
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
/* static */ bool
|
|
||||||
AbortController::IsEnabled(JSContext* aCx, JSObject* aGlobal)
|
|
||||||
{
|
|
||||||
if (NS_IsMainThread()) {
|
|
||||||
return Preferences::GetBool("dom.abortController.enabled", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace workers;
|
|
||||||
|
|
||||||
// Otherwise, check the pref via the WorkerPrivate
|
|
||||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
|
||||||
if (!workerPrivate) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return workerPrivate->AbortControllerEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ bool
|
|
||||||
AbortController::IsEnabledInFetch(JSContext* aCx, JSObject* aGlobal)
|
|
||||||
{
|
|
||||||
if (NS_IsMainThread()) {
|
|
||||||
return IsEnabled(aCx, aGlobal) &&
|
|
||||||
Preferences::GetBool("dom.abortController.fetch.enabled", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace workers;
|
|
||||||
|
|
||||||
// Otherwise, check the pref via the WorkerPrivate
|
|
||||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
|
||||||
if (!workerPrivate) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return workerPrivate->AbortControllerEnabled() &&
|
|
||||||
workerPrivate->AbortControllerEnabledInFetch();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ already_AddRefed<AbortController>
|
/* static */ already_AddRefed<AbortController>
|
||||||
AbortController::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
AbortController::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,12 +26,6 @@ public:
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AbortController)
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AbortController)
|
||||||
|
|
||||||
static bool
|
|
||||||
IsEnabled(JSContext* aCx, JSObject* aGlobal);
|
|
||||||
|
|
||||||
static bool
|
|
||||||
IsEnabledInFetch(JSContext* aCx, JSObject* aGlobal);
|
|
||||||
|
|
||||||
static already_AddRefed<AbortController>
|
static already_AddRefed<AbortController>
|
||||||
Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
|
Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
|
||||||
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
<script>
|
|
||||||
function ok(a, msg) {
|
|
||||||
parent.postMessage({ type: "check", status: !!a, message: msg }, "*");
|
|
||||||
}
|
|
||||||
|
|
||||||
function is(a, b, msg) {
|
|
||||||
ok(a === b, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testWebIDL() {
|
|
||||||
ok("AbortController" in self, "We have a AbortController prototype");
|
|
||||||
ok("AbortSignal" in self, "We have a AbortSignal prototype");
|
|
||||||
|
|
||||||
var ac = new AbortController();
|
|
||||||
ok(!!ac, "AbortController can be created");
|
|
||||||
ok(ac instanceof AbortController, "AbortController is a AbortController");
|
|
||||||
|
|
||||||
ok(!!ac.signal, "AbortController has a signal");
|
|
||||||
ok(ac.signal instanceof AbortSignal, "abortSignal is a AbortSignal");
|
|
||||||
is(ac.signal.aborted, false, "By default AbortSignal.aborted is false");
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
function testUpdateData() {
|
|
||||||
var ac = new AbortController();
|
|
||||||
|
|
||||||
is(ac.signal.aborted, false, "By default AbortSignal.aborted is false");
|
|
||||||
|
|
||||||
ac.abort();
|
|
||||||
is(ac.signal.aborted, true, "Signal is aborted");
|
|
||||||
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
function testAbortEvent() {
|
|
||||||
var ac = new AbortController();
|
|
||||||
ac.signal.onabort = function(e) {
|
|
||||||
is(e.type, "abort", "Abort received");
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
ac.abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
var steps = [
|
|
||||||
// Simple stuff
|
|
||||||
testWebIDL,
|
|
||||||
testUpdateData,
|
|
||||||
|
|
||||||
// Event propagation
|
|
||||||
testAbortEvent,
|
|
||||||
];
|
|
||||||
|
|
||||||
function next() {
|
|
||||||
if (!steps.length) {
|
|
||||||
parent.postMessage({ type: "finish" }, "*");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var step = steps.shift();
|
|
||||||
step();
|
|
||||||
}
|
|
||||||
|
|
||||||
next();
|
|
||||||
|
|
||||||
</script>
|
|
|
@ -1,72 +0,0 @@
|
||||||
<script>
|
|
||||||
function ok(a, msg) {
|
|
||||||
parent.postMessage({ type: "check", status: !!a, message: msg }, "*");
|
|
||||||
}
|
|
||||||
|
|
||||||
function is(a, b, msg) {
|
|
||||||
ok(a === b, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testAbortedFetch() {
|
|
||||||
var ac = new AbortController();
|
|
||||||
ac.abort();
|
|
||||||
|
|
||||||
fetch("slow.sjs", { signal: ac.signal }).then(() => {
|
|
||||||
ok(false, "Fetch should not return a resolved promise");
|
|
||||||
}, e => {
|
|
||||||
is(e.name, "AbortError", "We have an abort error");
|
|
||||||
}).then(next);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFetchAndAbort() {
|
|
||||||
var ac = new AbortController();
|
|
||||||
|
|
||||||
var p = fetch("slow.sjs", { signal: ac.signal });
|
|
||||||
ac.abort();
|
|
||||||
|
|
||||||
p.then(() => {
|
|
||||||
ok(false, "Fetch should not return a resolved promise");
|
|
||||||
}, e => {
|
|
||||||
is(e.name, "AbortError", "We have an abort error");
|
|
||||||
}).then(next);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testWorkerAbortedFetch() {
|
|
||||||
var w = new Worker("worker_abort_controller_fetch.js");
|
|
||||||
w.onmessage = function(e) {
|
|
||||||
ok(e.data, "Abort + Fetch works in workers");
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
w.postMessage("testWorkerAbortedFetch");
|
|
||||||
}
|
|
||||||
|
|
||||||
function testWorkerFetchAndAbort() {
|
|
||||||
var w = new Worker("worker_abort_controller_fetch.js");
|
|
||||||
w.onmessage = function(e) {
|
|
||||||
ok(e.data, "Abort + Fetch works in workers");
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
w.postMessage("testWorkerFetchAndAbort");
|
|
||||||
}
|
|
||||||
|
|
||||||
var steps = [
|
|
||||||
// fetch + signaling
|
|
||||||
testAbortedFetch,
|
|
||||||
testFetchAndAbort,
|
|
||||||
testWorkerAbortedFetch,
|
|
||||||
testWorkerFetchAndAbort,
|
|
||||||
];
|
|
||||||
|
|
||||||
function next() {
|
|
||||||
if (!steps.length) {
|
|
||||||
parent.postMessage({ type: "finish" }, "*");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var step = steps.shift();
|
|
||||||
step();
|
|
||||||
}
|
|
||||||
|
|
||||||
next();
|
|
||||||
|
|
||||||
</script>
|
|
|
@ -1,7 +1,5 @@
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
support-files =
|
support-files =
|
||||||
file_abort_controller.html
|
|
||||||
file_abort_controller_fetch.html
|
|
||||||
worker_abort_controller_fetch.js
|
worker_abort_controller_fetch.js
|
||||||
slow.sjs
|
slow.sjs
|
||||||
|
|
||||||
|
|
|
@ -12,27 +12,61 @@
|
||||||
<body>
|
<body>
|
||||||
<script class="testbody" type="text/javascript">
|
<script class="testbody" type="text/javascript">
|
||||||
|
|
||||||
SpecialPowers.pushPrefEnv({"set": [["dom.abortController.enabled", true ]]}, () => {
|
function testWebIDL() {
|
||||||
let ifr = document.createElement("iframe");
|
ok("AbortController" in self, "We have a AbortController prototype");
|
||||||
ifr.src = "file_abort_controller.html";
|
ok("AbortSignal" in self, "We have a AbortSignal prototype");
|
||||||
document.body.appendChild(ifr);
|
|
||||||
|
|
||||||
window.onmessage = function(e) {
|
var ac = new AbortController();
|
||||||
if (e.data.type == "finish") {
|
ok(!!ac, "AbortController can be created");
|
||||||
SimpleTest.finish();
|
ok(ac instanceof AbortController, "AbortController is a AbortController");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.data.type == "check") {
|
ok(!!ac.signal, "AbortController has a signal");
|
||||||
ok(e.data.status, e.data.message);
|
ok(ac.signal instanceof AbortSignal, "abortSignal is a AbortSignal");
|
||||||
return;
|
is(ac.signal.aborted, false, "By default AbortSignal.aborted is false");
|
||||||
}
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
ok(false, "Something when wrong.");
|
function testUpdateData() {
|
||||||
|
var ac = new AbortController();
|
||||||
|
|
||||||
|
is(ac.signal.aborted, false, "By default AbortSignal.aborted is false");
|
||||||
|
|
||||||
|
ac.abort();
|
||||||
|
is(ac.signal.aborted, true, "Signal is aborted");
|
||||||
|
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testAbortEvent() {
|
||||||
|
var ac = new AbortController();
|
||||||
|
ac.signal.onabort = function(e) {
|
||||||
|
is(e.type, "abort", "Abort received");
|
||||||
|
next();
|
||||||
}
|
}
|
||||||
});
|
ac.abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
var steps = [
|
||||||
|
// Simple stuff
|
||||||
|
testWebIDL,
|
||||||
|
testUpdateData,
|
||||||
|
|
||||||
|
// Event propagation
|
||||||
|
testAbortEvent,
|
||||||
|
];
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
if (!steps.length) {
|
||||||
|
SimpleTest.finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var step = steps.shift();
|
||||||
|
step();
|
||||||
|
}
|
||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
next();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -12,28 +12,68 @@
|
||||||
<body>
|
<body>
|
||||||
<script class="testbody" type="text/javascript">
|
<script class="testbody" type="text/javascript">
|
||||||
|
|
||||||
SpecialPowers.pushPrefEnv({"set": [["dom.abortController.enabled", true ],
|
function testAbortedFetch() {
|
||||||
["dom.abortController.fetch.enabled", true]]}, () => {
|
var ac = new AbortController();
|
||||||
let ifr = document.createElement("iframe");
|
ac.abort();
|
||||||
ifr.src = "file_abort_controller_fetch.html";
|
|
||||||
document.body.appendChild(ifr);
|
|
||||||
|
|
||||||
window.onmessage = function(e) {
|
fetch("slow.sjs", { signal: ac.signal }).then(() => {
|
||||||
if (e.data.type == "finish") {
|
ok(false, "Fetch should not return a resolved promise");
|
||||||
SimpleTest.finish();
|
}, e => {
|
||||||
return;
|
is(e.name, "AbortError", "We have an abort error");
|
||||||
}
|
}).then(next);
|
||||||
|
}
|
||||||
|
|
||||||
if (e.data.type == "check") {
|
function testFetchAndAbort() {
|
||||||
ok(e.data.status, e.data.message);
|
var ac = new AbortController();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok(false, "Something when wrong.");
|
var p = fetch("slow.sjs", { signal: ac.signal });
|
||||||
|
ac.abort();
|
||||||
|
|
||||||
|
p.then(() => {
|
||||||
|
ok(false, "Fetch should not return a resolved promise");
|
||||||
|
}, e => {
|
||||||
|
is(e.name, "AbortError", "We have an abort error");
|
||||||
|
}).then(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testWorkerAbortedFetch() {
|
||||||
|
var w = new Worker("worker_abort_controller_fetch.js");
|
||||||
|
w.onmessage = function(e) {
|
||||||
|
ok(e.data, "Abort + Fetch works in workers");
|
||||||
|
next();
|
||||||
}
|
}
|
||||||
});
|
w.postMessage("testWorkerAbortedFetch");
|
||||||
|
}
|
||||||
|
|
||||||
|
function testWorkerFetchAndAbort() {
|
||||||
|
var w = new Worker("worker_abort_controller_fetch.js");
|
||||||
|
w.onmessage = function(e) {
|
||||||
|
ok(e.data, "Abort + Fetch works in workers");
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
w.postMessage("testWorkerFetchAndAbort");
|
||||||
|
}
|
||||||
|
|
||||||
|
var steps = [
|
||||||
|
// fetch + signaling
|
||||||
|
testAbortedFetch,
|
||||||
|
testFetchAndAbort,
|
||||||
|
testWorkerAbortedFetch,
|
||||||
|
testWorkerFetchAndAbort,
|
||||||
|
];
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
if (!steps.length) {
|
||||||
|
SimpleTest.finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var step = steps.shift();
|
||||||
|
step();
|
||||||
|
}
|
||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
next();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -244,16 +244,6 @@ DoesNotParticipateInAutoDirection(const Element* aElement)
|
||||||
aElement->IsInAnonymousSubtree());
|
aElement->IsInAnonymousSubtree());
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
|
||||||
IsBdiWithoutDirAuto(const Element* aElement)
|
|
||||||
{
|
|
||||||
// We are testing for bdi elements without explicit dir="auto", so we can't
|
|
||||||
// use the HasDirAuto() flag, since that will return true for bdi element with
|
|
||||||
// no dir attribute or an invalid dir attribute
|
|
||||||
return (aElement->IsHTMLElement(nsGkAtoms::bdi) &&
|
|
||||||
(!aElement->HasValidDir() || aElement->HasFixedDir()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if aElement is one of the element whose text content should not
|
* Returns true if aElement is one of the element whose text content should not
|
||||||
* affect the direction of ancestors with dir=auto (though it may affect its own
|
* affect the direction of ancestors with dir=auto (though it may affect its own
|
||||||
|
@ -263,7 +253,7 @@ static bool
|
||||||
DoesNotAffectDirectionOfAncestors(const Element* aElement)
|
DoesNotAffectDirectionOfAncestors(const Element* aElement)
|
||||||
{
|
{
|
||||||
return (DoesNotParticipateInAutoDirection(aElement) ||
|
return (DoesNotParticipateInAutoDirection(aElement) ||
|
||||||
IsBdiWithoutDirAuto(aElement) ||
|
aElement->IsHTMLElement(nsGkAtoms::bdi) ||
|
||||||
aElement->HasFixedDir());
|
aElement->HasFixedDir());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
<html>
|
||||||
|
<script>
|
||||||
|
window.onload=function(){
|
||||||
|
document.getElementById('b').textContent='Or';
|
||||||
|
document.getElementById('a').insertBefore(document.getElementById('c'), undefined);
|
||||||
|
document.getElementById('b').dir='ltr';
|
||||||
|
let o=document.getElementById('b');
|
||||||
|
o.parentNode.replaceChild(document.createElement('code'), o);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body dir='auto' id='a'>
|
||||||
|
<bdi id='b' dir='auto'>
|
||||||
|
</bdi>
|
||||||
|
<q id='c'>
|
||||||
|
</html>
|
|
@ -224,3 +224,4 @@ load 1383478.html
|
||||||
load 1383780.html
|
load 1383780.html
|
||||||
pref(clipboard.autocopy,true) load 1385272-1.html
|
pref(clipboard.autocopy,true) load 1385272-1.html
|
||||||
load 1393806.html
|
load 1393806.html
|
||||||
|
load 1400701.html
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include "nsIDOMRange.h"
|
#include "nsIDOMRange.h"
|
||||||
#include "nsIFormControl.h"
|
#include "nsIFormControl.h"
|
||||||
#include "nsIDOMHTMLAreaElement.h"
|
#include "nsIDOMHTMLAreaElement.h"
|
||||||
#include "nsIDOMHTMLAnchorElement.h"
|
|
||||||
#include "nsITransferable.h"
|
#include "nsITransferable.h"
|
||||||
#include "nsComponentManagerUtils.h"
|
#include "nsComponentManagerUtils.h"
|
||||||
#include "nsXPCOM.h"
|
#include "nsXPCOM.h"
|
||||||
|
@ -57,6 +56,7 @@
|
||||||
#include "TabParent.h"
|
#include "TabParent.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
#include "mozilla/dom/HTMLAreaElement.h"
|
#include "mozilla/dom/HTMLAreaElement.h"
|
||||||
|
#include "mozilla/dom/HTMLAnchorElement.h"
|
||||||
#include "nsVariant.h"
|
#include "nsVariant.h"
|
||||||
|
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
@ -474,9 +474,7 @@ DragDataProducer::Produce(DataTransfer* aDataTransfer,
|
||||||
draggedNode = mTarget;
|
draggedNode = mTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMHTMLAreaElement> area; // client-side image map
|
|
||||||
nsCOMPtr<nsIImageLoadingContent> image;
|
nsCOMPtr<nsIImageLoadingContent> image;
|
||||||
nsCOMPtr<nsIDOMHTMLAnchorElement> link;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> selectedImageOrLinkNode;
|
nsCOMPtr<nsIContent> selectedImageOrLinkNode;
|
||||||
GetDraggableSelectionData(selection, mSelectionTargetNode,
|
GetDraggableSelectionData(selection, mSelectionTargetNode,
|
||||||
|
@ -501,19 +499,16 @@ DragDataProducer::Produce(DataTransfer* aDataTransfer,
|
||||||
*aCanDrag = false;
|
*aCanDrag = false;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
area = do_QueryInterface(draggedNode);
|
|
||||||
image = do_QueryInterface(draggedNode);
|
image = do_QueryInterface(draggedNode);
|
||||||
link = do_QueryInterface(draggedNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// set for linked images, and links
|
// set for linked images, and links
|
||||||
nsCOMPtr<nsIContent> linkNode;
|
nsCOMPtr<nsIContent> linkNode;
|
||||||
|
|
||||||
if (area) {
|
RefPtr<HTMLAreaElement> areaElem = HTMLAreaElement::FromContentOrNull(draggedNode);
|
||||||
|
if (areaElem) {
|
||||||
// use the alt text (or, if missing, the href) as the title
|
// use the alt text (or, if missing, the href) as the title
|
||||||
HTMLAreaElement* areaElem = static_cast<HTMLAreaElement*>(area.get());
|
|
||||||
areaElem->GetAttribute(NS_LITERAL_STRING("alt"), mTitleString);
|
areaElem->GetAttribute(NS_LITERAL_STRING("alt"), mTitleString);
|
||||||
if (mTitleString.IsEmpty()) {
|
if (mTitleString.IsEmpty()) {
|
||||||
// this can be a relative link
|
// this can be a relative link
|
||||||
|
@ -638,9 +633,9 @@ DragDataProducer::Produce(DataTransfer* aDataTransfer,
|
||||||
nodeToSerialize = do_QueryInterface(draggedNode);
|
nodeToSerialize = do_QueryInterface(draggedNode);
|
||||||
}
|
}
|
||||||
dragNode = nodeToSerialize;
|
dragNode = nodeToSerialize;
|
||||||
} else if (link) {
|
} else if (draggedNode && draggedNode->IsHTMLElement(nsGkAtoms::a)) {
|
||||||
// set linkNode. The code below will handle this
|
// set linkNode. The code below will handle this
|
||||||
linkNode = do_QueryInterface(link); // XXX test this
|
linkNode = do_QueryInterface(draggedNode); // XXX test this
|
||||||
GetNodeString(draggedNode, mTitleString);
|
GetNodeString(draggedNode, mTitleString);
|
||||||
} else if (parentLink) {
|
} else if (parentLink) {
|
||||||
// parentLink will always be null if there's selected content
|
// parentLink will always be null if there's selected content
|
||||||
|
|
|
@ -666,7 +666,7 @@ BrowserElementChild.prototype = {
|
||||||
_ClickHandler: function(e) {
|
_ClickHandler: function(e) {
|
||||||
|
|
||||||
let isHTMLLink = node =>
|
let isHTMLLink = node =>
|
||||||
((node instanceof Ci.nsIDOMHTMLAnchorElement && node.href) ||
|
((ChromeUtils.getClassName(node) === "HTMLAnchorElement" && node.href) ||
|
||||||
(node instanceof Ci.nsIDOMHTMLAreaElement && node.href) ||
|
(node instanceof Ci.nsIDOMHTMLAreaElement && node.href) ||
|
||||||
node instanceof Ci.nsIDOMHTMLLinkElement);
|
node instanceof Ci.nsIDOMHTMLLinkElement);
|
||||||
|
|
||||||
|
@ -855,7 +855,7 @@ BrowserElementChild.prototype = {
|
||||||
_getSystemCtxMenuData: function(elem) {
|
_getSystemCtxMenuData: function(elem) {
|
||||||
let documentURI =
|
let documentURI =
|
||||||
docShell.QueryInterface(Ci.nsIWebNavigation).currentURI.spec;
|
docShell.QueryInterface(Ci.nsIWebNavigation).currentURI.spec;
|
||||||
if ((elem instanceof Ci.nsIDOMHTMLAnchorElement && elem.href) ||
|
if ((ChromeUtils.getClassName(elem) === "HTMLAnchorElement" && elem.href) ||
|
||||||
(elem instanceof Ci.nsIDOMHTMLAreaElement && elem.href)) {
|
(elem instanceof Ci.nsIDOMHTMLAreaElement && elem.href)) {
|
||||||
return {uri: elem.href,
|
return {uri: elem.href,
|
||||||
documentURI: documentURI,
|
documentURI: documentURI,
|
||||||
|
|
|
@ -8,10 +8,11 @@
|
||||||
#include "IPCBlobInputStreamChild.h"
|
#include "IPCBlobInputStreamChild.h"
|
||||||
#include "IPCBlobInputStreamStorage.h"
|
#include "IPCBlobInputStreamStorage.h"
|
||||||
#include "mozilla/ipc/InputStreamParams.h"
|
#include "mozilla/ipc/InputStreamParams.h"
|
||||||
|
#include "IPCBlobInputStreamThread.h"
|
||||||
#include "nsIAsyncInputStream.h"
|
#include "nsIAsyncInputStream.h"
|
||||||
#include "nsIStreamTransportService.h"
|
#include "nsIAsyncOutputStream.h"
|
||||||
#include "nsITransport.h"
|
#include "nsIPipe.h"
|
||||||
#include "nsNetCID.h"
|
#include "nsStreamUtils.h"
|
||||||
#include "nsStringStream.h"
|
#include "nsStringStream.h"
|
||||||
#include "SlicedInputStream.h"
|
#include "SlicedInputStream.h"
|
||||||
|
|
||||||
|
@ -20,8 +21,6 @@ namespace dom {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
|
|
||||||
|
|
||||||
class InputStreamCallbackRunnable final : public CancelableRunnable
|
class InputStreamCallbackRunnable final : public CancelableRunnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -247,7 +246,7 @@ IPCBlobInputStream::Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mAsyncRemoteStream) {
|
if (mAsyncRemoteStream) {
|
||||||
mAsyncRemoteStream->Close();
|
mAsyncRemoteStream->CloseWithStatus(NS_BASE_STREAM_CLOSED);
|
||||||
mAsyncRemoteStream = nullptr;
|
mAsyncRemoteStream = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,7 +502,7 @@ IPCBlobInputStream::OnInputStreamReady(nsIAsyncInputStream* aStream)
|
||||||
|
|
||||||
nsCOMPtr<nsIEventTarget> callbackEventTarget;
|
nsCOMPtr<nsIEventTarget> callbackEventTarget;
|
||||||
callbackEventTarget.swap(mInputStreamCallbackEventTarget);
|
callbackEventTarget.swap(mInputStreamCallbackEventTarget);
|
||||||
|
|
||||||
// This must be the last operation because the execution of the callback can
|
// This must be the last operation because the execution of the callback can
|
||||||
// be synchronous.
|
// be synchronous.
|
||||||
InputStreamCallbackRunnable::Execute(callback, callbackEventTarget, this);
|
InputStreamCallbackRunnable::Execute(callback, callbackEventTarget, this);
|
||||||
|
@ -643,30 +642,29 @@ IPCBlobInputStream::EnsureAsyncRemoteStream()
|
||||||
|
|
||||||
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(mRemoteStream);
|
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(mRemoteStream);
|
||||||
if (!asyncStream || !nonBlocking) {
|
if (!asyncStream || !nonBlocking) {
|
||||||
nsCOMPtr<nsIStreamTransportService> sts =
|
// Let's make the stream async using the DOMFile thread.
|
||||||
do_GetService(kStreamTransportServiceCID, &rv);
|
nsCOMPtr<nsIAsyncInputStream> pipeIn;
|
||||||
|
nsCOMPtr<nsIAsyncOutputStream> pipeOut;
|
||||||
|
rv = NS_NewPipe2(getter_AddRefs(pipeIn),
|
||||||
|
getter_AddRefs(pipeOut),
|
||||||
|
true, true);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsITransport> transport;
|
RefPtr<IPCBlobInputStreamThread> thread =
|
||||||
rv = sts->CreateInputTransport(mRemoteStream,
|
IPCBlobInputStreamThread::GetOrCreate();
|
||||||
/* aCloseWhenDone */ true,
|
if (NS_WARN_IF(!thread)) {
|
||||||
getter_AddRefs(transport));
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = NS_AsyncCopy(mRemoteStream, pipeOut, thread,
|
||||||
|
NS_ASYNCCOPY_VIA_WRITESEGMENTS);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> wrapper;
|
asyncStream = pipeIn;
|
||||||
rv = transport->OpenInputStream(/* aFlags */ 0,
|
|
||||||
/* aSegmentSize */ 0,
|
|
||||||
/* aSegmentCount */ 0,
|
|
||||||
getter_AddRefs(wrapper));
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
asyncStream = do_QueryInterface(wrapper);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(asyncStream);
|
MOZ_ASSERT(asyncStream);
|
||||||
|
|
|
@ -187,6 +187,8 @@ IPCBlobInputStreamChild::ActorDestroy(IProtocol::ActorDestroyReason aReason)
|
||||||
// thread.
|
// thread.
|
||||||
RefPtr<IPCBlobInputStreamThread> thread =
|
RefPtr<IPCBlobInputStreamThread> thread =
|
||||||
IPCBlobInputStreamThread::GetOrCreate();
|
IPCBlobInputStreamThread::GetOrCreate();
|
||||||
|
MOZ_ASSERT(thread, "We cannot continue without DOMFile thread.");
|
||||||
|
|
||||||
ResetManager();
|
ResetManager();
|
||||||
thread->MigrateActor(this);
|
thread->MigrateActor(this);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -36,7 +36,7 @@ public:
|
||||||
{
|
{
|
||||||
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
|
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
|
||||||
MOZ_ASSERT(gIPCBlobThread);
|
MOZ_ASSERT(gIPCBlobThread);
|
||||||
gIPCBlobThread->Initialize();
|
gIPCBlobThread->InitializeOnMainThread();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -93,7 +93,7 @@ NS_IMPL_ISUPPORTS_INHERITED(MigrateActorRunnable, Runnable,
|
||||||
|
|
||||||
} // anonymous
|
} // anonymous
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(IPCBlobInputStreamThread, nsIObserver)
|
NS_IMPL_ISUPPORTS(IPCBlobInputStreamThread, nsIObserver, nsIEventTarget)
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
IPCBlobInputStreamThread::IsOnFileEventTarget(nsIEventTarget* aEventTarget)
|
IPCBlobInputStreamThread::IsOnFileEventTarget(nsIEventTarget* aEventTarget)
|
||||||
|
@ -115,36 +115,21 @@ IPCBlobInputStreamThread::GetOrCreate()
|
||||||
|
|
||||||
if (!gIPCBlobThread) {
|
if (!gIPCBlobThread) {
|
||||||
gIPCBlobThread = new IPCBlobInputStreamThread();
|
gIPCBlobThread = new IPCBlobInputStreamThread();
|
||||||
gIPCBlobThread->Initialize();
|
if (!gIPCBlobThread->Initialize()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return gIPCBlobThread;
|
return gIPCBlobThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
IPCBlobInputStreamThread::Initialize()
|
IPCBlobInputStreamThread::Initialize()
|
||||||
{
|
{
|
||||||
if (!NS_IsMainThread()) {
|
|
||||||
RefPtr<Runnable> runnable = new ThreadInitializeRunnable();
|
|
||||||
SystemGroup::Dispatch(TaskCategory::Other, runnable.forget());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
||||||
if (NS_WARN_IF(!obs)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv =
|
|
||||||
obs->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIThread> thread;
|
nsCOMPtr<nsIThread> thread;
|
||||||
rv = NS_NewNamedThread("DOM File", getter_AddRefs(thread));
|
nsresult rv = NS_NewNamedThread("DOM File", getter_AddRefs(thread));
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mThread = thread;
|
mThread = thread;
|
||||||
|
@ -156,6 +141,32 @@ IPCBlobInputStreamThread::Initialize()
|
||||||
|
|
||||||
mPendingActors.Clear();
|
mPendingActors.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!NS_IsMainThread()) {
|
||||||
|
RefPtr<Runnable> runnable = new ThreadInitializeRunnable();
|
||||||
|
SystemGroup::Dispatch(TaskCategory::Other, runnable.forget());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeOnMainThread();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IPCBlobInputStreamThread::InitializeOnMainThread()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||||
|
if (NS_WARN_IF(!obs)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult rv =
|
||||||
|
obs->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -205,5 +216,48 @@ IPCBlobInputStreamThread::MigrateActorInternal(IPCBlobInputStreamChild* aActor)
|
||||||
mThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
mThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nsIEventTarget
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(bool)
|
||||||
|
IPCBlobInputStreamThread::IsOnCurrentThreadInfallible()
|
||||||
|
{
|
||||||
|
return mThread->IsOnCurrentThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
IPCBlobInputStreamThread::IsOnCurrentThread(bool* aRetval)
|
||||||
|
{
|
||||||
|
return mThread->IsOnCurrentThread(aRetval);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
IPCBlobInputStreamThread::Dispatch(already_AddRefed<nsIRunnable> aRunnable,
|
||||||
|
uint32_t aFlags)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIRunnable> runnable(aRunnable);
|
||||||
|
|
||||||
|
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
|
||||||
|
|
||||||
|
if (gShutdownHasStarted) {
|
||||||
|
return NS_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mThread->Dispatch(runnable.forget(), aFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
IPCBlobInputStreamThread::DispatchFromScript(nsIRunnable* aRunnable,
|
||||||
|
uint32_t aFlags)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIRunnable> runnable(aRunnable);
|
||||||
|
return Dispatch(runnable.forget(), aFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
IPCBlobInputStreamThread::DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_t)
|
||||||
|
{
|
||||||
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
} // dom namespace
|
} // dom namespace
|
||||||
} // mozilla namespace
|
} // mozilla namespace
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#define mozilla_dom_IPCBlobInputStreamThread_h
|
#define mozilla_dom_IPCBlobInputStreamThread_h
|
||||||
|
|
||||||
#include "nsIObserverService.h"
|
#include "nsIObserverService.h"
|
||||||
|
#include "nsIEventTarget.h"
|
||||||
|
|
||||||
class nsIThread;
|
class nsIThread;
|
||||||
|
|
||||||
|
@ -17,10 +18,12 @@ namespace dom {
|
||||||
class IPCBlobInputStreamChild;
|
class IPCBlobInputStreamChild;
|
||||||
|
|
||||||
class IPCBlobInputStreamThread final : public nsIObserver
|
class IPCBlobInputStreamThread final : public nsIObserver
|
||||||
|
, public nsIEventTarget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NS_DECL_THREADSAFE_ISUPPORTS
|
NS_DECL_THREADSAFE_ISUPPORTS
|
||||||
NS_DECL_NSIOBSERVER
|
NS_DECL_NSIOBSERVER
|
||||||
|
NS_DECL_NSIEVENTTARGET
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
IsOnFileEventTarget(nsIEventTarget* aEventTarget);
|
IsOnFileEventTarget(nsIEventTarget* aEventTarget);
|
||||||
|
@ -31,9 +34,12 @@ public:
|
||||||
void
|
void
|
||||||
MigrateActor(IPCBlobInputStreamChild* aActor);
|
MigrateActor(IPCBlobInputStreamChild* aActor);
|
||||||
|
|
||||||
void
|
bool
|
||||||
Initialize();
|
Initialize();
|
||||||
|
|
||||||
|
void
|
||||||
|
InitializeOnMainThread();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~IPCBlobInputStreamThread() = default;
|
~IPCBlobInputStreamThread() = default;
|
||||||
|
|
||||||
|
|
|
@ -58,10 +58,13 @@ HTMLAnchorElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
|
||||||
nsGenericHTMLElement::IsInteractiveHTMLContent(aIgnoreTabindex);
|
nsGenericHTMLElement::IsInteractiveHTMLContent(aIgnoreTabindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLAnchorElement,
|
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLAnchorElement)
|
||||||
nsGenericHTMLElement,
|
NS_INTERFACE_TABLE_INHERITED(HTMLAnchorElement,
|
||||||
nsIDOMHTMLAnchorElement,
|
Link)
|
||||||
Link)
|
NS_INTERFACE_TABLE_TAIL_INHERITING(nsGenericHTMLElement)
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF_INHERITED(HTMLAnchorElement, Element)
|
||||||
|
NS_IMPL_RELEASE_INHERITED(HTMLAnchorElement, Element)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLAnchorElement)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLAnchorElement)
|
||||||
|
|
||||||
|
@ -83,17 +86,6 @@ HTMLAnchorElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
|
||||||
return HTMLAnchorElementBinding::Wrap(aCx, this, aGivenProto);
|
return HTMLAnchorElementBinding::Wrap(aCx, this, aGivenProto);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_STRING_ATTR(HTMLAnchorElement, Charset, charset)
|
|
||||||
NS_IMPL_STRING_ATTR(HTMLAnchorElement, Coords, coords)
|
|
||||||
NS_IMPL_URI_ATTR(HTMLAnchorElement, Href, href)
|
|
||||||
NS_IMPL_STRING_ATTR(HTMLAnchorElement, Hreflang, hreflang)
|
|
||||||
NS_IMPL_STRING_ATTR(HTMLAnchorElement, Name, name)
|
|
||||||
NS_IMPL_STRING_ATTR(HTMLAnchorElement, Rel, rel)
|
|
||||||
NS_IMPL_STRING_ATTR(HTMLAnchorElement, Rev, rev)
|
|
||||||
NS_IMPL_STRING_ATTR(HTMLAnchorElement, Shape, shape)
|
|
||||||
NS_IMPL_STRING_ATTR(HTMLAnchorElement, Type, type)
|
|
||||||
NS_IMPL_STRING_ATTR(HTMLAnchorElement, Download, download)
|
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
HTMLAnchorElement::TabIndexDefault()
|
HTMLAnchorElement::TabIndexDefault()
|
||||||
{
|
{
|
||||||
|
@ -268,19 +260,12 @@ HTMLAnchorElement::GetLinkTarget(nsAString& aTarget)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
void
|
||||||
HTMLAnchorElement::GetTarget(nsAString& aValue)
|
HTMLAnchorElement::GetTarget(nsAString& aValue)
|
||||||
{
|
{
|
||||||
if (!GetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue)) {
|
if (!GetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue)) {
|
||||||
GetBaseTarget(aValue);
|
GetBaseTarget(aValue);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
HTMLAnchorElement::SetTarget(const nsAString& aValue)
|
|
||||||
{
|
|
||||||
return SetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsDOMTokenList*
|
nsDOMTokenList*
|
||||||
|
@ -292,64 +277,26 @@ HTMLAnchorElement::RelList()
|
||||||
return mRelList;
|
return mRelList;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IMPL_URI_PART(_part) \
|
void
|
||||||
NS_IMETHODIMP \
|
HTMLAnchorElement::GetText(nsAString& aText, mozilla::ErrorResult& aRv)
|
||||||
HTMLAnchorElement::Get##_part(nsAString& a##_part) \
|
|
||||||
{ \
|
|
||||||
Link::Get##_part(a##_part); \
|
|
||||||
return NS_OK; \
|
|
||||||
} \
|
|
||||||
NS_IMETHODIMP \
|
|
||||||
HTMLAnchorElement::Set##_part(const nsAString& a##_part) \
|
|
||||||
{ \
|
|
||||||
Link::Set##_part(a##_part); \
|
|
||||||
return NS_OK; \
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPL_URI_PART(Protocol)
|
|
||||||
IMPL_URI_PART(Host)
|
|
||||||
IMPL_URI_PART(Hostname)
|
|
||||||
IMPL_URI_PART(Pathname)
|
|
||||||
IMPL_URI_PART(Search)
|
|
||||||
IMPL_URI_PART(Port)
|
|
||||||
IMPL_URI_PART(Hash)
|
|
||||||
|
|
||||||
#undef IMPL_URI_PART
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
HTMLAnchorElement::GetText(nsAString& aText)
|
|
||||||
{
|
{
|
||||||
if(!nsContentUtils::GetNodeTextContent(this, true, aText, fallible)) {
|
if (NS_WARN_IF(!nsContentUtils::GetNodeTextContent(this, true, aText, fallible))) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
void
|
||||||
HTMLAnchorElement::SetText(const nsAString& aText)
|
HTMLAnchorElement::SetText(const nsAString& aText, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
return nsContentUtils::SetNodeTextContent(this, aText, false);
|
aRv = nsContentUtils::SetNodeTextContent(this, aText, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
void
|
||||||
HTMLAnchorElement::ToString(nsAString& aSource)
|
HTMLAnchorElement::ToString(nsAString& aSource)
|
||||||
{
|
{
|
||||||
return GetHref(aSource);
|
return GetHref(aSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
HTMLAnchorElement::GetPing(nsAString& aValue)
|
|
||||||
{
|
|
||||||
GetAttr(kNameSpaceID_None, nsGkAtoms::ping, aValue);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
HTMLAnchorElement::SetPing(const nsAString& aValue)
|
|
||||||
{
|
|
||||||
return SetAttr(kNameSpaceID_None, nsGkAtoms::ping, aValue, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<nsIURI>
|
already_AddRefed<nsIURI>
|
||||||
HTMLAnchorElement::GetHrefURI() const
|
HTMLAnchorElement::GetHrefURI() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/dom/Link.h"
|
#include "mozilla/dom/Link.h"
|
||||||
#include "nsGenericHTMLElement.h"
|
#include "nsGenericHTMLElement.h"
|
||||||
#include "nsIDOMHTMLAnchorElement.h"
|
|
||||||
#include "nsDOMTokenList.h"
|
#include "nsDOMTokenList.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -19,7 +18,6 @@ class EventChainPreVisitor;
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
class HTMLAnchorElement final : public nsGenericHTMLElement,
|
class HTMLAnchorElement final : public nsGenericHTMLElement,
|
||||||
public nsIDOMHTMLAnchorElement,
|
|
||||||
public Link
|
public Link
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -39,15 +37,15 @@ public:
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLAnchorElement,
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLAnchorElement,
|
||||||
nsGenericHTMLElement)
|
nsGenericHTMLElement)
|
||||||
|
|
||||||
|
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLAnchorElement, a);
|
||||||
|
|
||||||
virtual int32_t TabIndexDefault() override;
|
virtual int32_t TabIndexDefault() override;
|
||||||
virtual bool Draggable() const override;
|
virtual bool Draggable() const override;
|
||||||
|
|
||||||
// Element
|
// Element
|
||||||
virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
|
virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
|
||||||
|
|
||||||
// nsIDOMHTMLAnchorElement
|
// DOM memory reporter participant
|
||||||
NS_DECL_NSIDOMHTMLANCHORELEMENT
|
|
||||||
|
|
||||||
NS_DECL_ADDSIZEOFEXCLUDINGTHIS
|
NS_DECL_ADDSIZEOFEXCLUDINGTHIS
|
||||||
|
|
||||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||||
|
@ -84,12 +82,15 @@ public:
|
||||||
|
|
||||||
// WebIDL API
|
// WebIDL API
|
||||||
|
|
||||||
// The XPCOM GetHref is OK for us
|
void GetHref(nsAString& aValue)
|
||||||
|
{
|
||||||
|
GetURIAttr(nsGkAtoms::href, nullptr, aValue);
|
||||||
|
}
|
||||||
void SetHref(const nsAString& aValue, mozilla::ErrorResult& rv)
|
void SetHref(const nsAString& aValue, mozilla::ErrorResult& rv)
|
||||||
{
|
{
|
||||||
SetHTMLAttr(nsGkAtoms::href, aValue, rv);
|
SetHTMLAttr(nsGkAtoms::href, aValue, rv);
|
||||||
}
|
}
|
||||||
// The XPCOM GetTarget is OK for us
|
void GetTarget(nsAString& aValue);
|
||||||
void SetTarget(const nsAString& aValue, mozilla::ErrorResult& rv)
|
void SetTarget(const nsAString& aValue, mozilla::ErrorResult& rv)
|
||||||
{
|
{
|
||||||
SetHTMLAttr(nsGkAtoms::target, aValue, rv);
|
SetHTMLAttr(nsGkAtoms::target, aValue, rv);
|
||||||
|
@ -102,7 +103,10 @@ public:
|
||||||
{
|
{
|
||||||
SetHTMLAttr(nsGkAtoms::download, aValue, rv);
|
SetHTMLAttr(nsGkAtoms::download, aValue, rv);
|
||||||
}
|
}
|
||||||
// The XPCOM GetPing is OK for us
|
void GetPing(DOMString& aValue)
|
||||||
|
{
|
||||||
|
GetHTMLAttr(nsGkAtoms::ping, aValue);
|
||||||
|
}
|
||||||
void SetPing(const nsAString& aValue, mozilla::ErrorResult& rv)
|
void SetPing(const nsAString& aValue, mozilla::ErrorResult& rv)
|
||||||
{
|
{
|
||||||
SetHTMLAttr(nsGkAtoms::ping, aValue, rv);
|
SetHTMLAttr(nsGkAtoms::ping, aValue, rv);
|
||||||
|
@ -119,9 +123,9 @@ public:
|
||||||
{
|
{
|
||||||
SetHTMLAttr(nsGkAtoms::referrerpolicy, aValue, rv);
|
SetHTMLAttr(nsGkAtoms::referrerpolicy, aValue, rv);
|
||||||
}
|
}
|
||||||
void GetReferrerPolicy(nsAString& aReferrer)
|
void GetReferrerPolicy(DOMString& aPolicy)
|
||||||
{
|
{
|
||||||
GetEnumAttr(nsGkAtoms::referrerpolicy, EmptyCString().get(), aReferrer);
|
GetEnumAttr(nsGkAtoms::referrerpolicy, EmptyCString().get(), aPolicy);
|
||||||
}
|
}
|
||||||
nsDOMTokenList* RelList();
|
nsDOMTokenList* RelList();
|
||||||
void GetHreflang(DOMString& aValue)
|
void GetHreflang(DOMString& aValue)
|
||||||
|
@ -132,6 +136,11 @@ public:
|
||||||
{
|
{
|
||||||
SetHTMLAttr(nsGkAtoms::hreflang, aValue, rv);
|
SetHTMLAttr(nsGkAtoms::hreflang, aValue, rv);
|
||||||
}
|
}
|
||||||
|
// Needed for docshell
|
||||||
|
void GetType(nsAString& aValue)
|
||||||
|
{
|
||||||
|
GetHTMLAttr(nsGkAtoms::type, aValue);
|
||||||
|
}
|
||||||
void GetType(DOMString& aValue)
|
void GetType(DOMString& aValue)
|
||||||
{
|
{
|
||||||
GetHTMLAttr(nsGkAtoms::type, aValue);
|
GetHTMLAttr(nsGkAtoms::type, aValue);
|
||||||
|
@ -140,11 +149,8 @@ public:
|
||||||
{
|
{
|
||||||
SetHTMLAttr(nsGkAtoms::type, aValue, rv);
|
SetHTMLAttr(nsGkAtoms::type, aValue, rv);
|
||||||
}
|
}
|
||||||
// The XPCOM GetText is OK for us
|
void GetText(nsAString& aValue, mozilla::ErrorResult& rv);
|
||||||
void SetText(const nsAString& aValue, mozilla::ErrorResult& rv)
|
void SetText(const nsAString& aValue, mozilla::ErrorResult& rv);
|
||||||
{
|
|
||||||
rv = SetText(aValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Link::GetOrigin is OK for us
|
// Link::GetOrigin is OK for us
|
||||||
|
|
||||||
|
@ -175,7 +181,6 @@ public:
|
||||||
// Link::Link::GetHash is OK for us
|
// Link::Link::GetHash is OK for us
|
||||||
// Link::Link::SetHash is OK for us
|
// Link::Link::SetHash is OK for us
|
||||||
|
|
||||||
// The XPCOM URI decomposition attributes are fine for us
|
|
||||||
void GetCoords(DOMString& aValue)
|
void GetCoords(DOMString& aValue)
|
||||||
{
|
{
|
||||||
GetHTMLAttr(nsGkAtoms::coords, aValue);
|
GetHTMLAttr(nsGkAtoms::coords, aValue);
|
||||||
|
@ -220,6 +225,7 @@ public:
|
||||||
{
|
{
|
||||||
GetHref(aResult);
|
GetHref(aResult);
|
||||||
}
|
}
|
||||||
|
void ToString(nsAString& aSource);
|
||||||
|
|
||||||
virtual void NodeInfoChanged(nsIDocument* aOldDoc) final override
|
virtual void NodeInfoChanged(nsIDocument* aOldDoc) final override
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,6 +42,7 @@ public:
|
||||||
|
|
||||||
// nsIDOMHTMLAreaElement
|
// nsIDOMHTMLAreaElement
|
||||||
NS_DECL_NSIDOMHTMLAREAELEMENT
|
NS_DECL_NSIDOMHTMLAREAELEMENT
|
||||||
|
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLAreaElement, area);
|
||||||
|
|
||||||
virtual nsresult GetEventTargetParent(
|
virtual nsresult GetEventTargetParent(
|
||||||
EventChainPreVisitor& aVisitor) override;
|
EventChainPreVisitor& aVisitor) override;
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
|
|
||||||
// nsIDOMHTMLLinkElement
|
// nsIDOMHTMLLinkElement
|
||||||
NS_DECL_NSIDOMHTMLLINKELEMENT
|
NS_DECL_NSIDOMHTMLLINKELEMENT
|
||||||
|
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLLinkElement, link);
|
||||||
NS_DECL_ADDSIZEOFEXCLUDINGTHIS
|
NS_DECL_ADDSIZEOFEXCLUDINGTHIS
|
||||||
|
|
||||||
void LinkAdded();
|
void LinkAdded();
|
||||||
|
|
|
@ -8,7 +8,6 @@ with Files("**"):
|
||||||
BUG_COMPONENT = ("Core", "DOM")
|
BUG_COMPONENT = ("Core", "DOM")
|
||||||
|
|
||||||
XPIDL_SOURCES += [
|
XPIDL_SOURCES += [
|
||||||
'nsIDOMHTMLAnchorElement.idl',
|
|
||||||
'nsIDOMHTMLAreaElement.idl',
|
'nsIDOMHTMLAreaElement.idl',
|
||||||
'nsIDOMHTMLBaseElement.idl',
|
'nsIDOMHTMLBaseElement.idl',
|
||||||
'nsIDOMHTMLButtonElement.idl',
|
'nsIDOMHTMLButtonElement.idl',
|
||||||
|
|
|
@ -1,55 +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 "nsIDOMHTMLElement.idl"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The nsIDOMHTMLAnchorElement interface is the interface to a [X]HTML
|
|
||||||
* a element.
|
|
||||||
*
|
|
||||||
* This interface is trying to follow the DOM Level 2 HTML specification:
|
|
||||||
* http://www.w3.org/TR/DOM-Level-2-HTML/
|
|
||||||
*
|
|
||||||
* with changes from the work-in-progress WHATWG HTML specification:
|
|
||||||
* http://www.whatwg.org/specs/web-apps/current-work/
|
|
||||||
*/
|
|
||||||
|
|
||||||
[uuid(339c01c8-2d41-4626-b231-eec63f0241b6)]
|
|
||||||
interface nsIDOMHTMLAnchorElement : nsISupports
|
|
||||||
{
|
|
||||||
attribute DOMString href;
|
|
||||||
attribute DOMString target;
|
|
||||||
|
|
||||||
attribute DOMString ping;
|
|
||||||
attribute DOMString download;
|
|
||||||
|
|
||||||
attribute DOMString rel;
|
|
||||||
attribute DOMString hreflang;
|
|
||||||
attribute DOMString type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An alias for the textContent attribute.
|
|
||||||
*/
|
|
||||||
[Null(Stringify)]
|
|
||||||
attribute DOMString text;
|
|
||||||
|
|
||||||
// URL decomposition IDL attributes
|
|
||||||
attribute DOMString protocol;
|
|
||||||
attribute DOMString host;
|
|
||||||
attribute DOMString hostname;
|
|
||||||
attribute DOMString port;
|
|
||||||
attribute DOMString pathname;
|
|
||||||
attribute DOMString search;
|
|
||||||
attribute DOMString hash;
|
|
||||||
|
|
||||||
|
|
||||||
attribute DOMString charset;
|
|
||||||
attribute DOMString coords;
|
|
||||||
attribute DOMString name;
|
|
||||||
attribute DOMString rev;
|
|
||||||
attribute DOMString shape;
|
|
||||||
|
|
||||||
DOMString toString();
|
|
||||||
};
|
|
|
@ -110,6 +110,7 @@
|
||||||
|
|
||||||
#if defined(XP_WIN) && defined(ACCESSIBILITY)
|
#if defined(XP_WIN) && defined(ACCESSIBILITY)
|
||||||
#include "mozilla/a11y/AccessibleWrap.h"
|
#include "mozilla/a11y/AccessibleWrap.h"
|
||||||
|
#include "mozilla/a11y/Compatibility.h"
|
||||||
#include "mozilla/a11y/nsWinUtils.h"
|
#include "mozilla/a11y/nsWinUtils.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2894,6 +2895,23 @@ TabParent::SetDocShellIsActive(bool isActive)
|
||||||
mDocShellIsActive = isActive;
|
mDocShellIsActive = isActive;
|
||||||
Unused << SendSetDocShellIsActive(isActive, mPreserveLayers, mLayerTreeEpoch);
|
Unused << SendSetDocShellIsActive(isActive, mPreserveLayers, mLayerTreeEpoch);
|
||||||
|
|
||||||
|
// update active accessible documents on windows
|
||||||
|
#if defined(XP_WIN) && defined(ACCESSIBILITY)
|
||||||
|
if (a11y::Compatibility::IsDolphin()) {
|
||||||
|
if (a11y::DocAccessibleParent* tabDoc = GetTopLevelDocAccessible()) {
|
||||||
|
HWND window = tabDoc->GetEmulatedWindowHandle();
|
||||||
|
MOZ_ASSERT(window);
|
||||||
|
if (window) {
|
||||||
|
if (isActive) {
|
||||||
|
a11y::nsWinUtils::ShowNativeWindow(window);
|
||||||
|
} else {
|
||||||
|
a11y::nsWinUtils::HideNativeWindow(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Let's inform the priority manager. This operation can end up with the
|
// Let's inform the priority manager. This operation can end up with the
|
||||||
// changing of the process priority.
|
// changing of the process priority.
|
||||||
ProcessPriorityManager::TabActivityChanged(this, isActive);
|
ProcessPriorityManager::TabActivityChanged(this, isActive);
|
||||||
|
|
|
@ -26,7 +26,7 @@ var dshell = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
addEventListener("click",
|
addEventListener("click",
|
||||||
function(e) {
|
function(e) {
|
||||||
dump(e.target + "\n");
|
dump(e.target + "\n");
|
||||||
if (e.target instanceof Components.interfaces.nsIDOMHTMLAnchorElement &&
|
if (ChromeUtils.getClassName(e.target) === "HTMLAnchorElement" &&
|
||||||
dshell == docShell) {
|
dshell == docShell) {
|
||||||
var retval = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
var retval = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||||
getInterface(Components.interfaces.nsIContentFrameMessageManager).
|
getInterface(Components.interfaces.nsIContentFrameMessageManager).
|
||||||
|
|
|
@ -49,7 +49,7 @@ skip-if = toolkit == 'android' # android(Bug 1189784, timeouts on 4.3 emulator),
|
||||||
[test_getUserMedia_addTrackRemoveTrack.html]
|
[test_getUserMedia_addTrackRemoveTrack.html]
|
||||||
skip-if = android_version == '18' || os == 'linux' # android(Bug 1189784, timeouts on 4.3 emulator), linux bug 1377450
|
skip-if = android_version == '18' || os == 'linux' # android(Bug 1189784, timeouts on 4.3 emulator), linux bug 1377450
|
||||||
[test_getUserMedia_addtrack_removetrack_events.html]
|
[test_getUserMedia_addtrack_removetrack_events.html]
|
||||||
skip-if os == 'linux' && debug # Bug 1389983
|
skip-if = os == 'linux' && debug # Bug 1389983
|
||||||
[test_getUserMedia_basicAudio.html]
|
[test_getUserMedia_basicAudio.html]
|
||||||
[test_getUserMedia_basicVideo.html]
|
[test_getUserMedia_basicVideo.html]
|
||||||
[test_getUserMedia_basicVideo_playAfterLoadedmetadata.html]
|
[test_getUserMedia_basicVideo_playAfterLoadedmetadata.html]
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<style>
|
||||||
|
text::first-letter {}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function js() {
|
||||||
|
a.setAttribute("fill", "url()");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<body onload=js()>
|
||||||
|
<svg>
|
||||||
|
<text id="a">aa</text>
|
|
@ -93,3 +93,4 @@ load 1329093-2.html
|
||||||
load 1347617-1.svg
|
load 1347617-1.svg
|
||||||
load 1347617-2.svg
|
load 1347617-2.svg
|
||||||
load 1347617-3.svg
|
load 1347617-3.svg
|
||||||
|
load 1402798.html
|
||||||
|
|
|
@ -12,9 +12,7 @@
|
||||||
<body>
|
<body>
|
||||||
<script class="testbody" type="text/javascript">
|
<script class="testbody" type="text/javascript">
|
||||||
|
|
||||||
SpecialPowers.pushPrefEnv({"set": [["dom.fetchObserver.enabled", true ],
|
SpecialPowers.pushPrefEnv({"set": [["dom.fetchObserver.enabled", true ]]}, () => {
|
||||||
["dom.abortController.enabled", true ],
|
|
||||||
["dom.abortController.fetch.enabled", true ]]}, () => {
|
|
||||||
let ifr = document.createElement('iframe');
|
let ifr = document.createElement('iframe');
|
||||||
ifr.src = "file_fetch_observer.html";
|
ifr.src = "file_fetch_observer.html";
|
||||||
document.body.appendChild(ifr);
|
document.body.appendChild(ifr);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "WebBrowserPersistLocalDocument.h"
|
#include "WebBrowserPersistLocalDocument.h"
|
||||||
#include "WebBrowserPersistDocumentParent.h"
|
#include "WebBrowserPersistDocumentParent.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/HTMLAnchorElement.h"
|
||||||
#include "mozilla/dom/HTMLInputElement.h"
|
#include "mozilla/dom/HTMLInputElement.h"
|
||||||
#include "mozilla/dom/HTMLObjectElement.h"
|
#include "mozilla/dom/HTMLObjectElement.h"
|
||||||
#include "mozilla/dom/HTMLSharedElement.h"
|
#include "mozilla/dom/HTMLSharedElement.h"
|
||||||
|
@ -20,7 +21,6 @@
|
||||||
#include "nsIDOMAttr.h"
|
#include "nsIDOMAttr.h"
|
||||||
#include "nsIDOMComment.h"
|
#include "nsIDOMComment.h"
|
||||||
#include "nsIDOMDocument.h"
|
#include "nsIDOMDocument.h"
|
||||||
#include "nsIDOMHTMLAnchorElement.h"
|
|
||||||
#include "nsIDOMHTMLAreaElement.h"
|
#include "nsIDOMHTMLAreaElement.h"
|
||||||
#include "nsIDOMHTMLBaseElement.h"
|
#include "nsIDOMHTMLBaseElement.h"
|
||||||
#include "nsIDOMHTMLCollection.h"
|
#include "nsIDOMHTMLCollection.h"
|
||||||
|
@ -941,7 +941,7 @@ PersistNodeFixup::FixupNode(nsIDOMNode *aNodeIn,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix up href and file links in the elements
|
// Fix up href and file links in the elements
|
||||||
nsCOMPtr<nsIDOMHTMLAnchorElement> nodeAsAnchor = do_QueryInterface(aNodeIn);
|
RefPtr<dom::HTMLAnchorElement> nodeAsAnchor = dom::HTMLAnchorElement::FromContent(content);
|
||||||
if (nodeAsAnchor) {
|
if (nodeAsAnchor) {
|
||||||
rv = GetNodeToFixup(aNodeIn, aNodeOut);
|
rv = GetNodeToFixup(aNodeIn, aNodeOut);
|
||||||
if (NS_SUCCEEDED(rv) && *aNodeOut) {
|
if (NS_SUCCEEDED(rv) && *aNodeOut) {
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
* https://dom.spec.whatwg.org/#abortcontroller
|
* https://dom.spec.whatwg.org/#abortcontroller
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[Constructor(), Exposed=(Window,Worker),
|
[Constructor(), Exposed=(Window,Worker)]
|
||||||
Func="AbortController::IsEnabled"]
|
|
||||||
interface AbortController {
|
interface AbortController {
|
||||||
readonly attribute AbortSignal signal;
|
readonly attribute AbortSignal signal;
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
* https://dom.spec.whatwg.org/#abortsignal
|
* https://dom.spec.whatwg.org/#abortsignal
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[Exposed=(Window,Worker),
|
[Exposed=(Window,Worker)]
|
||||||
Func="AbortController::IsEnabled"]
|
|
||||||
interface AbortSignal : EventTarget {
|
interface AbortSignal : EventTarget {
|
||||||
readonly attribute boolean aborted;
|
readonly attribute boolean aborted;
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ interface HTMLAnchorElement : HTMLElement {
|
||||||
[CEReactions, SetterThrows]
|
[CEReactions, SetterThrows]
|
||||||
attribute DOMString type;
|
attribute DOMString type;
|
||||||
|
|
||||||
[CEReactions, SetterThrows]
|
[CEReactions, Throws]
|
||||||
attribute DOMString text;
|
attribute DOMString text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,7 @@ interface Request {
|
||||||
readonly attribute RequestRedirect redirect;
|
readonly attribute RequestRedirect redirect;
|
||||||
readonly attribute DOMString integrity;
|
readonly attribute DOMString integrity;
|
||||||
|
|
||||||
[Func="AbortController::IsEnabledInFetch",
|
[BinaryName="getOrCreateSignal"]
|
||||||
BinaryName="getOrCreateSignal"]
|
|
||||||
readonly attribute AbortSignal signal;
|
readonly attribute AbortSignal signal;
|
||||||
|
|
||||||
[Throws,
|
[Throws,
|
||||||
|
@ -52,7 +51,6 @@ dictionary RequestInit {
|
||||||
RequestRedirect redirect;
|
RequestRedirect redirect;
|
||||||
DOMString integrity;
|
DOMString integrity;
|
||||||
|
|
||||||
[Func="AbortController::IsEnabledInFetch"]
|
|
||||||
AbortSignal? signal;
|
AbortSignal? signal;
|
||||||
|
|
||||||
[Func="FetchObserver::IsEnabled"]
|
[Func="FetchObserver::IsEnabled"]
|
||||||
|
|
|
@ -42,8 +42,6 @@ WORKER_SIMPLE_PREF("dom.requestcontext.enabled", RequestContextEnabled, REQUESTC
|
||||||
WORKER_SIMPLE_PREF("gfx.offscreencanvas.enabled", OffscreenCanvasEnabled, OFFSCREENCANVAS_ENABLED)
|
WORKER_SIMPLE_PREF("gfx.offscreencanvas.enabled", OffscreenCanvasEnabled, OFFSCREENCANVAS_ENABLED)
|
||||||
WORKER_SIMPLE_PREF("dom.webkitBlink.dirPicker.enabled", WebkitBlinkDirectoryPickerEnabled, DOM_WEBKITBLINK_DIRPICKER_WEBKITBLINK)
|
WORKER_SIMPLE_PREF("dom.webkitBlink.dirPicker.enabled", WebkitBlinkDirectoryPickerEnabled, DOM_WEBKITBLINK_DIRPICKER_WEBKITBLINK)
|
||||||
WORKER_SIMPLE_PREF("dom.netinfo.enabled", NetworkInformationEnabled, NETWORKINFORMATION_ENABLED)
|
WORKER_SIMPLE_PREF("dom.netinfo.enabled", NetworkInformationEnabled, NETWORKINFORMATION_ENABLED)
|
||||||
WORKER_SIMPLE_PREF("dom.abortController.enabled", AbortControllerEnabled, ABORTCONTROLLER_ENABLED)
|
|
||||||
WORKER_SIMPLE_PREF("dom.abortController.fetch.enabled", AbortControllerEnabledInFetch, ABORTCONTROLLER_FETCH_ENABLED)
|
|
||||||
WORKER_SIMPLE_PREF("dom.fetchObserver.enabled", FetchObserverEnabled, FETCHOBSERVER_ENABLED)
|
WORKER_SIMPLE_PREF("dom.fetchObserver.enabled", FetchObserverEnabled, FETCHOBSERVER_ENABLED)
|
||||||
WORKER_SIMPLE_PREF("privacy.resistFingerprinting", ResistFingerprintingEnabled, RESISTFINGERPRINTING_ENABLED)
|
WORKER_SIMPLE_PREF("privacy.resistFingerprinting", ResistFingerprintingEnabled, RESISTFINGERPRINTING_ENABLED)
|
||||||
WORKER_SIMPLE_PREF("devtools.enabled", DevToolsEnabled, DEVTOOLS_ENABLED)
|
WORKER_SIMPLE_PREF("devtools.enabled", DevToolsEnabled, DEVTOOLS_ENABLED)
|
||||||
|
|
|
@ -18,11 +18,11 @@
|
||||||
#include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::a, etc.
|
#include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::a, etc.
|
||||||
#include "nsHTMLTags.h"
|
#include "nsHTMLTags.h"
|
||||||
#include "nsIAtom.h" // for nsIAtom
|
#include "nsIAtom.h" // for nsIAtom
|
||||||
#include "nsIDOMHTMLAnchorElement.h" // for nsIDOMHTMLAnchorElement
|
|
||||||
#include "nsIDOMNode.h" // for nsIDOMNode
|
#include "nsIDOMNode.h" // for nsIDOMNode
|
||||||
#include "nsNameSpaceManager.h" // for kNameSpaceID_None
|
#include "nsNameSpaceManager.h" // for kNameSpaceID_None
|
||||||
#include "nsLiteralString.h" // for NS_LITERAL_STRING
|
#include "nsLiteralString.h" // for NS_LITERAL_STRING
|
||||||
#include "nsString.h" // for nsAutoString
|
#include "nsString.h" // for nsAutoString
|
||||||
|
#include "mozilla/dom/HTMLAnchorElement.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
@ -336,14 +336,18 @@ HTMLEditUtils::IsLink(nsINode* aNode)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aNode);
|
MOZ_ASSERT(aNode);
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(aNode);
|
if (!aNode->IsContent()) {
|
||||||
if (anchor) {
|
return false;
|
||||||
nsAutoString tmpText;
|
|
||||||
if (NS_SUCCEEDED(anchor->GetHref(tmpText)) && !tmpText.IsEmpty()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContentOrNull(aNode->AsContent());
|
||||||
|
if (!anchor) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString tmpText;
|
||||||
|
anchor->GetHref(tmpText);
|
||||||
|
return !tmpText.IsEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "nsIDocumentInlines.h"
|
#include "nsIDocumentInlines.h"
|
||||||
#include "nsIDOMEventTarget.h"
|
#include "nsIDOMEventTarget.h"
|
||||||
#include "nsIDOMMouseEvent.h"
|
#include "nsIDOMMouseEvent.h"
|
||||||
#include "nsIDOMHTMLAnchorElement.h"
|
|
||||||
#include "nsISelectionController.h"
|
#include "nsISelectionController.h"
|
||||||
#include "nsIDOMHTMLDocument.h"
|
#include "nsIDOMHTMLDocument.h"
|
||||||
#include "nsILinkHandler.h"
|
#include "nsILinkHandler.h"
|
||||||
|
@ -2594,19 +2593,21 @@ HTMLEditor::InsertLinkAroundSelection(nsIDOMElement* aAnchorElement)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Be sure we were given an anchor element
|
// Be sure we were given an anchor element
|
||||||
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(aAnchorElement);
|
nsCOMPtr<nsIContent> content = do_QueryInterface(aAnchorElement);
|
||||||
|
RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContentOrNull(content);
|
||||||
if (!anchor) {
|
if (!anchor) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoString href;
|
nsAutoString href;
|
||||||
nsresult rv = anchor->GetHref(href);
|
anchor->GetHref(href);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
if (href.IsEmpty()) {
|
if (href.IsEmpty()) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
AutoPlaceholderBatch beginBatching(this);
|
AutoPlaceholderBatch beginBatching(this);
|
||||||
|
|
||||||
// Set all attributes found on the supplied anchor element
|
// Set all attributes found on the supplied anchor element
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
#include "nsIDOMDocument.h"
|
#include "nsIDOMDocument.h"
|
||||||
#include "nsIDOMDocumentFragment.h"
|
#include "nsIDOMDocumentFragment.h"
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMElement.h"
|
||||||
#include "nsIDOMHTMLAnchorElement.h"
|
|
||||||
#include "nsIDOMHTMLFrameElement.h"
|
#include "nsIDOMHTMLFrameElement.h"
|
||||||
#include "nsIDOMHTMLIFrameElement.h"
|
#include "nsIDOMHTMLIFrameElement.h"
|
||||||
#include "nsIDOMHTMLImageElement.h"
|
#include "nsIDOMHTMLImageElement.h"
|
||||||
|
|
|
@ -608,10 +608,6 @@ GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage,
|
||||||
case ImageFormat::SURFACE_TEXTURE:
|
case ImageFormat::SURFACE_TEXTURE:
|
||||||
return BlitImage(static_cast<layers::SurfaceTextureImage*>(srcImage), destSize,
|
return BlitImage(static_cast<layers::SurfaceTextureImage*>(srcImage), destSize,
|
||||||
destOrigin);
|
destOrigin);
|
||||||
|
|
||||||
case ImageFormat::EGLIMAGE:
|
|
||||||
return BlitImage(static_cast<layers::EGLImageImage*>(srcImage), destSize,
|
|
||||||
destOrigin);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
case ImageFormat::MAC_IOSURFACE:
|
case ImageFormat::MAC_IOSURFACE:
|
||||||
|
@ -647,41 +643,6 @@ GLBlitHelper::BlitImage(layers::SurfaceTextureImage* srcImage, const gfx::IntSiz
|
||||||
gfxCriticalError() << "BlitImage(SurfaceTextureImage) not implemented.";
|
gfxCriticalError() << "BlitImage(SurfaceTextureImage) not implemented.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
GLBlitHelper::BlitImage(layers::EGLImageImage* const srcImage,
|
|
||||||
const gfx::IntSize& destSize, const OriginPos destOrigin) const
|
|
||||||
{
|
|
||||||
const EGLImage eglImage = srcImage->GetImage();
|
|
||||||
const EGLSync eglSync = srcImage->GetSync();
|
|
||||||
if (eglSync) {
|
|
||||||
EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), eglSync, 0, LOCAL_EGL_FOREVER);
|
|
||||||
if (status != LOCAL_EGL_CONDITION_SATISFIED) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint tex = 0;
|
|
||||||
mGL->fGenTextures(1, &tex);
|
|
||||||
|
|
||||||
const ScopedSaveMultiTex saveTex(mGL, 1, LOCAL_GL_TEXTURE_2D);
|
|
||||||
mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, tex);
|
|
||||||
mGL->TexParams_SetClampNoMips();
|
|
||||||
mGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, eglImage);
|
|
||||||
|
|
||||||
const auto& srcOrigin = srcImage->GetOriginPos();
|
|
||||||
const bool yFlip = destOrigin != srcOrigin;
|
|
||||||
const gfx::IntRect srcRect(0, 0, 1, 1);
|
|
||||||
const gfx::IntSize srcSize(1, 1);
|
|
||||||
const DrawBlitProg::BaseArgs baseArgs = { destSize, yFlip, srcRect, srcSize };
|
|
||||||
|
|
||||||
const auto& prog = GetDrawBlitProg({kFragHeader_Tex2D, kFragBody_RGBA});
|
|
||||||
MOZ_RELEASE_ASSERT(prog);
|
|
||||||
prog->Draw(baseArgs);
|
|
||||||
|
|
||||||
mGL->fDeleteTextures(1, &tex);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
|
|
@ -28,7 +28,6 @@ class GPUVideoImage;
|
||||||
class PlanarYCbCrImage;
|
class PlanarYCbCrImage;
|
||||||
class SurfaceTextureImage;
|
class SurfaceTextureImage;
|
||||||
class MacIOSurfaceImage;
|
class MacIOSurfaceImage;
|
||||||
class EGLImageImage;
|
|
||||||
class SurfaceDescriptorD3D10;
|
class SurfaceDescriptorD3D10;
|
||||||
class SurfaceDescriptorDXGIYCbCr;
|
class SurfaceDescriptorDXGIYCbCr;
|
||||||
} // namespace layers
|
} // namespace layers
|
||||||
|
@ -133,8 +132,6 @@ public:
|
||||||
// Blit onto the current FB.
|
// Blit onto the current FB.
|
||||||
bool BlitImage(layers::SurfaceTextureImage* stImage, const gfx::IntSize& destSize,
|
bool BlitImage(layers::SurfaceTextureImage* stImage, const gfx::IntSize& destSize,
|
||||||
OriginPos destOrigin) const;
|
OriginPos destOrigin) const;
|
||||||
bool BlitImage(layers::EGLImageImage* eglImage, const gfx::IntSize& destSize,
|
|
||||||
OriginPos destOrigin) const;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
bool BlitImage(layers::MacIOSurfaceImage* srcImage, const gfx::IntSize& destSize,
|
bool BlitImage(layers::MacIOSurfaceImage* srcImage, const gfx::IntSize& destSize,
|
||||||
|
|
|
@ -16,35 +16,6 @@ namespace layers {
|
||||||
|
|
||||||
static RefPtr<GLContext> sSnapshotContext;
|
static RefPtr<GLContext> sSnapshotContext;
|
||||||
|
|
||||||
EGLImageImage::EGLImageImage(EGLImage aImage, EGLSync aSync,
|
|
||||||
const gfx::IntSize& aSize, const gl::OriginPos& aOrigin,
|
|
||||||
bool aOwns)
|
|
||||||
: GLImage(ImageFormat::EGLIMAGE),
|
|
||||||
mImage(aImage),
|
|
||||||
mSync(aSync),
|
|
||||||
mSize(aSize),
|
|
||||||
mPos(aOrigin),
|
|
||||||
mOwns(aOwns)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
EGLImageImage::~EGLImageImage()
|
|
||||||
{
|
|
||||||
if (!mOwns) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mImage) {
|
|
||||||
sEGLLibrary.fDestroyImage(EGL_DISPLAY(), mImage);
|
|
||||||
mImage = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSync) {
|
|
||||||
sEGLLibrary.fDestroySync(EGL_DISPLAY(), mSync);
|
|
||||||
mSync = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<gfx::SourceSurface>
|
already_AddRefed<gfx::SourceSurface>
|
||||||
GLImage::GetAsSourceSurface()
|
GLImage::GetAsSourceSurface()
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,38 +28,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class EGLImageImage : public GLImage {
|
|
||||||
public:
|
|
||||||
EGLImageImage(EGLImage aImage, EGLSync aSync,
|
|
||||||
const gfx::IntSize& aSize, const gl::OriginPos& aOrigin,
|
|
||||||
bool aOwns);
|
|
||||||
|
|
||||||
gfx::IntSize GetSize() override { return mSize; }
|
|
||||||
gl::OriginPos GetOriginPos() const {
|
|
||||||
return mPos;
|
|
||||||
}
|
|
||||||
EGLImage GetImage() const {
|
|
||||||
return mImage;
|
|
||||||
}
|
|
||||||
EGLSync GetSync() const {
|
|
||||||
return mSync;
|
|
||||||
}
|
|
||||||
|
|
||||||
EGLImageImage* AsEGLImageImage() override {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual ~EGLImageImage();
|
|
||||||
|
|
||||||
private:
|
|
||||||
EGLImage mImage;
|
|
||||||
EGLSync mSync;
|
|
||||||
gfx::IntSize mSize;
|
|
||||||
gl::OriginPos mPos;
|
|
||||||
bool mOwns;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
|
||||||
class SurfaceTextureImage : public GLImage {
|
class SurfaceTextureImage : public GLImage {
|
||||||
|
|
|
@ -174,7 +174,6 @@ protected:
|
||||||
|
|
||||||
/* Forward declarations for Image derivatives. */
|
/* Forward declarations for Image derivatives. */
|
||||||
class GLImage;
|
class GLImage;
|
||||||
class EGLImageImage;
|
|
||||||
class SharedRGBImage;
|
class SharedRGBImage;
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
class SurfaceTextureImage;
|
class SurfaceTextureImage;
|
||||||
|
@ -233,7 +232,6 @@ public:
|
||||||
virtual TextureClient* GetTextureClient(KnowsCompositor* aForwarder) { return nullptr; }
|
virtual TextureClient* GetTextureClient(KnowsCompositor* aForwarder) { return nullptr; }
|
||||||
|
|
||||||
/* Access to derived classes. */
|
/* Access to derived classes. */
|
||||||
virtual EGLImageImage* AsEGLImageImage() { return nullptr; }
|
|
||||||
virtual GLImage* AsGLImage() { return nullptr; }
|
virtual GLImage* AsGLImage() { return nullptr; }
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
virtual SurfaceTextureImage* AsSurfaceTextureImage() { return nullptr; }
|
virtual SurfaceTextureImage* AsSurfaceTextureImage() { return nullptr; }
|
||||||
|
|
|
@ -55,11 +55,6 @@ enum class ImageFormat {
|
||||||
*/
|
*/
|
||||||
SURFACE_TEXTURE,
|
SURFACE_TEXTURE,
|
||||||
|
|
||||||
/**
|
|
||||||
* An EGL Image that can be shared across threads.
|
|
||||||
*/
|
|
||||||
EGLIMAGE,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The D3D9_RGB32_TEXTURE format creates a D3D9SurfaceImage, and wraps a
|
* The D3D9_RGB32_TEXTURE format creates a D3D9SurfaceImage, and wraps a
|
||||||
* IDirect3DTexture9 in RGB32 layout.
|
* IDirect3DTexture9 in RGB32 layout.
|
||||||
|
|
|
@ -400,8 +400,6 @@ AppendToString(std::stringstream& aStream, ImageFormat format,
|
||||||
aStream << "ImageFormat::MAC_IOSURFACE"; break;
|
aStream << "ImageFormat::MAC_IOSURFACE"; break;
|
||||||
case ImageFormat::SURFACE_TEXTURE:
|
case ImageFormat::SURFACE_TEXTURE:
|
||||||
aStream << "ImageFormat::SURFACE_TEXTURE"; break;
|
aStream << "ImageFormat::SURFACE_TEXTURE"; break;
|
||||||
case ImageFormat::EGLIMAGE:
|
|
||||||
aStream << "ImageFormat::EGLIMAGE"; break;
|
|
||||||
case ImageFormat::D3D9_RGB32_TEXTURE:
|
case ImageFormat::D3D9_RGB32_TEXTURE:
|
||||||
aStream << "ImageFormat::D3D9_RBG32_TEXTURE"; break;
|
aStream << "ImageFormat::D3D9_RBG32_TEXTURE"; break;
|
||||||
case ImageFormat::OVERLAY_IMAGE:
|
case ImageFormat::OVERLAY_IMAGE:
|
||||||
|
|
|
@ -118,24 +118,14 @@ ImageClient::CreateTextureClientForImage(Image* aImage, KnowsCompositor* aForwar
|
||||||
if (!status) {
|
if (!status) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
} else if (aImage->GetFormat() == ImageFormat::SURFACE_TEXTURE ||
|
|
||||||
aImage->GetFormat() == ImageFormat::EGLIMAGE) {
|
|
||||||
gfx::IntSize size = aImage->GetSize();
|
|
||||||
|
|
||||||
if (aImage->GetFormat() == ImageFormat::EGLIMAGE) {
|
|
||||||
EGLImageImage* typedImage = aImage->AsEGLImageImage();
|
|
||||||
texture = EGLImageTextureData::CreateTextureClient(
|
|
||||||
typedImage, size, aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
|
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
} else if (aImage->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
|
} else if (aImage->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
|
||||||
SurfaceTextureImage* typedImage = aImage->AsSurfaceTextureImage();
|
gfx::IntSize size = aImage->GetSize();
|
||||||
texture = AndroidSurfaceTextureData::CreateTextureClient(
|
SurfaceTextureImage* typedImage = aImage->AsSurfaceTextureImage();
|
||||||
typedImage->GetHandle(), size, typedImage->GetContinuous(), typedImage->GetOriginPos(),
|
texture = AndroidSurfaceTextureData::CreateTextureClient(
|
||||||
aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
|
typedImage->GetHandle(), size, typedImage->GetContinuous(), typedImage->GetOriginPos(),
|
||||||
|
aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
|
||||||
MOZ_ASSERT(false, "Bad ImageFormat.");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
RefPtr<gfx::SourceSurface> surface = aImage->GetAsSourceSurface();
|
RefPtr<gfx::SourceSurface> surface = aImage->GetAsSourceSurface();
|
||||||
MOZ_ASSERT(surface);
|
MOZ_ASSERT(surface);
|
||||||
|
|
|
@ -17,62 +17,6 @@ namespace layers {
|
||||||
|
|
||||||
class CompositableForwarder;
|
class CompositableForwarder;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
|
||||||
// EGLImage
|
|
||||||
|
|
||||||
EGLImageTextureData::EGLImageTextureData(EGLImageImage* aImage, gfx::IntSize aSize)
|
|
||||||
: mImage(aImage)
|
|
||||||
, mSize(aSize)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<TextureClient>
|
|
||||||
EGLImageTextureData::CreateTextureClient(EGLImageImage* aImage, gfx::IntSize aSize,
|
|
||||||
LayersIPCChannel* aAllocator, TextureFlags aFlags)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(XRE_IsParentProcess(),
|
|
||||||
"Can't pass an `EGLImage` between processes.");
|
|
||||||
|
|
||||||
if (!aImage || !XRE_IsParentProcess()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX - This is quite sad and slow.
|
|
||||||
aFlags |= TextureFlags::DEALLOCATE_CLIENT;
|
|
||||||
|
|
||||||
if (aImage->GetOriginPos() == gl::OriginPos::BottomLeft) {
|
|
||||||
aFlags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TextureClient::CreateWithData(
|
|
||||||
new EGLImageTextureData(aImage, aSize),
|
|
||||||
aFlags, aAllocator
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
EGLImageTextureData::FillInfo(TextureData::Info& aInfo) const
|
|
||||||
{
|
|
||||||
aInfo.size = mSize;
|
|
||||||
aInfo.format = gfx::SurfaceFormat::UNKNOWN;
|
|
||||||
aInfo.hasIntermediateBuffer = false;
|
|
||||||
aInfo.hasSynchronization = false;
|
|
||||||
aInfo.supportsMoz2D = false;
|
|
||||||
aInfo.canExposeMappedData = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
EGLImageTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
|
|
||||||
{
|
|
||||||
const bool hasAlpha = true;
|
|
||||||
aOutDescriptor =
|
|
||||||
EGLImageDescriptor((uintptr_t)mImage->GetImage(),
|
|
||||||
(uintptr_t)mImage->GetSync(),
|
|
||||||
mImage->GetSize(), hasAlpha);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// AndroidSurface
|
// AndroidSurface
|
||||||
|
|
||||||
|
|
|
@ -20,34 +20,6 @@ namespace mozilla {
|
||||||
|
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
class EGLImageTextureData : public TextureData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
static already_AddRefed<TextureClient>
|
|
||||||
CreateTextureClient(EGLImageImage* aImage, gfx::IntSize aSize,
|
|
||||||
LayersIPCChannel* aAllocator, TextureFlags aFlags);
|
|
||||||
|
|
||||||
virtual void FillInfo(TextureData::Info& aInfo) const override;
|
|
||||||
|
|
||||||
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
|
|
||||||
|
|
||||||
virtual void Deallocate(LayersIPCChannel*) override { mImage = nullptr; }
|
|
||||||
|
|
||||||
virtual void Forget(LayersIPCChannel*) override { mImage = nullptr; }
|
|
||||||
|
|
||||||
// Unused functions.
|
|
||||||
virtual bool Lock(OpenMode) override { return true; }
|
|
||||||
|
|
||||||
virtual void Unlock() override {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
EGLImageTextureData(EGLImageImage* aImage, gfx::IntSize aSize);
|
|
||||||
|
|
||||||
RefPtr<EGLImageImage> mImage;
|
|
||||||
const gfx::IntSize mSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
|
||||||
class AndroidSurfaceTextureData : public TextureData
|
class AndroidSurfaceTextureData : public TextureData
|
||||||
|
|
|
@ -608,12 +608,15 @@ WebRenderDebugPrefChangeCallback(const char* aPrefName, void*)
|
||||||
if (Preferences::GetBool(WR_DEBUG_PREF".profiler", false)) {
|
if (Preferences::GetBool(WR_DEBUG_PREF".profiler", false)) {
|
||||||
flags |= (1 << 0);
|
flags |= (1 << 0);
|
||||||
}
|
}
|
||||||
if (Preferences::GetBool(WR_DEBUG_PREF".texture-cache", false)) {
|
if (Preferences::GetBool(WR_DEBUG_PREF".render-targets", false)) {
|
||||||
flags |= (1 << 1);
|
flags |= (1 << 1);
|
||||||
}
|
}
|
||||||
if (Preferences::GetBool(WR_DEBUG_PREF".render-targets", false)) {
|
if (Preferences::GetBool(WR_DEBUG_PREF".texture-cache", false)) {
|
||||||
flags |= (1 << 2);
|
flags |= (1 << 2);
|
||||||
}
|
}
|
||||||
|
if (Preferences::GetBool(WR_DEBUG_PREF".alpha-primitives", false)) {
|
||||||
|
flags |= (1 << 3);
|
||||||
|
}
|
||||||
|
|
||||||
gfx::gfxVars::SetWebRenderDebugFlags(flags);
|
gfx::gfxVars::SetWebRenderDebugFlags(flags);
|
||||||
}
|
}
|
||||||
|
|
|
@ -600,7 +600,7 @@ UnknownPropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleV
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
UnknownStrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
|
UnknownStrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||||
ObjectOpResult& result)
|
ObjectOpResult& result)
|
||||||
{
|
{
|
||||||
JS_ReportErrorASCII(cx, "setter could not be wrapped via CPOWs");
|
JS_ReportErrorASCII(cx, "setter could not be wrapped via CPOWs");
|
||||||
|
|
|
@ -379,13 +379,11 @@ typedef bool
|
||||||
/**
|
/**
|
||||||
* Set a property named by id in obj, treating the assignment as strict
|
* Set a property named by id in obj, treating the assignment as strict
|
||||||
* mode code if strict is true. Note the jsid id type -- id may be a string
|
* mode code if strict is true. Note the jsid id type -- id may be a string
|
||||||
* (Unicode property identifier) or an int (element index). The *vp out
|
* (Unicode property identifier) or an int (element index).
|
||||||
* parameter, on success, is the new property value after the
|
|
||||||
* set.
|
|
||||||
*/
|
*/
|
||||||
typedef bool
|
typedef bool
|
||||||
(* JSSetterOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
|
(* JSSetterOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
|
||||||
JS::MutableHandleValue vp, JS::ObjectOpResult& result);
|
JS::HandleValue v, JS::ObjectOpResult& result);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a property named by id in obj.
|
* Delete a property named by id in obj.
|
||||||
|
|
|
@ -642,7 +642,7 @@ array_length_getter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleV
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
array_length_setter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
|
array_length_setter(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||||
ObjectOpResult& result)
|
ObjectOpResult& result)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(id == NameToId(cx->names().length));
|
MOZ_ASSERT(id == NameToId(cx->names().length));
|
||||||
|
@ -651,14 +651,14 @@ array_length_setter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleV
|
||||||
// This array .length property was found on the prototype
|
// This array .length property was found on the prototype
|
||||||
// chain. Ideally the setter should not have been called, but since
|
// chain. Ideally the setter should not have been called, but since
|
||||||
// we're here, do an impression of SetPropertyByDefining.
|
// we're here, do an impression of SetPropertyByDefining.
|
||||||
return DefineDataProperty(cx, obj, id, vp, JSPROP_ENUMERATE, result);
|
return DefineDataProperty(cx, obj, id, v, JSPROP_ENUMERATE, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
|
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
|
||||||
MOZ_ASSERT(arr->lengthIsWritable(),
|
MOZ_ASSERT(arr->lengthIsWritable(),
|
||||||
"setter shouldn't be called if property is non-writable");
|
"setter shouldn't be called if property is non-writable");
|
||||||
|
|
||||||
return ArraySetLength(cx, arr, id, JSPROP_PERMANENT, vp, result);
|
return ArraySetLength(cx, arr, id, JSPROP_PERMANENT, v, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ReverseIndexComparator
|
struct ReverseIndexComparator
|
||||||
|
|
|
@ -1327,7 +1327,6 @@ JSContext::JSContext(JSRuntime* runtime, const JS::ContextOptions& options)
|
||||||
suppressProfilerSampling(false),
|
suppressProfilerSampling(false),
|
||||||
tempLifoAlloc_((size_t)TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
tempLifoAlloc_((size_t)TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||||
debuggerMutations(0),
|
debuggerMutations(0),
|
||||||
propertyRemovals(0),
|
|
||||||
ionPcScriptCache(nullptr),
|
ionPcScriptCache(nullptr),
|
||||||
throwing(false),
|
throwing(false),
|
||||||
overRecursed_(false),
|
overRecursed_(false),
|
||||||
|
|
|
@ -613,13 +613,6 @@ struct JSContext : public JS::RootingContext,
|
||||||
|
|
||||||
js::ThreadLocalData<uint32_t> debuggerMutations;
|
js::ThreadLocalData<uint32_t> debuggerMutations;
|
||||||
|
|
||||||
/*
|
|
||||||
* The propertyRemovals counter is incremented for every JSObject::clear,
|
|
||||||
* and for each JSObject::remove method call that frees a slot in the given
|
|
||||||
* object. See js_NativeGet and js_NativeSet in jsobj.cpp.
|
|
||||||
*/
|
|
||||||
js::ThreadLocalData<uint32_t> propertyRemovals;
|
|
||||||
|
|
||||||
// Cache for jit::GetPcScript().
|
// Cache for jit::GetPcScript().
|
||||||
js::ThreadLocalData<js::jit::PcScriptCache*> ionPcScriptCache;
|
js::ThreadLocalData<js::jit::PcScriptCache*> ionPcScriptCache;
|
||||||
|
|
||||||
|
|
|
@ -365,14 +365,14 @@ CallJSGetterOp(JSContext* cx, GetterOp op, HandleObject obj, HandleId id,
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE bool
|
MOZ_ALWAYS_INLINE bool
|
||||||
CallJSSetterOp(JSContext* cx, SetterOp op, HandleObject obj, HandleId id, MutableHandleValue vp,
|
CallJSSetterOp(JSContext* cx, SetterOp op, HandleObject obj, HandleId id, HandleValue v,
|
||||||
ObjectOpResult& result)
|
ObjectOpResult& result)
|
||||||
{
|
{
|
||||||
if (!CheckRecursionLimit(cx))
|
if (!CheckRecursionLimit(cx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
assertSameCompartment(cx, obj, id, vp);
|
assertSameCompartment(cx, obj, id, v);
|
||||||
return op(cx, obj, id, vp, result);
|
return op(cx, obj, id, v, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
|
|
|
@ -195,10 +195,8 @@ js::SetPropertyIgnoringNamedGetter(JSContext* cx, HandleObject obj, HandleId id,
|
||||||
RootedObject receiverObj(cx, &receiver.toObject());
|
RootedObject receiverObj(cx, &receiver.toObject());
|
||||||
|
|
||||||
// Nonstandard SpiderMonkey special case: setter ops.
|
// Nonstandard SpiderMonkey special case: setter ops.
|
||||||
if (SetterOp setter = ownDesc.setter()) {
|
if (SetterOp setter = ownDesc.setter())
|
||||||
RootedValue valCopy(cx, v);
|
return CallJSSetterOp(cx, setter, receiverObj, id, v, result);
|
||||||
return CallJSSetterOp(cx, setter, receiverObj, id, &valCopy, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Steps 5.c-d.
|
// Steps 5.c-d.
|
||||||
Rooted<PropertyDescriptor> existingDescriptor(cx);
|
Rooted<PropertyDescriptor> existingDescriptor(cx);
|
||||||
|
|
|
@ -476,7 +476,7 @@ MappedArgGetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
MappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
|
MappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||||
ObjectOpResult& result)
|
ObjectOpResult& result)
|
||||||
{
|
{
|
||||||
if (!obj->is<MappedArgumentsObject>())
|
if (!obj->is<MappedArgumentsObject>())
|
||||||
|
@ -499,9 +499,9 @@ MappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue
|
||||||
if (JSID_IS_INT(id)) {
|
if (JSID_IS_INT(id)) {
|
||||||
unsigned arg = unsigned(JSID_TO_INT(id));
|
unsigned arg = unsigned(JSID_TO_INT(id));
|
||||||
if (arg < argsobj->initialLength() && !argsobj->isElementDeleted(arg)) {
|
if (arg < argsobj->initialLength() && !argsobj->isElementDeleted(arg)) {
|
||||||
argsobj->setElement(cx, arg, vp);
|
argsobj->setElement(cx, arg, v);
|
||||||
if (arg < script->functionNonDelazifying()->nargs())
|
if (arg < script->functionNonDelazifying()->nargs())
|
||||||
TypeScript::SetArgument(cx, script, arg, vp);
|
TypeScript::SetArgument(cx, script, arg, v);
|
||||||
return result.succeed();
|
return result.succeed();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -518,7 +518,7 @@ MappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue
|
||||||
*/
|
*/
|
||||||
ObjectOpResult ignored;
|
ObjectOpResult ignored;
|
||||||
return NativeDeleteProperty(cx, argsobj, id, ignored) &&
|
return NativeDeleteProperty(cx, argsobj, id, ignored) &&
|
||||||
NativeDefineDataProperty(cx, argsobj, id, vp, attrs, result);
|
NativeDefineDataProperty(cx, argsobj, id, v, attrs, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -726,7 +726,7 @@ UnmappedArgGetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleVal
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
UnmappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
|
UnmappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||||
ObjectOpResult& result)
|
ObjectOpResult& result)
|
||||||
{
|
{
|
||||||
if (!obj->is<UnmappedArgumentsObject>())
|
if (!obj->is<UnmappedArgumentsObject>())
|
||||||
|
@ -744,7 +744,7 @@ UnmappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleVal
|
||||||
if (JSID_IS_INT(id)) {
|
if (JSID_IS_INT(id)) {
|
||||||
unsigned arg = unsigned(JSID_TO_INT(id));
|
unsigned arg = unsigned(JSID_TO_INT(id));
|
||||||
if (arg < argsobj->initialLength()) {
|
if (arg < argsobj->initialLength()) {
|
||||||
argsobj->setElement(cx, arg, vp);
|
argsobj->setElement(cx, arg, v);
|
||||||
return result.succeed();
|
return result.succeed();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -758,7 +758,7 @@ UnmappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleVal
|
||||||
*/
|
*/
|
||||||
ObjectOpResult ignored;
|
ObjectOpResult ignored;
|
||||||
return NativeDeleteProperty(cx, argsobj, id, ignored) &&
|
return NativeDeleteProperty(cx, argsobj, id, ignored) &&
|
||||||
NativeDefineDataProperty(cx, argsobj, id, vp, attrs, result);
|
NativeDefineDataProperty(cx, argsobj, id, v, attrs, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
|
|
|
@ -2503,22 +2503,8 @@ NativeSetExistingDataProperty(JSContext* cx, HandleNativeObject obj, HandleShape
|
||||||
|
|
||||||
MOZ_ASSERT(!obj->is<WithEnvironmentObject>()); // See bug 1128681.
|
MOZ_ASSERT(!obj->is<WithEnvironmentObject>()); // See bug 1128681.
|
||||||
|
|
||||||
uint32_t sample = cx->propertyRemovals;
|
|
||||||
RootedId id(cx, shape->propid());
|
RootedId id(cx, shape->propid());
|
||||||
RootedValue value(cx, v);
|
return CallJSSetterOp(cx, shape->setterOp(), obj, id, v, result);
|
||||||
if (!CallJSSetterOp(cx, shape->setterOp(), obj, id, &value, result))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Update any slot for the shape with the value produced by the setter,
|
|
||||||
// unless the setter deleted the shape.
|
|
||||||
if (shape->hasSlot() &&
|
|
||||||
(MOZ_LIKELY(cx->propertyRemovals == sample) ||
|
|
||||||
obj->contains(cx, shape)))
|
|
||||||
{
|
|
||||||
obj->setSlot(shape->slot(), value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true; // result is populated by CallJSSetterOp above.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2729,8 +2715,7 @@ SetExistingProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleVa
|
||||||
if (shape->hasDefaultSetter())
|
if (shape->hasDefaultSetter())
|
||||||
return result.succeed();
|
return result.succeed();
|
||||||
|
|
||||||
RootedValue valCopy(cx, v);
|
return CallJSSetterOp(cx, shape->setterOp(), obj, id, v, result);
|
||||||
return CallJSSetterOp(cx, shape->setterOp(), obj, id, &valCopy, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shadow pobj[id] by defining a new data property receiver[id].
|
// Shadow pobj[id] by defining a new data property receiver[id].
|
||||||
|
|
|
@ -855,13 +855,8 @@ NativeObject::putProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
|
||||||
* to will botch an assertion in JSObject::freeSlot) if the new last
|
* to will botch an assertion in JSObject::freeSlot) if the new last
|
||||||
* property (shape here) has a slotSpan that does not cover it.
|
* property (shape here) has a slotSpan that does not cover it.
|
||||||
*/
|
*/
|
||||||
if (hadSlot && !shape->hasSlot()) {
|
if (hadSlot && !shape->hasSlot() && oldSlot < obj->slotSpan())
|
||||||
if (oldSlot < obj->slotSpan())
|
obj->freeSlot(cx, oldSlot);
|
||||||
obj->freeSlot(cx, oldSlot);
|
|
||||||
/* Note: The optimization based on propertyRemovals is only relevant to the active thread. */
|
|
||||||
if (!cx->helperThread())
|
|
||||||
++cx->propertyRemovals;
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->checkShapeConsistency();
|
obj->checkShapeConsistency();
|
||||||
|
|
||||||
|
@ -959,11 +954,8 @@ NativeObject::removeProperty(JSContext* cx, HandleNativeObject obj, jsid id_)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If shape has a slot, free its slot number. */
|
/* If shape has a slot, free its slot number. */
|
||||||
if (shape->hasSlot()) {
|
if (shape->hasSlot())
|
||||||
obj->freeSlot(cx, shape->slot());
|
obj->freeSlot(cx, shape->slot());
|
||||||
if (!cx->helperThread())
|
|
||||||
++cx->propertyRemovals;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A dictionary-mode object owns mutable, unique shapes on a non-circular
|
* A dictionary-mode object owns mutable, unique shapes on a non-circular
|
||||||
|
@ -1042,8 +1034,6 @@ NativeObject::clear(JSContext* cx, HandleNativeObject obj)
|
||||||
|
|
||||||
JS_ALWAYS_TRUE(obj->setLastProperty(cx, shape));
|
JS_ALWAYS_TRUE(obj->setLastProperty(cx, shape));
|
||||||
|
|
||||||
if (!cx->helperThread())
|
|
||||||
++cx->propertyRemovals;
|
|
||||||
obj->checkShapeConsistency();
|
obj->checkShapeConsistency();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -440,14 +440,14 @@ sandbox_moved(JSObject* obj, JSObject* old)
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
writeToProto_setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
|
writeToProto_setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
|
||||||
JS::MutableHandleValue vp, JS::ObjectOpResult& result)
|
JS::HandleValue v, JS::ObjectOpResult& result)
|
||||||
{
|
{
|
||||||
RootedObject proto(cx);
|
RootedObject proto(cx);
|
||||||
if (!JS_GetPrototype(cx, obj, &proto))
|
if (!JS_GetPrototype(cx, obj, &proto))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
RootedValue receiver(cx, ObjectValue(*proto));
|
RootedValue receiver(cx, ObjectValue(*proto));
|
||||||
return JS_ForwardSetPropertyTo(cx, proto, id, vp, receiver, result);
|
return JS_ForwardSetPropertyTo(cx, proto, id, v, receiver, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|
|
@ -762,7 +762,7 @@ nsIPresShell::nsIPresShell()
|
||||||
, mFrozen(false)
|
, mFrozen(false)
|
||||||
, mIsFirstPaint(false)
|
, mIsFirstPaint(false)
|
||||||
, mObservesMutationsForPrint(false)
|
, mObservesMutationsForPrint(false)
|
||||||
, mSuppressInterruptibleReflows(false)
|
, mWasLastReflowInterrupted(false)
|
||||||
, mScrollPositionClampingScrollPortSizeSet(false)
|
, mScrollPositionClampingScrollPortSizeSet(false)
|
||||||
, mNeedLayoutFlush(true)
|
, mNeedLayoutFlush(true)
|
||||||
, mNeedStyleFlush(true)
|
, mNeedStyleFlush(true)
|
||||||
|
@ -4197,7 +4197,7 @@ PresShell::DoFlushPendingNotifications(mozilla::ChangesToFlush aFlush)
|
||||||
// worry about them. They can't be triggered during reflow, so we should
|
// worry about them. They can't be triggered during reflow, so we should
|
||||||
// be good.
|
// be good.
|
||||||
|
|
||||||
if (flushType >= (mSuppressInterruptibleReflows
|
if (flushType >= (SuppressInterruptibleReflows()
|
||||||
? FlushType::Layout
|
? FlushType::Layout
|
||||||
: FlushType::InterruptibleLayout) &&
|
: FlushType::InterruptibleLayout) &&
|
||||||
!mIsDestroying) {
|
!mIsDestroying) {
|
||||||
|
@ -4232,7 +4232,7 @@ PresShell::DoFlushPendingNotifications(mozilla::ChangesToFlush aFlush)
|
||||||
if (!didLayoutFlush && flushType >= FlushType::InterruptibleLayout &&
|
if (!didLayoutFlush && flushType >= FlushType::InterruptibleLayout &&
|
||||||
!mIsDestroying) {
|
!mIsDestroying) {
|
||||||
// We suppressed this flush either due to it not being safe to flush,
|
// We suppressed this flush either due to it not being safe to flush,
|
||||||
// or due to mSuppressInterruptibleReflows. Either way, the
|
// or due to SuppressInterruptibleReflows(). Either way, the
|
||||||
// mNeedLayoutFlush flag needs to be re-set.
|
// mNeedLayoutFlush flag needs to be re-set.
|
||||||
SetNeedLayoutFlush();
|
SetNeedLayoutFlush();
|
||||||
}
|
}
|
||||||
|
@ -9457,7 +9457,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
|
||||||
// Any FlushPendingNotifications with interruptible reflows
|
// Any FlushPendingNotifications with interruptible reflows
|
||||||
// should be suppressed now. We don't want to do extra reflow work
|
// should be suppressed now. We don't want to do extra reflow work
|
||||||
// before our reflow event happens.
|
// before our reflow event happens.
|
||||||
mSuppressInterruptibleReflows = true;
|
mWasLastReflowInterrupted = true;
|
||||||
MaybeScheduleReflow();
|
MaybeScheduleReflow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1581,6 +1581,21 @@ public:
|
||||||
mFontSizeInflationEnabledIsDirty = true;
|
mFontSizeInflationEnabledIsDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the most recent interruptible reflow was interrupted.
|
||||||
|
*/
|
||||||
|
bool IsReflowInterrupted() const {
|
||||||
|
return mWasLastReflowInterrupted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the the interruptible reflows have to be suppressed.
|
||||||
|
* This may happen only if if the most recent reflow was interrupted.
|
||||||
|
*/
|
||||||
|
bool SuppressInterruptibleReflows() const {
|
||||||
|
return mWasLastReflowInterrupted;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// Approximate frame visibility tracking public API.
|
// Approximate frame visibility tracking public API.
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1794,7 +1809,8 @@ protected:
|
||||||
bool mIsFirstPaint : 1;
|
bool mIsFirstPaint : 1;
|
||||||
bool mObservesMutationsForPrint : 1;
|
bool mObservesMutationsForPrint : 1;
|
||||||
|
|
||||||
bool mSuppressInterruptibleReflows : 1;
|
// Whether the most recent interruptible reflow was actually interrupted:
|
||||||
|
bool mWasLastReflowInterrupted : 1;
|
||||||
bool mScrollPositionClampingScrollPortSizeSet : 1;
|
bool mScrollPositionClampingScrollPortSizeSet : 1;
|
||||||
|
|
||||||
// True if a layout flush might not be a no-op
|
// True if a layout flush might not be a no-op
|
||||||
|
|
|
@ -1949,7 +1949,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
|
||||||
|
|
||||||
nsCOMPtr<nsIPresShell> shellKungFuDeathGrip(shell);
|
nsCOMPtr<nsIPresShell> shellKungFuDeathGrip(shell);
|
||||||
shell->mObservingLayoutFlushes = false;
|
shell->mObservingLayoutFlushes = false;
|
||||||
shell->mSuppressInterruptibleReflows = false;
|
shell->mWasLastReflowInterrupted = false;
|
||||||
FlushType flushType = HasPendingAnimations(shell)
|
FlushType flushType = HasPendingAnimations(shell)
|
||||||
? FlushType::Layout
|
? FlushType::Layout
|
||||||
: FlushType::InterruptibleLayout;
|
: FlushType::InterruptibleLayout;
|
||||||
|
|
|
@ -43,7 +43,6 @@
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
#include "nsNetCID.h"
|
#include "nsNetCID.h"
|
||||||
#include "nsCSSRendering.h"
|
#include "nsCSSRendering.h"
|
||||||
#include "nsIDOMHTMLAnchorElement.h"
|
|
||||||
#include "nsNameSpaceManager.h"
|
#include "nsNameSpaceManager.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#ifdef ACCESSIBILITY
|
#ifdef ACCESSIBILITY
|
||||||
|
@ -81,6 +80,7 @@
|
||||||
|
|
||||||
#include "mozilla/dom/Link.h"
|
#include "mozilla/dom/Link.h"
|
||||||
#include "SVGImageContext.h"
|
#include "SVGImageContext.h"
|
||||||
|
#include "mozilla/dom/HTMLAnchorElement.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
@ -1993,7 +1993,7 @@ nsImageFrame::GetAnchorHREFTargetAndNode(nsIURI** aHref, nsString& aTarget,
|
||||||
}
|
}
|
||||||
status = (*aHref != nullptr);
|
status = (*aHref != nullptr);
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(content));
|
RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContent(content);
|
||||||
if (anchor) {
|
if (anchor) {
|
||||||
anchor->GetTarget(aTarget);
|
anchor->GetTarget(aTarget);
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,6 @@ static const char kPrintingPromptService[] = "@mozilla.org/embedcomp/printingpro
|
||||||
#include "nsILayoutHistoryState.h"
|
#include "nsILayoutHistoryState.h"
|
||||||
#include "nsFrameManager.h"
|
#include "nsFrameManager.h"
|
||||||
#include "mozilla/ReflowInput.h"
|
#include "mozilla/ReflowInput.h"
|
||||||
#include "nsIDOMHTMLAnchorElement.h"
|
|
||||||
#include "nsIDOMHTMLAreaElement.h"
|
#include "nsIDOMHTMLAreaElement.h"
|
||||||
#include "nsIDOMHTMLLinkElement.h"
|
#include "nsIDOMHTMLLinkElement.h"
|
||||||
#include "nsIDOMHTMLImageElement.h"
|
#include "nsIDOMHTMLImageElement.h"
|
||||||
|
|
|
@ -1413,7 +1413,7 @@ fuzzy-if(Android,5,2800) == 506481-1.html 506481-1-ref.html
|
||||||
== 507762-4.html 507762-2-ref.html
|
== 507762-4.html 507762-2-ref.html
|
||||||
random-if(cocoaWidget||(gtkWidget&&webrender)||winWidget) == 508816-1.xul 508816-1-ref.xul # Bug 631982 and bug 1375012
|
random-if(cocoaWidget||(gtkWidget&&webrender)||winWidget) == 508816-1.xul 508816-1-ref.xul # Bug 631982 and bug 1375012
|
||||||
== 508816-2.html 508816-2-ref.html
|
== 508816-2.html 508816-2-ref.html
|
||||||
== 508908-1.xul 508908-1-ref.xul
|
skip-if(isDebugBuild) == 508908-1.xul 508908-1-ref.xul
|
||||||
== 508919-1.xhtml 508919-1-ref.xhtml
|
== 508919-1.xhtml 508919-1-ref.xhtml
|
||||||
== 509155-1.xhtml 509155-1-ref.xhtml
|
== 509155-1.xhtml 509155-1-ref.xhtml
|
||||||
fuzzy-if(Android,5,1656) fuzzy-if(skiaContent,1,1200) == 512410.html 512410-ref.html
|
fuzzy-if(Android,5,1656) fuzzy-if(skiaContent,1,1200) == 512410.html 512410-ref.html
|
||||||
|
|
|
@ -372,7 +372,8 @@ include ../../toolkit/themes/osx/reftests/reftest.list
|
||||||
include ../../toolkit/content/tests/reftests/reftest.list
|
include ../../toolkit/content/tests/reftests/reftest.list
|
||||||
|
|
||||||
# -moz-transform/
|
# -moz-transform/
|
||||||
include transform/reftest.list
|
# skipping on non-e10s windows because of assertion in bug 1401228
|
||||||
|
skip-if(winWidget&&!browserIsRemote) include transform/reftest.list
|
||||||
|
|
||||||
# 3d transforms
|
# 3d transforms
|
||||||
include transform-3d/reftest.list
|
include transform-3d/reftest.list
|
||||||
|
|
|
@ -356,6 +356,9 @@ class RemoteReftest(RefTest):
|
||||||
debuggerInfo=debuggerInfo,
|
debuggerInfo=debuggerInfo,
|
||||||
symbolsPath=symbolsPath,
|
symbolsPath=symbolsPath,
|
||||||
timeout=timeout)
|
timeout=timeout)
|
||||||
|
if status == 1:
|
||||||
|
# when max run time exceeded, avoid restart
|
||||||
|
lastTestSeen = RefTest.TEST_SEEN_FINAL
|
||||||
return status, lastTestSeen
|
return status, lastTestSeen
|
||||||
|
|
||||||
def cleanup(self, profileDir):
|
def cleanup(self, profileDir):
|
||||||
|
|
|
@ -429,9 +429,9 @@ class RefTest(object):
|
||||||
self._populate_logger(options)
|
self._populate_logger(options)
|
||||||
|
|
||||||
# Number of times to repeat test(s) when running with --repeat
|
# Number of times to repeat test(s) when running with --repeat
|
||||||
VERIFY_REPEAT = 20
|
VERIFY_REPEAT = 10
|
||||||
# Number of times to repeat test(s) when running test in separate browser
|
# Number of times to repeat test(s) when running test in separate browser
|
||||||
VERIFY_REPEAT_SINGLE_BROWSER = 10
|
VERIFY_REPEAT_SINGLE_BROWSER = 5
|
||||||
|
|
||||||
def step1():
|
def step1():
|
||||||
stepOptions = copy.deepcopy(options)
|
stepOptions = copy.deepcopy(options)
|
||||||
|
@ -448,12 +448,34 @@ class RefTest(object):
|
||||||
break
|
break
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def step3():
|
||||||
|
stepOptions = copy.deepcopy(options)
|
||||||
|
stepOptions.repeat = VERIFY_REPEAT
|
||||||
|
stepOptions.runUntilFailure = True
|
||||||
|
stepOptions.environment.append("MOZ_CHAOSMODE=3")
|
||||||
|
result = self.runTests(tests, stepOptions)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def step4():
|
||||||
|
stepOptions = copy.deepcopy(options)
|
||||||
|
stepOptions.environment.append("MOZ_CHAOSMODE=3")
|
||||||
|
for i in xrange(VERIFY_REPEAT_SINGLE_BROWSER):
|
||||||
|
result = self.runTests(tests, stepOptions)
|
||||||
|
if result != 0:
|
||||||
|
break
|
||||||
|
return result
|
||||||
|
|
||||||
steps = [
|
steps = [
|
||||||
("1. Run each test %d times in one browser." % VERIFY_REPEAT,
|
("1. Run each test %d times in one browser." % VERIFY_REPEAT,
|
||||||
step1),
|
step1),
|
||||||
("2. Run each test %d times in a new browser each time." %
|
("2. Run each test %d times in a new browser each time." %
|
||||||
VERIFY_REPEAT_SINGLE_BROWSER,
|
VERIFY_REPEAT_SINGLE_BROWSER,
|
||||||
step2),
|
step2),
|
||||||
|
("3. Run each test %d times in one browser, in chaos mode." % VERIFY_REPEAT,
|
||||||
|
step3),
|
||||||
|
("4. Run each test %d times in a new browser each time, in chaos mode." %
|
||||||
|
VERIFY_REPEAT_SINGLE_BROWSER,
|
||||||
|
step4),
|
||||||
]
|
]
|
||||||
|
|
||||||
stepResults = {}
|
stepResults = {}
|
||||||
|
|
|
@ -484,10 +484,13 @@ public final class IntentHelper implements BundleEventListener {
|
||||||
*/
|
*/
|
||||||
private void openNoHandler(final GeckoBundle msg, final EventCallback callback) {
|
private void openNoHandler(final GeckoBundle msg, final EventCallback callback) {
|
||||||
final String uri = msg.getString("uri");
|
final String uri = msg.getString("uri");
|
||||||
|
final GeckoBundle errorResponse = new GeckoBundle();
|
||||||
|
|
||||||
if (TextUtils.isEmpty(uri)) {
|
if (TextUtils.isEmpty(uri)) {
|
||||||
Log.w(LOGTAG, "Received empty URL - loading about:neterror");
|
Log.w(LOGTAG, "Received empty URL - loading about:neterror");
|
||||||
callback.sendError(getUnknownProtocolErrorPageUri(""));
|
errorResponse.putString("uri", getUnknownProtocolErrorPageUri(""));
|
||||||
|
errorResponse.putBoolean("isFallback", false);
|
||||||
|
callback.sendError(errorResponse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,7 +508,9 @@ public final class IntentHelper implements BundleEventListener {
|
||||||
|
|
||||||
// Don't log the exception to prevent leaking URIs.
|
// Don't log the exception to prevent leaking URIs.
|
||||||
Log.w(LOGTAG, "Unable to parse Intent URI - loading about:neterror");
|
Log.w(LOGTAG, "Unable to parse Intent URI - loading about:neterror");
|
||||||
callback.sendError(errorUri);
|
errorResponse.putString("uri", errorUri);
|
||||||
|
errorResponse.putBoolean("isFallback", false);
|
||||||
|
callback.sendError(errorResponse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,9 +518,10 @@ public final class IntentHelper implements BundleEventListener {
|
||||||
// https://developer.chrome.com/multidevice/android/intents
|
// https://developer.chrome.com/multidevice/android/intents
|
||||||
final String fallbackUrl = intent.getStringExtra(EXTRA_BROWSER_FALLBACK_URL);
|
final String fallbackUrl = intent.getStringExtra(EXTRA_BROWSER_FALLBACK_URL);
|
||||||
if (isFallbackUrlValid(fallbackUrl)) {
|
if (isFallbackUrlValid(fallbackUrl)) {
|
||||||
|
errorResponse.putString("uri", fallbackUrl);
|
||||||
|
errorResponse.putBoolean("isFallback", true);
|
||||||
// Opens the page in JS.
|
// Opens the page in JS.
|
||||||
callback.sendError(fallbackUrl);
|
callback.sendError(errorResponse);
|
||||||
|
|
||||||
} else if (intent.getPackage() != null) {
|
} else if (intent.getPackage() != null) {
|
||||||
// Note on alternative flows: we could get the intent package from a component, however, for
|
// Note on alternative flows: we could get the intent package from a component, however, for
|
||||||
// security reasons, components are ignored when opening URIs (bug 1168998) so we should
|
// security reasons, components are ignored when opening URIs (bug 1168998) so we should
|
||||||
|
@ -552,7 +558,9 @@ public final class IntentHelper implements BundleEventListener {
|
||||||
//
|
//
|
||||||
// Don't log the URI to prevent leaking it.
|
// Don't log the URI to prevent leaking it.
|
||||||
Log.w(LOGTAG, "Unable to open URI, maybe showing neterror");
|
Log.w(LOGTAG, "Unable to open URI, maybe showing neterror");
|
||||||
callback.sendError(getUnknownProtocolErrorPageUri(intent.getData().toString()));
|
errorResponse.putString("uri", getUnknownProtocolErrorPageUri(intent.getData().toString()));
|
||||||
|
errorResponse.putBoolean("isFallback", false);
|
||||||
|
callback.sendError(errorResponse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2735,7 +2735,7 @@ var NativeWindow = {
|
||||||
*/
|
*/
|
||||||
_getContextType: function(element) {
|
_getContextType: function(element) {
|
||||||
// For anchor nodes, we try to use the scheme to pick a string
|
// For anchor nodes, we try to use the scheme to pick a string
|
||||||
if (element instanceof Ci.nsIDOMHTMLAnchorElement) {
|
if (ChromeUtils.getClassName(element) === "HTMLAnchorElement") {
|
||||||
let uri = this.makeURI(this._getLinkURL(element));
|
let uri = this.makeURI(this._getLinkURL(element));
|
||||||
try {
|
try {
|
||||||
return Strings.browser.GetStringFromName("browser.menu.context." + uri.scheme);
|
return Strings.browser.GetStringFromName("browser.menu.context." + uri.scheme);
|
||||||
|
@ -2820,7 +2820,7 @@ var NativeWindow = {
|
||||||
|
|
||||||
// Returns a url associated with a node
|
// Returns a url associated with a node
|
||||||
_getUrl: function(node) {
|
_getUrl: function(node) {
|
||||||
if ((node instanceof Ci.nsIDOMHTMLAnchorElement && node.href) ||
|
if ((ChromeUtils.getClassName(node) === "HTMLAnchorElement" && node.href) ||
|
||||||
(node instanceof Ci.nsIDOMHTMLAreaElement && node.href)) {
|
(node instanceof Ci.nsIDOMHTMLAreaElement && node.href)) {
|
||||||
return this._getLinkURL(node);
|
return this._getLinkURL(node);
|
||||||
} else if (node instanceof Ci.nsIImageLoadingContent && node.currentURI) {
|
} else if (node instanceof Ci.nsIImageLoadingContent && node.currentURI) {
|
||||||
|
@ -3051,7 +3051,7 @@ var NativeWindow = {
|
||||||
|
|
||||||
_getLink: function(aElement) {
|
_getLink: function(aElement) {
|
||||||
if (aElement.nodeType == Ci.nsIDOMNode.ELEMENT_NODE &&
|
if (aElement.nodeType == Ci.nsIDOMNode.ELEMENT_NODE &&
|
||||||
((aElement instanceof Ci.nsIDOMHTMLAnchorElement && aElement.href) ||
|
((ChromeUtils.getClassName(aElement) === "HTMLAnchorElement" && aElement.href) ||
|
||||||
(aElement instanceof Ci.nsIDOMHTMLAreaElement && aElement.href) ||
|
(aElement instanceof Ci.nsIDOMHTMLAreaElement && aElement.href) ||
|
||||||
aElement instanceof Ci.nsIDOMHTMLLinkElement ||
|
aElement instanceof Ci.nsIDOMHTMLLinkElement ||
|
||||||
aElement.getAttributeNS(kXLinkNamespace, "type") == "simple")) {
|
aElement.getAttributeNS(kXLinkNamespace, "type") == "simple")) {
|
||||||
|
@ -4775,7 +4775,7 @@ var BrowserEventHandler = {
|
||||||
|
|
||||||
_getLinkURI: function(aElement) {
|
_getLinkURI: function(aElement) {
|
||||||
if (aElement.nodeType == Ci.nsIDOMNode.ELEMENT_NODE &&
|
if (aElement.nodeType == Ci.nsIDOMNode.ELEMENT_NODE &&
|
||||||
((aElement instanceof Ci.nsIDOMHTMLAnchorElement && aElement.href) ||
|
((ChromeUtils.getClassName(aElement) === "HTMLAnchorElement" && aElement.href) ||
|
||||||
(aElement instanceof Ci.nsIDOMHTMLAreaElement && aElement.href))) {
|
(aElement instanceof Ci.nsIDOMHTMLAreaElement && aElement.href))) {
|
||||||
try {
|
try {
|
||||||
return Services.io.newURI(aElement.href);
|
return Services.io.newURI(aElement.href);
|
||||||
|
|
|
@ -64,6 +64,8 @@ function startup() {
|
||||||
"GeckoViewScroll");
|
"GeckoViewScroll");
|
||||||
ModuleManager.add("resource://gre/modules/GeckoViewTab.jsm",
|
ModuleManager.add("resource://gre/modules/GeckoViewTab.jsm",
|
||||||
"GeckoViewTab");
|
"GeckoViewTab");
|
||||||
|
ModuleManager.add("resource://gre/modules/GeckoViewRemoteDebugger.jsm",
|
||||||
|
"GeckoViewRemoteDebugger");
|
||||||
|
|
||||||
// Move focus to the content window at the end of startup,
|
// Move focus to the content window at the end of startup,
|
||||||
// so things like text selection can work properly.
|
// so things like text selection can work properly.
|
||||||
|
|
|
@ -65,15 +65,20 @@ ContentDispatchChooser.prototype =
|
||||||
|
|
||||||
EventDispatcher.instance.sendRequestForResult(msg).then(() => {
|
EventDispatcher.instance.sendRequestForResult(msg).then(() => {
|
||||||
// Java opens an app on success: take no action.
|
// Java opens an app on success: take no action.
|
||||||
}, (uri) => {
|
}, (data) => {
|
||||||
|
if (data.isFallback) {
|
||||||
|
// We always want to open a fallback url
|
||||||
|
window.location.href = data.uri;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// We couldn't open this. If this was from a click, it's likely that we just
|
// We couldn't open this. If this was from a click, it's likely that we just
|
||||||
// want this to fail silently. If the user entered this on the address bar, though,
|
// want this to fail silently. If the user entered this on the address bar, though,
|
||||||
// we want to show the neterror page.
|
// we want to show the neterror page.
|
||||||
|
|
||||||
let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||||
let millis = dwu.millisSinceLastUserInput;
|
let millis = dwu.millisSinceLastUserInput;
|
||||||
if (millis > 0 && millis >= 1000) {
|
if (millis > 0 && millis >= 1000) {
|
||||||
window.location.href = uri;
|
window.location.href = data.uri;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -496,6 +496,9 @@ public class GeckoView extends LayerView {
|
||||||
} else {
|
} else {
|
||||||
mSettings = settings;
|
mSettings = settings;
|
||||||
}
|
}
|
||||||
|
mSettings.setString(GeckoViewSettings.DEBUGGER_SOCKET_DIR,
|
||||||
|
context.getApplicationInfo().dataDir);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -65,6 +65,11 @@ public final class GeckoViewSettings {
|
||||||
public static final Key<Integer> DISPLAY_MODE =
|
public static final Key<Integer> DISPLAY_MODE =
|
||||||
new Key<Integer>("displayMode");
|
new Key<Integer>("displayMode");
|
||||||
|
|
||||||
|
public static final Key<Boolean> USE_REMOTE_DEBUGGER =
|
||||||
|
new Key<Boolean>("useRemoteDebugger");
|
||||||
|
|
||||||
|
public static final Key<String> DEBUGGER_SOCKET_DIR =
|
||||||
|
new Key<String>("debuggerSocketDir");
|
||||||
|
|
||||||
private final EventDispatcher mEventDispatcher;
|
private final EventDispatcher mEventDispatcher;
|
||||||
private final GeckoBundle mBundle;
|
private final GeckoBundle mBundle;
|
||||||
|
@ -81,6 +86,9 @@ public final class GeckoViewSettings {
|
||||||
setBoolean(USE_PRIVATE_MODE, false);
|
setBoolean(USE_PRIVATE_MODE, false);
|
||||||
setBoolean(USE_MULTIPROCESS, true);
|
setBoolean(USE_MULTIPROCESS, true);
|
||||||
setInt(DISPLAY_MODE, DisplayMode.BROWSER.value());
|
setInt(DISPLAY_MODE, DisplayMode.BROWSER.value());
|
||||||
|
setBoolean(USE_REMOTE_DEBUGGER, false);
|
||||||
|
// Set in GeckoView.init().
|
||||||
|
setString(DEBUGGER_SOCKET_DIR, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ GeckoViewSettings(GeckoViewSettings settings, EventDispatcher eventDispatcher) {
|
/* package */ GeckoViewSettings(GeckoViewSettings settings, EventDispatcher eventDispatcher) {
|
||||||
|
@ -122,6 +130,23 @@ public final class GeckoViewSettings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setString(final Key<String> key, final String value) {
|
||||||
|
synchronized (mBundle) {
|
||||||
|
final Object old = mBundle.get(key.text);
|
||||||
|
if (old != null && old.equals(value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mBundle.putString(key.text, value);
|
||||||
|
}
|
||||||
|
dispatchUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getString(final Key<String> key) {
|
||||||
|
synchronized (mBundle) {
|
||||||
|
return mBundle.getString(key.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* package */ GeckoBundle asBundle() {
|
/* package */ GeckoBundle asBundle() {
|
||||||
return mBundle;
|
return mBundle;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ public class GeckoViewActivity extends Activity {
|
||||||
private static final String LOGTAG = "GeckoViewActivity";
|
private static final String LOGTAG = "GeckoViewActivity";
|
||||||
private static final String DEFAULT_URL = "https://mozilla.org";
|
private static final String DEFAULT_URL = "https://mozilla.org";
|
||||||
private static final String USE_MULTIPROCESS_EXTRA = "use_multiprocess";
|
private static final String USE_MULTIPROCESS_EXTRA = "use_multiprocess";
|
||||||
|
private static final String USE_REMOTE_DEBUGGER_EXTRA = "use_remote_debugger";
|
||||||
|
|
||||||
/* package */ static final int REQUEST_FILE_PICKER = 1;
|
/* package */ static final int REQUEST_FILE_PICKER = 1;
|
||||||
private static final int REQUEST_PERMISSIONS = 2;
|
private static final int REQUEST_PERMISSIONS = 2;
|
||||||
|
@ -95,6 +96,9 @@ public class GeckoViewActivity extends Activity {
|
||||||
mGeckoView.getSettings().setBoolean(
|
mGeckoView.getSettings().setBoolean(
|
||||||
GeckoViewSettings.USE_MULTIPROCESS,
|
GeckoViewSettings.USE_MULTIPROCESS,
|
||||||
intent.getBooleanExtra(USE_MULTIPROCESS_EXTRA, true));
|
intent.getBooleanExtra(USE_MULTIPROCESS_EXTRA, true));
|
||||||
|
mGeckoView.getSettings().setBoolean(
|
||||||
|
GeckoViewSettings.USE_REMOTE_DEBUGGER,
|
||||||
|
intent.getBooleanExtra(USE_REMOTE_DEBUGGER_EXTRA, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -443,10 +443,8 @@
|
||||||
@BINPATH@/features/*
|
@BINPATH@/features/*
|
||||||
|
|
||||||
; DevTools
|
; DevTools
|
||||||
#ifndef MOZ_GECKOVIEW_JAR
|
|
||||||
@BINPATH@/chrome/devtools@JAREXT@
|
@BINPATH@/chrome/devtools@JAREXT@
|
||||||
@BINPATH@/chrome/devtools.manifest
|
@BINPATH@/chrome/devtools.manifest
|
||||||
#endif
|
|
||||||
|
|
||||||
; [Default Preferences]
|
; [Default Preferences]
|
||||||
; All the pref files must be part of base to prevent migration bugs
|
; All the pref files must be part of base to prevent migration bugs
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/* 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";
|
||||||
|
|
||||||
|
this.EXPORTED_SYMBOLS = ["GeckoViewRemoteDebugger"];
|
||||||
|
|
||||||
|
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/GeckoViewModule.jsm");
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "dump", () =>
|
||||||
|
Cu.import("resource://gre/modules/AndroidLog.jsm", {})
|
||||||
|
.AndroidLog.d.bind(null, "ViewRemoteDebugger"));
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "DebuggerServer", () => {
|
||||||
|
const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||||
|
const { DebuggerServer } = require("devtools/server/main");
|
||||||
|
return DebuggerServer;
|
||||||
|
});
|
||||||
|
|
||||||
|
function debug(aMsg) {
|
||||||
|
// dump(aMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
class GeckoViewRemoteDebugger extends GeckoViewModule {
|
||||||
|
init() {
|
||||||
|
this._isEnabled = false;
|
||||||
|
this._usbDebugger = new USBRemoteDebugger();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSettingsUpdate() {
|
||||||
|
let enabled = this.settings.useRemoteDebugger;
|
||||||
|
|
||||||
|
if (enabled && !this._isEnabled) {
|
||||||
|
this.register();
|
||||||
|
} else if (!enabled) {
|
||||||
|
this.unregister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
register() {
|
||||||
|
if (!DebuggerServer.initialized) {
|
||||||
|
DebuggerServer.init();
|
||||||
|
DebuggerServer.addBrowserActors("navigator:geckoview");
|
||||||
|
DebuggerServer.registerModule(
|
||||||
|
"resource://gre/modules/dbg-browser-actors.js");
|
||||||
|
DebuggerServer.allowChromeProcess = true;
|
||||||
|
}
|
||||||
|
this._isEnabled = true;
|
||||||
|
this._usbDebugger.stop();
|
||||||
|
|
||||||
|
let windowId = this.window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIDOMWindowUtils)
|
||||||
|
.outerWindowID;
|
||||||
|
let portOrPath = this.settings.debuggerSocketDir +
|
||||||
|
"/firefox-debugger-socket-" +
|
||||||
|
windowId;
|
||||||
|
this._usbDebugger.start(portOrPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
unregister() {
|
||||||
|
this._isEnabled = false;
|
||||||
|
this._usbDebugger.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class USBRemoteDebugger {
|
||||||
|
start(aPortOrPath) {
|
||||||
|
try {
|
||||||
|
let AuthenticatorType = DebuggerServer.Authenticators.get("PROMPT");
|
||||||
|
let authenticator = new AuthenticatorType.Server();
|
||||||
|
authenticator.allowConnection = this.allowConnection.bind(this);
|
||||||
|
this._listener = DebuggerServer.createListener();
|
||||||
|
this._listener.portOrPath = aPortOrPath;
|
||||||
|
this._listener.authenticator = authenticator;
|
||||||
|
this._listener.open();
|
||||||
|
debug(`USB remote debugger - listening on ${aPortOrPath}`);
|
||||||
|
} catch (e) {
|
||||||
|
debug("Unable to start USB debugger server: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
if (!this._listener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this._listener.close();
|
||||||
|
this._listener = null;
|
||||||
|
} catch (e) {
|
||||||
|
debug("Unable to stop USB debugger server: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allowConnection(aSession) {
|
||||||
|
if (!this._listener) {
|
||||||
|
return DebuggerServer.AuthenticationResult.DENY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aSession.server.port) {
|
||||||
|
return DebuggerServer.AuthenticationResult.DENY;
|
||||||
|
}
|
||||||
|
return DebuggerServer.AuthenticationResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,9 +22,10 @@ function debug(aMsg) {
|
||||||
// Stub BrowserApp implementation for WebExtensions support.
|
// Stub BrowserApp implementation for WebExtensions support.
|
||||||
class GeckoViewTab extends GeckoViewModule {
|
class GeckoViewTab extends GeckoViewModule {
|
||||||
init() {
|
init() {
|
||||||
this.browser.tab = { id: 0 };
|
this.browser.tab = { id: 0, browser: this.browser };
|
||||||
|
|
||||||
this.window.BrowserApp = {
|
this.window.gBrowser = this.window.BrowserApp = {
|
||||||
|
selectedBrowser: this.browser,
|
||||||
tabs: [this.browser.tab],
|
tabs: [this.browser.tab],
|
||||||
selectedTab: this.browser.tab,
|
selectedTab: this.browser.tab,
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ EXTRA_JS_MODULES += [
|
||||||
'GeckoViewModule.jsm',
|
'GeckoViewModule.jsm',
|
||||||
'GeckoViewNavigation.jsm',
|
'GeckoViewNavigation.jsm',
|
||||||
'GeckoViewProgress.jsm',
|
'GeckoViewProgress.jsm',
|
||||||
|
'GeckoViewRemoteDebugger.jsm',
|
||||||
'GeckoViewScroll.jsm',
|
'GeckoViewScroll.jsm',
|
||||||
'GeckoViewSettings.jsm',
|
'GeckoViewSettings.jsm',
|
||||||
'GeckoViewTab.jsm',
|
'GeckoViewTab.jsm',
|
||||||
|
|
|
@ -880,6 +880,7 @@ pref("gfx.webrender.blob-images", false);
|
||||||
// WebRender debugging utilities.
|
// WebRender debugging utilities.
|
||||||
pref("gfx.webrender.debug.texture-cache", false);
|
pref("gfx.webrender.debug.texture-cache", false);
|
||||||
pref("gfx.webrender.debug.render-targets", false);
|
pref("gfx.webrender.debug.render-targets", false);
|
||||||
|
pref("gfx.webrender.debug.alpha-primitives", false);
|
||||||
pref("gfx.webrender.debug.profiler", false);
|
pref("gfx.webrender.debug.profiler", false);
|
||||||
|
|
||||||
// Whether webrender should be used as much as possible.
|
// Whether webrender should be used as much as possible.
|
||||||
|
@ -5075,12 +5076,6 @@ pref("dom.battery.enabled", true);
|
||||||
// Streams API
|
// Streams API
|
||||||
pref("dom.streams.enabled", false);
|
pref("dom.streams.enabled", false);
|
||||||
|
|
||||||
// Abort API
|
|
||||||
pref("dom.abortController.enabled", true);
|
|
||||||
|
|
||||||
// Fetch + Abort API
|
|
||||||
pref("dom.abortController.fetch.enabled", true);
|
|
||||||
|
|
||||||
// Push
|
// Push
|
||||||
|
|
||||||
pref("dom.push.enabled", false);
|
pref("dom.push.enabled", false);
|
||||||
|
|
|
@ -2326,9 +2326,9 @@ toolbar#nav-bar {
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Number of times to repeat test(s) when running with --repeat
|
# Number of times to repeat test(s) when running with --repeat
|
||||||
VERIFY_REPEAT = 20
|
VERIFY_REPEAT = 10
|
||||||
# Number of times to repeat test(s) when running test in
|
# Number of times to repeat test(s) when running test in
|
||||||
VERIFY_REPEAT_SINGLE_BROWSER = 10
|
VERIFY_REPEAT_SINGLE_BROWSER = 5
|
||||||
|
|
||||||
def step1():
|
def step1():
|
||||||
stepOptions = copy.deepcopy(options)
|
stepOptions = copy.deepcopy(options)
|
||||||
|
@ -2352,12 +2352,41 @@ toolbar#nav-bar {
|
||||||
break
|
break
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def step3():
|
||||||
|
stepOptions = copy.deepcopy(options)
|
||||||
|
stepOptions.repeat = VERIFY_REPEAT
|
||||||
|
stepOptions.keep_open = False
|
||||||
|
stepOptions.environment.append("MOZ_CHAOSMODE=3")
|
||||||
|
result = self.runTests(stepOptions)
|
||||||
|
result = result or (-2 if self.countfail > 0 else 0)
|
||||||
|
self.message_logger.finish()
|
||||||
|
return result
|
||||||
|
|
||||||
|
def step4():
|
||||||
|
stepOptions = copy.deepcopy(options)
|
||||||
|
stepOptions.repeat = 0
|
||||||
|
stepOptions.keep_open = False
|
||||||
|
stepOptions.environment.append("MOZ_CHAOSMODE=3")
|
||||||
|
for i in xrange(VERIFY_REPEAT_SINGLE_BROWSER):
|
||||||
|
result = self.runTests(stepOptions)
|
||||||
|
result = result or (-2 if self.countfail > 0 else 0)
|
||||||
|
self.message_logger.finish()
|
||||||
|
if result != 0:
|
||||||
|
break
|
||||||
|
return result
|
||||||
|
|
||||||
steps = [
|
steps = [
|
||||||
("1. Run each test %d times in one browser." % VERIFY_REPEAT,
|
("1. Run each test %d times in one browser." % VERIFY_REPEAT,
|
||||||
step1),
|
step1),
|
||||||
("2. Run each test %d times in a new browser each time." %
|
("2. Run each test %d times in a new browser each time." %
|
||||||
VERIFY_REPEAT_SINGLE_BROWSER,
|
VERIFY_REPEAT_SINGLE_BROWSER,
|
||||||
step2),
|
step2),
|
||||||
|
("3. Run each test %d times in one browser, in chaos mode." %
|
||||||
|
VERIFY_REPEAT,
|
||||||
|
step3),
|
||||||
|
("4. Run each test %d times in a new browser each time, "
|
||||||
|
"in chaos mode." % VERIFY_REPEAT_SINGLE_BROWSER,
|
||||||
|
step4),
|
||||||
]
|
]
|
||||||
|
|
||||||
stepResults = {}
|
stepResults = {}
|
||||||
|
|
|
@ -101,8 +101,8 @@ def create_parser(mach_interface=False):
|
||||||
add_arg('--geckoProfileEntries', dest="gecko_profile_entries", type=int,
|
add_arg('--geckoProfileEntries', dest="gecko_profile_entries", type=int,
|
||||||
help="How many samples to take with the profiler")
|
help="How many samples to take with the profiler")
|
||||||
add_arg('--extension', dest='extensions', action='append',
|
add_arg('--extension', dest='extensions', action='append',
|
||||||
default=['${talos}/talos-powers/talos-powers-signed.xpi',
|
default=['${talos}/talos-powers',
|
||||||
'${talos}/pageloader/pageloader-signed.xpi'],
|
'${talos}/pageloader'],
|
||||||
help="Extension to install while running")
|
help="Extension to install while running")
|
||||||
add_arg('--fast', action='store_true',
|
add_arg('--fast', action='store_true',
|
||||||
help="Run tp tests as tp_fast")
|
help="Run tp tests as tp_fast")
|
||||||
|
|
|
@ -194,7 +194,9 @@ DEFAULTS = dict(
|
||||||
'identity.fxaccounts.migrateToDevEdition': False,
|
'identity.fxaccounts.migrateToDevEdition': False,
|
||||||
'plugin.state.flash': 0,
|
'plugin.state.flash': 0,
|
||||||
'media.libavcodec.allow-obsolete': True,
|
'media.libavcodec.allow-obsolete': True,
|
||||||
'extensions.legacy.enabled': True
|
'extensions.legacy.enabled': True,
|
||||||
|
'xpinstall.signatures.required': False,
|
||||||
|
'extensions.allow-non-mpc-extensions': True
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче