mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
merge mozilla-inbound to mozilla-central. r=merge a=merge
MozReview-Commit-ID: BGCq2q6xO1S
This commit is contained in:
commit
a3b6b15cef
@ -601,9 +601,13 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
||||
if (!mDocument)
|
||||
return;
|
||||
|
||||
// Wait until an update, we have started, or an interruptible reflow is
|
||||
// finished.
|
||||
if (mObservingState == eRefreshProcessing ||
|
||||
mObservingState == eRefreshProcessingForUpdate)
|
||||
mObservingState == eRefreshProcessingForUpdate ||
|
||||
mPresShell->IsReflowInterrupted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Any generic notifications should be queued if we're processing content
|
||||
// insertions or generic notifications.
|
||||
|
@ -87,6 +87,8 @@ RootAccessibleWrap::GetInternalUnknown()
|
||||
void
|
||||
RootAccessibleWrap::DocumentActivated(DocAccessible* aDocument)
|
||||
{
|
||||
// This check will never work with e10s enabled, in other words, as of
|
||||
// Firefox 57.
|
||||
if (Compatibility::IsDolphin() &&
|
||||
nsCoreUtils::IsTabDocument(aDocument->DocumentNode())) {
|
||||
uint32_t count = mChildDocuments.Length();
|
||||
|
@ -5,7 +5,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
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", "");
|
||||
// The time interval between checks for a new version (in seconds)
|
||||
pref("app.update.interval", 28800); // 8 hours
|
||||
|
@ -12,6 +12,10 @@ var Cu = Components.utils;
|
||||
const DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC =
|
||||
"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/Services.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
|
||||
@ -20,37 +24,65 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||
"resource://gre/modules/PlacesUtils.jsm");
|
||||
|
||||
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 = {
|
||||
_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() {
|
||||
let ini = null;
|
||||
try {
|
||||
if (this._iniFile) {
|
||||
if (this._hasDistributionIni) {
|
||||
ini = Cc["@mozilla.org/xpcom/ini-parser-factory;1"].
|
||||
getService(Ci.nsIINIParserFactory).
|
||||
createINIParser(this._iniFile);
|
||||
}
|
||||
} catch (e) {
|
||||
// Unable to parse INI.
|
||||
Cu.reportError("Unable to parse distribution.ini");
|
||||
if (e.result == Cr.NS_ERROR_FILE_NOT_FOUND) {
|
||||
// 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);
|
||||
return this._ini;
|
||||
|
@ -86,6 +86,7 @@ do_register_cleanup(function() {
|
||||
distDir.append("distribution");
|
||||
distDir.remove(true);
|
||||
Assert.ok(!distDir.exists());
|
||||
Services.prefs.clearUserPref("distribution.testing.loadFromProfile");
|
||||
});
|
||||
|
||||
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
|
||||
data/engine-de-DE.xml
|
||||
|
||||
[test_distribution.js]
|
||||
[test_browserGlue_migration_loop_cleanup.js]
|
||||
[test_distribution.js]
|
||||
[test_distribution_cachedexistence.js]
|
||||
|
@ -175,7 +175,7 @@ PluginContent.prototype = {
|
||||
},
|
||||
|
||||
_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
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
return {
|
||||
@ -649,7 +649,7 @@ PluginContent.prototype = {
|
||||
let doc = plugin.ownerDocument;
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
let permissionString;
|
||||
if (plugin instanceof Ci.nsIDOMHTMLAnchorElement) {
|
||||
if (ChromeUtils.getClassName(plugin) === "HTMLAnchorElement") {
|
||||
// We only have replacement content for Flash installs
|
||||
permissionString = pluginHost.getPermissionStringForType(FLASH_MIME_TYPE);
|
||||
} else {
|
||||
@ -681,10 +681,9 @@ PluginContent.prototype = {
|
||||
onOverlayClick(event) {
|
||||
let document = event.target.ownerDocument;
|
||||
let plugin = document.getBindingParent(event.target);
|
||||
let contentWindow = plugin.ownerGlobal.top;
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
// 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") &&
|
||||
!overlay.hasAttribute("dismissed") &&
|
||||
event.button == 0 &&
|
||||
@ -730,7 +729,7 @@ PluginContent.prototype = {
|
||||
}
|
||||
if (pluginInfo.permissionString == pluginHost.getPermissionStringForType(plugin.actualType)) {
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
if (plugin instanceof Ci.nsIDOMHTMLAnchorElement) {
|
||||
if (ChromeUtils.getClassName(plugin) === "HTMLAnchorElement") {
|
||||
placeHolderFound = true;
|
||||
} else {
|
||||
pluginFound = true;
|
||||
|
@ -39,8 +39,6 @@
|
||||
|
||||
const Services = require("Services");
|
||||
|
||||
const DEFAULT_HTTP_VERSION = "HTTP/1.1";
|
||||
|
||||
const Curl = {
|
||||
/**
|
||||
* Generates a cURL command string which can be used from the command line etc.
|
||||
@ -106,11 +104,6 @@ const Curl = {
|
||||
command.push("-I");
|
||||
}
|
||||
|
||||
// Add http version.
|
||||
if (data.httpVersion && data.httpVersion != DEFAULT_HTTP_VERSION) {
|
||||
command.push("--" + data.httpVersion.split("/")[1]);
|
||||
}
|
||||
|
||||
// Add request headers.
|
||||
let headers = data.headers;
|
||||
if (multipartRequest) {
|
||||
|
1
devtools/client/shared/vendor/WasmDis.js
vendored
1
devtools/client/shared/vendor/WasmDis.js
vendored
@ -747,4 +747,3 @@ var WasmDisassembler = (function () {
|
||||
return WasmDisassembler;
|
||||
}());
|
||||
exports.WasmDisassembler = WasmDisassembler;
|
||||
//# sourceMappingURL=WasmDis.js.map
|
1
devtools/client/shared/vendor/WasmParser.js
vendored
1
devtools/client/shared/vendor/WasmParser.js
vendored
@ -1400,4 +1400,3 @@ if (!exports.bytesToString) {
|
||||
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.
|
||||
*/
|
||||
grip: function () {
|
||||
this.hooks.incrementGripDepth();
|
||||
|
||||
let g = {
|
||||
"type": "object",
|
||||
"actor": this.actorID
|
||||
};
|
||||
|
||||
// If it's a proxy, lie and tell that it belongs to an invented "Proxy" class.
|
||||
// The `isProxy` function detects them even behind non-opaque security wrappers,
|
||||
// which is useful to avoid running proxy traps through transparent wrappers.
|
||||
if (isProxy(this.obj)) {
|
||||
// Check if the object has a wrapper which denies access. It may be a CPOW or a
|
||||
// security wrapper. Change the class so that this will be visible in the UI.
|
||||
let unwrapped = unwrap(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";
|
||||
} else {
|
||||
try {
|
||||
g.class = this.obj.class;
|
||||
g.extensible = this.obj.isExtensible();
|
||||
g.frozen = this.obj.isFrozen();
|
||||
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.
|
||||
}
|
||||
g.class = this.obj.class;
|
||||
g.extensible = this.obj.isExtensible();
|
||||
g.frozen = this.obj.isFrozen();
|
||||
g.sealed = this.obj.isSealed();
|
||||
}
|
||||
|
||||
// Changing the class so that CPOWs will be visible in the UI
|
||||
let isCPOW = DevToolsUtils.isCPOW(this.obj);
|
||||
if (isCPOW) {
|
||||
g.class = "CPOW: " + g.class;
|
||||
if (g.class == "Promise") {
|
||||
g.promiseState = this._createPromiseState();
|
||||
}
|
||||
|
||||
if (g.class != "DeadObject" && !isCPOW) {
|
||||
if (g.class == "Promise") {
|
||||
g.promiseState = this._createPromiseState();
|
||||
}
|
||||
// FF40+: Allow to know how many properties an object has to lazily display them
|
||||
// when there is a bunch.
|
||||
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
|
||||
// to lazily display them when there is a bunch.
|
||||
// Throws on some MouseEvent object in tests.
|
||||
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 (TYPED_ARRAY_CLASSES.indexOf(g.class) != -1) {
|
||||
// Bug 1348761: getOwnPropertyNames is unecessary slow on TypedArrays
|
||||
let length = DevToolsUtils.getProperty(this.obj, "length");
|
||||
g.ownPropertyLength = length;
|
||||
} else if (g.class != "Proxy") {
|
||||
g.ownPropertyLength = this.obj.getOwnPropertyNames().length;
|
||||
if (fn(this, g, raw)) {
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
let msg = "ObjectActor.prototype.grip previewer function";
|
||||
DevToolsUtils.reportException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,20 +289,20 @@ ObjectActor.prototype = {
|
||||
onPrototypeAndProperties: function () {
|
||||
let ownProperties = Object.create(null);
|
||||
let ownSymbols = [];
|
||||
let names;
|
||||
let symbols;
|
||||
try {
|
||||
names = this.obj.getOwnPropertyNames();
|
||||
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.
|
||||
|
||||
// Inaccessible, proxy and dead objects should not be accessed.
|
||||
let unwrapped = unwrap(this.obj);
|
||||
if (!unwrapped || unwrapped.isProxy || this.obj.class == "DeadObject") {
|
||||
return { from: this.actorID,
|
||||
prototype: this.hooks.createValueGrip(null),
|
||||
ownProperties,
|
||||
ownSymbols,
|
||||
safeGetterValues: Object.create(null) };
|
||||
}
|
||||
|
||||
let names = this.obj.getOwnPropertyNames();
|
||||
let symbols = this.obj.getOwnPropertySymbols();
|
||||
|
||||
for (let name of names) {
|
||||
ownProperties[name] = this._propertyDescriptor(name);
|
||||
}
|
||||
@ -340,8 +339,9 @@ ObjectActor.prototype = {
|
||||
let obj = this.obj;
|
||||
let level = 0, i = 0;
|
||||
|
||||
// Do not search safe getters in proxy objects.
|
||||
if (isProxy(obj)) {
|
||||
// Do not search safe getters in inaccessible nor proxy objects.
|
||||
let unwrapped = unwrap(obj);
|
||||
if (!unwrapped || unwrapped.isProxy) {
|
||||
return safeGetterValues;
|
||||
}
|
||||
|
||||
@ -355,8 +355,13 @@ ObjectActor.prototype = {
|
||||
level++;
|
||||
}
|
||||
|
||||
// Stop iterating when the prototype chain ends or a proxy is found.
|
||||
while (obj && !isProxy(obj)) {
|
||||
while (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);
|
||||
for (let name of getters) {
|
||||
// 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.
|
||||
* Non-opaque security wrappers are unwrapped first before the check.
|
||||
* Removes all the non-opaque security wrappers of a debuggee object.
|
||||
* Returns null if some wrapper can't be removed.
|
||||
*
|
||||
* @param obj Debugger.Object
|
||||
* The debuggee object to be checked.
|
||||
* The debuggee object to be unwrapped.
|
||||
*/
|
||||
function isProxy(obj) {
|
||||
// Check if the object is a proxy without security wrappers.
|
||||
if (obj.isProxy) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// No need to remove opaque wrappers since they prevent proxy traps from running.
|
||||
function unwrap(obj) {
|
||||
// Check if `obj` has an opaque wrapper.
|
||||
if (obj.class === "Opaque") {
|
||||
return false;
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Attempt to unwrap. If the debugger can't unwrap, then proxy traps won't be
|
||||
// allowed to run either, so the object can be safely assumed to not be a proxy.
|
||||
// Attempt to unwrap. If this operation is not allowed, it may return null or throw.
|
||||
let unwrapped;
|
||||
try {
|
||||
unwrapped = obj.unwrap();
|
||||
} catch (err) {
|
||||
return false;
|
||||
unwrapped = null;
|
||||
}
|
||||
|
||||
// Check if further unwrapping is not possible.
|
||||
if (!unwrapped || unwrapped === obj) {
|
||||
return false;
|
||||
return unwrapped;
|
||||
}
|
||||
|
||||
// Recursively check whether the unwrapped object is a proxy.
|
||||
return isProxy(unwrapped);
|
||||
// Recursively remove additional security wrappers.
|
||||
return unwrap(unwrapped);
|
||||
}
|
||||
|
||||
exports.ObjectActor = ObjectActor;
|
||||
|
@ -167,7 +167,7 @@ var DebuggerServer = {
|
||||
* window (i.e the global style editor). Set this to your main window type,
|
||||
* for example "navigator:browser".
|
||||
*/
|
||||
chromeWindowType: null,
|
||||
chromeWindowType: "navigator:browser",
|
||||
|
||||
/**
|
||||
* Allow debugging chrome of (parent or child) processes.
|
||||
@ -266,11 +266,13 @@ var DebuggerServer = {
|
||||
* actors to retrieve them.
|
||||
*/
|
||||
registerActors({ root = true, browser = true, tab = true,
|
||||
windowType = "navigator:browser" }) {
|
||||
this.chromeWindowType = windowType;
|
||||
windowType = null }) {
|
||||
if (windowType) {
|
||||
this.chromeWindowType = windowType;
|
||||
}
|
||||
|
||||
if (browser) {
|
||||
this.addBrowserActors(windowType);
|
||||
this.addBrowserActors(this.chromeWindowType);
|
||||
}
|
||||
|
||||
if (root) {
|
||||
@ -420,8 +422,10 @@ var DebuggerServer = {
|
||||
* restrictPrivileges=true, to prevent exposing them on b2g parent process's
|
||||
* root actor.
|
||||
*/
|
||||
addBrowserActors(windowType = "navigator:browser", restrictPrivileges = false) {
|
||||
this.chromeWindowType = windowType;
|
||||
addBrowserActors(windowType = null, restrictPrivileges = false) {
|
||||
if (windowType) {
|
||||
this.chromeWindowType = windowType;
|
||||
}
|
||||
this.registerModule("devtools/server/actors/webbrowser");
|
||||
|
||||
if (!restrictPrivileges) {
|
||||
|
@ -6,10 +6,13 @@
|
||||
|
||||
var gServer;
|
||||
var gDebuggee;
|
||||
var gDebuggeeHasXrays;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gGlobal;
|
||||
var gHasXrays;
|
||||
var gGlobalIsInvisible;
|
||||
var gSubsumes;
|
||||
var gIsOpaque;
|
||||
|
||||
function run_test() {
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
@ -31,63 +34,95 @@ async function run_test_with_server(server, callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
async function run_tests_in_principal(principal, title) {
|
||||
// Prepare the debuggee.
|
||||
gDebuggee = Cu.Sandbox(principal);
|
||||
gDebuggee.__name = title;
|
||||
gServer.addTestGlobal(gDebuggee);
|
||||
gDebuggee.eval(function stopMe(arg1, arg2) {
|
||||
debugger;
|
||||
}.toString());
|
||||
gClient = new DebuggerClient(gServer.connectPipe());
|
||||
await gClient.connect();
|
||||
const [,, threadClient] = await attachTestTabAndResume(gClient, title);
|
||||
gThreadClient = threadClient;
|
||||
async function run_tests_in_principal(debuggeePrincipal, title) {
|
||||
for (gDebuggeeHasXrays of [true, false]) {
|
||||
// Prepare the debuggee.
|
||||
let fullTitle = gDebuggeeHasXrays ? title + "-with-xrays" : title;
|
||||
gDebuggee = Cu.Sandbox(debuggeePrincipal, {wantXrays: gDebuggeeHasXrays});
|
||||
gDebuggee.__name = fullTitle;
|
||||
gServer.addTestGlobal(gDebuggee);
|
||||
gDebuggee.eval(function stopMe() {
|
||||
debugger;
|
||||
}.toString());
|
||||
gClient = new DebuggerClient(gServer.connectPipe());
|
||||
await gClient.connect();
|
||||
const [,, threadClient] = await attachTestTabAndResume(gClient, fullTitle);
|
||||
gThreadClient = threadClient;
|
||||
|
||||
// Test objects created in the debuggee.
|
||||
await testPrincipal(undefined, false);
|
||||
// Test objects created in the debuggee.
|
||||
await testPrincipal(undefined);
|
||||
|
||||
// Test objects created in a new system principal with Xrays.
|
||||
await testPrincipal(systemPrincipal, true);
|
||||
// Test objects created in a system principal new global.
|
||||
await testPrincipal(systemPrincipal);
|
||||
|
||||
// Test objects created in a new system principal without Xrays.
|
||||
await testPrincipal(systemPrincipal, false);
|
||||
// Test objects created in a cross-origin null principal new global.
|
||||
await testPrincipal(null);
|
||||
|
||||
// Test objects created in a new null principal with Xrays.
|
||||
await testPrincipal(null, true);
|
||||
if (debuggeePrincipal === null) {
|
||||
// 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.
|
||||
await testPrincipal(null, false);
|
||||
|
||||
// Finish.
|
||||
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.
|
||||
// If none is specified, use the debuggee.
|
||||
if (principal !== undefined) {
|
||||
gGlobal = Cu.Sandbox(principal, {wantXrays});
|
||||
gHasXrays = wantXrays;
|
||||
} else {
|
||||
if (globalPrincipal === undefined) {
|
||||
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) {
|
||||
gThreadClient.addOneTimeListener("paused", async function (event, packet) {
|
||||
// Get the grips.
|
||||
let [proxyGrip, inheritsProxyGrip] = packet.frame.arguments;
|
||||
let [proxyGrip, inheritsProxyGrip, inheritsProxy2Grip] = packet.frame.arguments;
|
||||
|
||||
// Check the grip of the proxy object.
|
||||
check_proxy_grip(proxyGrip);
|
||||
|
||||
// Retrieve the properties of the object which inherits from a proxy,
|
||||
// and check the grip of its prototype.
|
||||
let objClient = gThreadClient.pauseGrip(inheritsProxyGrip);
|
||||
let response = await objClient.getPrototypeAndProperties();
|
||||
check_properties(response.ownProperties);
|
||||
check_prototype(response.prototype);
|
||||
// Check the prototype and properties of the proxy object.
|
||||
let proxyClient = gThreadClient.pauseGrip(proxyGrip);
|
||||
let proxyResponse = await proxyClient.getPrototypeAndProperties();
|
||||
check_properties(proxyResponse.ownProperties, true, false);
|
||||
check_prototype(proxyResponse.prototype, true, false);
|
||||
|
||||
// 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.
|
||||
strictEqual(gGlobal.trapDidRun, false, "No proxy trap did run.");
|
||||
@ -105,24 +140,21 @@ function testPrincipal(principal, wantXrays = true) {
|
||||
gGlobal.eval(`
|
||||
var trapDidRun = false;
|
||||
var proxy = new Proxy({}, new Proxy({}, {get: (_, trap) => {
|
||||
return function(_, arg) {
|
||||
trapDidRun = true;
|
||||
throw new Error("proxy trap '" + trap + "' was called.");
|
||||
}
|
||||
trapDidRun = true;
|
||||
throw new Error("proxy trap '" + trap + "' was called.");
|
||||
}}));
|
||||
var inheritsProxy = Object.create(proxy, {x:{value:1}});
|
||||
`);
|
||||
let data = Cu.createObjectIn(gDebuggee, {defineAs: "data"});
|
||||
data.proxy = gGlobal.proxy;
|
||||
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) {
|
||||
const {preview} = grip;
|
||||
|
||||
@ -136,11 +168,11 @@ function check_proxy_grip(grip) {
|
||||
strictEqual(target, grip.proxyTarget, "<target> contains the [[ProxyTarget]].");
|
||||
let handler = preview.ownProperties["<handler>"].value;
|
||||
strictEqual(handler, grip.proxyHandler, "<handler> contains the [[ProxyHandler]].");
|
||||
} else if (!isSystemPrincipal(gDebuggee)) {
|
||||
// The debuggee is not allowed to remove the security wrappers.
|
||||
strictEqual(grip.class, "Object", "The grip has an Object class.");
|
||||
ok(!("ownPropertyLength" in grip), "The grip doesn't know the number of properties.");
|
||||
} else if (!gHasXrays || isSystemPrincipal(gGlobal)) {
|
||||
} else if (gIsOpaque) {
|
||||
// The proxy has opaque security wrappers.
|
||||
strictEqual(grip.class, "Opaque", "The grip has an Opaque class.");
|
||||
strictEqual(grip.ownPropertyLength, 0, "The grip has no properties.");
|
||||
} else if (gSubsumes && !gGlobalIsInvisible) {
|
||||
// The proxy has non-opaque security wrappers.
|
||||
strictEqual(grip.class, "Proxy", "The grip has a Proxy class.");
|
||||
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(!("<handler>" in preview), "The preview has no <handler> property.");
|
||||
} else {
|
||||
// The proxy has opaque security wrappers.
|
||||
strictEqual(grip.class, "Opaque", "The grip has an Opaque class.");
|
||||
strictEqual(grip.ownPropertyLength, 0, "The grip has no properties.");
|
||||
// The debuggee is not allowed to remove the security wrappers.
|
||||
strictEqual(grip.class, "Inaccessible", "The grip has an Inaccessible class.");
|
||||
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;
|
||||
|
||||
if (!isSystemPrincipal(gDebuggee) && gDebuggee !== gGlobal) {
|
||||
// The debuggee is not allowed to access the object.
|
||||
strictEqual(ownPropertiesLength, 0, "No own property could be retrieved.");
|
||||
} else {
|
||||
if (createdInDebuggee || !isProxy && gSubsumes && !gGlobalIsInvisible) {
|
||||
// The debuggee can access the properties.
|
||||
strictEqual(ownPropertiesLength, 1, "1 own property was retrieved.");
|
||||
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) {
|
||||
if (!isSystemPrincipal(gDebuggee) && gDebuggee !== gGlobal) {
|
||||
// The debuggee is not allowed to access the object. It sees a null prototype.
|
||||
strictEqual(proto.type, "null", "The prototype is null.");
|
||||
} else if (!gHasXrays || isSystemPrincipal(gGlobal)) {
|
||||
// The object has no security wrappers or non-opaque ones.
|
||||
function check_prototype(proto, isProxy, createdInDebuggee) {
|
||||
if (gIsOpaque && !gGlobalIsInvisible && !createdInDebuggee) {
|
||||
// The object is or inherits from a proxy with opaque security wrappers.
|
||||
// The debuggee sees `Object.prototype` when retrieving the prototype.
|
||||
strictEqual(proto.class, "Object", "The prototype has a Object class.");
|
||||
} 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.
|
||||
check_proxy_grip(proto);
|
||||
} else {
|
||||
// The object has opaque security wrappers.
|
||||
// The debuggee sees `Object.prototype` when retrieving the prototype.
|
||||
strictEqual(proto.class, "Object", "The prototype has a Object class.");
|
||||
// The debuggee is not allowed to access the object. It sees a null prototype.
|
||||
strictEqual(proto.type, "null", "The prototype is null.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ function doConsoleCalls(aState)
|
||||
{
|
||||
type: "object",
|
||||
actor: /[a-z]/,
|
||||
class: "Object",
|
||||
class: "Inaccessible",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -12,10 +12,7 @@
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsIDOMHTMLElement.h"
|
||||
#include "nsIDOMHTMLHtmlElement.h"
|
||||
#include "nsIDOMHTMLAnchorElement.h"
|
||||
#include "nsIDOMHTMLImageElement.h"
|
||||
#include "nsIDOMHTMLAreaElement.h"
|
||||
#include "nsIDOMHTMLLinkElement.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsICSSDeclaration.h"
|
||||
#include "nsIDOMCSSValue.h"
|
||||
@ -27,7 +24,13 @@
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "nsIContentPolicy.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::ErrorResult;
|
||||
|
||||
@ -63,30 +66,24 @@ nsContextMenuInfo::GetAssociatedLink(nsAString& aHRef)
|
||||
NS_ENSURE_STATE(mAssociatedLink);
|
||||
aHRef.Truncate(0);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> content(do_QueryInterface(mAssociatedLink));
|
||||
nsAutoString localName;
|
||||
if (content) {
|
||||
content->GetLocalName(localName);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMElement> linkContent;
|
||||
ToLowerCase(localName);
|
||||
if (localName.EqualsLiteral("a") ||
|
||||
localName.EqualsLiteral("area") ||
|
||||
localName.EqualsLiteral("link")) {
|
||||
bool hasAttr;
|
||||
content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(mAssociatedLink));
|
||||
nsCOMPtr<nsIContent> linkContent;
|
||||
if (content &&
|
||||
content->IsAnyOfHTMLElements(nsGkAtoms::a,
|
||||
nsGkAtoms::area,
|
||||
nsGkAtoms::link)) {
|
||||
bool hasAttr = content->HasAttr(kNameSpaceID_None, nsGkAtoms::href);
|
||||
if (hasAttr) {
|
||||
linkContent = content;
|
||||
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(linkContent));
|
||||
RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContent(linkContent);
|
||||
if (anchor) {
|
||||
anchor->GetHref(aHRef);
|
||||
} else {
|
||||
nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(linkContent));
|
||||
RefPtr<HTMLAreaElement> area = HTMLAreaElement::FromContent(linkContent);
|
||||
if (area) {
|
||||
area->GetHref(aHRef);
|
||||
} else {
|
||||
nsCOMPtr<nsIDOMHTMLLinkElement> link(do_QueryInterface(linkContent));
|
||||
RefPtr<HTMLLinkElement> link = HTMLLinkElement::FromContent(linkContent);
|
||||
if (link) {
|
||||
link->GetHref(aHRef);
|
||||
}
|
||||
@ -101,15 +98,12 @@ nsContextMenuInfo::GetAssociatedLink(nsAString& aHRef)
|
||||
if (!content) {
|
||||
break;
|
||||
}
|
||||
content->GetLocalName(localName);
|
||||
ToLowerCase(localName);
|
||||
if (localName.EqualsLiteral("a")) {
|
||||
if (content->IsHTMLElement(nsGkAtoms::a)) {
|
||||
bool hasAttr;
|
||||
content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr);
|
||||
hasAttr = content->HasAttr(kNameSpaceID_None, nsGkAtoms::href);
|
||||
if (hasAttr) {
|
||||
linkContent = content;
|
||||
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(
|
||||
do_QueryInterface(linkContent));
|
||||
RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContent(linkContent);
|
||||
if (anchor) {
|
||||
anchor->GetHref(aHRef);
|
||||
}
|
||||
|
@ -135,7 +135,6 @@
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsIController.h"
|
||||
#include "nsPICommandUpdater.h"
|
||||
#include "nsIDOMHTMLAnchorElement.h"
|
||||
#include "nsIWebBrowserChrome3.h"
|
||||
#include "nsITabChild.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
|
||||
nsAutoString typeHint;
|
||||
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(aContent));
|
||||
RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContent(aContent);
|
||||
if (anchor) {
|
||||
anchor->GetType(typeHint);
|
||||
NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
|
||||
|
@ -22,44 +22,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AbortController)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
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>
|
||||
AbortController::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
||||
{
|
||||
|
@ -26,12 +26,6 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
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>
|
||||
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]
|
||||
support-files =
|
||||
file_abort_controller.html
|
||||
file_abort_controller_fetch.html
|
||||
worker_abort_controller_fetch.js
|
||||
slow.sjs
|
||||
|
||||
|
@ -12,27 +12,61 @@
|
||||
<body>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.abortController.enabled", true ]]}, () => {
|
||||
let ifr = document.createElement("iframe");
|
||||
ifr.src = "file_abort_controller.html";
|
||||
document.body.appendChild(ifr);
|
||||
function testWebIDL() {
|
||||
ok("AbortController" in self, "We have a AbortController prototype");
|
||||
ok("AbortSignal" in self, "We have a AbortSignal prototype");
|
||||
|
||||
window.onmessage = function(e) {
|
||||
if (e.data.type == "finish") {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
var ac = new AbortController();
|
||||
ok(!!ac, "AbortController can be created");
|
||||
ok(ac instanceof AbortController, "AbortController is a AbortController");
|
||||
|
||||
if (e.data.type == "check") {
|
||||
ok(e.data.status, e.data.message);
|
||||
return;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
next();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
@ -12,28 +12,68 @@
|
||||
<body>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.abortController.enabled", true ],
|
||||
["dom.abortController.fetch.enabled", true]]}, () => {
|
||||
let ifr = document.createElement("iframe");
|
||||
ifr.src = "file_abort_controller_fetch.html";
|
||||
document.body.appendChild(ifr);
|
||||
function testAbortedFetch() {
|
||||
var ac = new AbortController();
|
||||
ac.abort();
|
||||
|
||||
window.onmessage = function(e) {
|
||||
if (e.data.type == "finish") {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
if (e.data.type == "check") {
|
||||
ok(e.data.status, e.data.message);
|
||||
return;
|
||||
}
|
||||
function testFetchAndAbort() {
|
||||
var ac = new AbortController();
|
||||
|
||||
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();
|
||||
next();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
@ -244,16 +244,6 @@ DoesNotParticipateInAutoDirection(const Element* aElement)
|
||||
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
|
||||
* affect the direction of ancestors with dir=auto (though it may affect its own
|
||||
@ -263,7 +253,7 @@ static bool
|
||||
DoesNotAffectDirectionOfAncestors(const Element* aElement)
|
||||
{
|
||||
return (DoesNotParticipateInAutoDirection(aElement) ||
|
||||
IsBdiWithoutDirAuto(aElement) ||
|
||||
aElement->IsHTMLElement(nsGkAtoms::bdi) ||
|
||||
aElement->HasFixedDir());
|
||||
}
|
||||
|
||||
|
15
dom/base/crashtests/1400701.html
Normal file
15
dom/base/crashtests/1400701.html
Normal file
@ -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
|
||||
pref(clipboard.autocopy,true) load 1385272-1.html
|
||||
load 1393806.html
|
||||
load 1400701.html
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsIDOMHTMLAreaElement.h"
|
||||
#include "nsIDOMHTMLAnchorElement.h"
|
||||
#include "nsITransferable.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsXPCOM.h"
|
||||
@ -57,6 +56,7 @@
|
||||
#include "TabParent.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/HTMLAreaElement.h"
|
||||
#include "mozilla/dom/HTMLAnchorElement.h"
|
||||
#include "nsVariant.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
@ -474,9 +474,7 @@ DragDataProducer::Produce(DataTransfer* aDataTransfer,
|
||||
draggedNode = mTarget;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLAreaElement> area; // client-side image map
|
||||
nsCOMPtr<nsIImageLoadingContent> image;
|
||||
nsCOMPtr<nsIDOMHTMLAnchorElement> link;
|
||||
|
||||
nsCOMPtr<nsIContent> selectedImageOrLinkNode;
|
||||
GetDraggableSelectionData(selection, mSelectionTargetNode,
|
||||
@ -501,19 +499,16 @@ DragDataProducer::Produce(DataTransfer* aDataTransfer,
|
||||
*aCanDrag = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
area = do_QueryInterface(draggedNode);
|
||||
image = do_QueryInterface(draggedNode);
|
||||
link = do_QueryInterface(draggedNode);
|
||||
}
|
||||
|
||||
{
|
||||
// set for linked images, and links
|
||||
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
|
||||
HTMLAreaElement* areaElem = static_cast<HTMLAreaElement*>(area.get());
|
||||
areaElem->GetAttribute(NS_LITERAL_STRING("alt"), mTitleString);
|
||||
if (mTitleString.IsEmpty()) {
|
||||
// this can be a relative link
|
||||
@ -638,9 +633,9 @@ DragDataProducer::Produce(DataTransfer* aDataTransfer,
|
||||
nodeToSerialize = do_QueryInterface(draggedNode);
|
||||
}
|
||||
dragNode = nodeToSerialize;
|
||||
} else if (link) {
|
||||
} else if (draggedNode && draggedNode->IsHTMLElement(nsGkAtoms::a)) {
|
||||
// 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);
|
||||
} else if (parentLink) {
|
||||
// parentLink will always be null if there's selected content
|
||||
|
@ -666,7 +666,7 @@ BrowserElementChild.prototype = {
|
||||
_ClickHandler: function(e) {
|
||||
|
||||
let isHTMLLink = node =>
|
||||
((node instanceof Ci.nsIDOMHTMLAnchorElement && node.href) ||
|
||||
((ChromeUtils.getClassName(node) === "HTMLAnchorElement" && node.href) ||
|
||||
(node instanceof Ci.nsIDOMHTMLAreaElement && node.href) ||
|
||||
node instanceof Ci.nsIDOMHTMLLinkElement);
|
||||
|
||||
@ -855,7 +855,7 @@ BrowserElementChild.prototype = {
|
||||
_getSystemCtxMenuData: function(elem) {
|
||||
let documentURI =
|
||||
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)) {
|
||||
return {uri: elem.href,
|
||||
documentURI: documentURI,
|
||||
|
@ -8,10 +8,11 @@
|
||||
#include "IPCBlobInputStreamChild.h"
|
||||
#include "IPCBlobInputStreamStorage.h"
|
||||
#include "mozilla/ipc/InputStreamParams.h"
|
||||
#include "IPCBlobInputStreamThread.h"
|
||||
#include "nsIAsyncInputStream.h"
|
||||
#include "nsIStreamTransportService.h"
|
||||
#include "nsITransport.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsIAsyncOutputStream.h"
|
||||
#include "nsIPipe.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "SlicedInputStream.h"
|
||||
|
||||
@ -20,8 +21,6 @@ namespace dom {
|
||||
|
||||
namespace {
|
||||
|
||||
static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
|
||||
|
||||
class InputStreamCallbackRunnable final : public CancelableRunnable
|
||||
{
|
||||
public:
|
||||
@ -247,7 +246,7 @@ IPCBlobInputStream::Close()
|
||||
}
|
||||
|
||||
if (mAsyncRemoteStream) {
|
||||
mAsyncRemoteStream->Close();
|
||||
mAsyncRemoteStream->CloseWithStatus(NS_BASE_STREAM_CLOSED);
|
||||
mAsyncRemoteStream = nullptr;
|
||||
}
|
||||
|
||||
@ -503,7 +502,7 @@ IPCBlobInputStream::OnInputStreamReady(nsIAsyncInputStream* aStream)
|
||||
|
||||
nsCOMPtr<nsIEventTarget> callbackEventTarget;
|
||||
callbackEventTarget.swap(mInputStreamCallbackEventTarget);
|
||||
|
||||
|
||||
// This must be the last operation because the execution of the callback can
|
||||
// be synchronous.
|
||||
InputStreamCallbackRunnable::Execute(callback, callbackEventTarget, this);
|
||||
@ -643,30 +642,29 @@ IPCBlobInputStream::EnsureAsyncRemoteStream()
|
||||
|
||||
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(mRemoteStream);
|
||||
if (!asyncStream || !nonBlocking) {
|
||||
nsCOMPtr<nsIStreamTransportService> sts =
|
||||
do_GetService(kStreamTransportServiceCID, &rv);
|
||||
// Let's make the stream async using the DOMFile thread.
|
||||
nsCOMPtr<nsIAsyncInputStream> pipeIn;
|
||||
nsCOMPtr<nsIAsyncOutputStream> pipeOut;
|
||||
rv = NS_NewPipe2(getter_AddRefs(pipeIn),
|
||||
getter_AddRefs(pipeOut),
|
||||
true, true);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITransport> transport;
|
||||
rv = sts->CreateInputTransport(mRemoteStream,
|
||||
/* aCloseWhenDone */ true,
|
||||
getter_AddRefs(transport));
|
||||
RefPtr<IPCBlobInputStreamThread> thread =
|
||||
IPCBlobInputStreamThread::GetOrCreate();
|
||||
if (NS_WARN_IF(!thread)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = NS_AsyncCopy(mRemoteStream, pipeOut, thread,
|
||||
NS_ASYNCCOPY_VIA_WRITESEGMENTS);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> wrapper;
|
||||
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);
|
||||
asyncStream = pipeIn;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(asyncStream);
|
||||
|
@ -187,6 +187,8 @@ IPCBlobInputStreamChild::ActorDestroy(IProtocol::ActorDestroyReason aReason)
|
||||
// thread.
|
||||
RefPtr<IPCBlobInputStreamThread> thread =
|
||||
IPCBlobInputStreamThread::GetOrCreate();
|
||||
MOZ_ASSERT(thread, "We cannot continue without DOMFile thread.");
|
||||
|
||||
ResetManager();
|
||||
thread->MigrateActor(this);
|
||||
return;
|
||||
|
@ -36,7 +36,7 @@ public:
|
||||
{
|
||||
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
|
||||
MOZ_ASSERT(gIPCBlobThread);
|
||||
gIPCBlobThread->Initialize();
|
||||
gIPCBlobThread->InitializeOnMainThread();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
@ -93,7 +93,7 @@ NS_IMPL_ISUPPORTS_INHERITED(MigrateActorRunnable, Runnable,
|
||||
|
||||
} // anonymous
|
||||
|
||||
NS_IMPL_ISUPPORTS(IPCBlobInputStreamThread, nsIObserver)
|
||||
NS_IMPL_ISUPPORTS(IPCBlobInputStreamThread, nsIObserver, nsIEventTarget)
|
||||
|
||||
/* static */ bool
|
||||
IPCBlobInputStreamThread::IsOnFileEventTarget(nsIEventTarget* aEventTarget)
|
||||
@ -115,36 +115,21 @@ IPCBlobInputStreamThread::GetOrCreate()
|
||||
|
||||
if (!gIPCBlobThread) {
|
||||
gIPCBlobThread = new IPCBlobInputStreamThread();
|
||||
gIPCBlobThread->Initialize();
|
||||
if (!gIPCBlobThread->Initialize()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return gIPCBlobThread;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
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;
|
||||
rv = NS_NewNamedThread("DOM File", getter_AddRefs(thread));
|
||||
nsresult rv = NS_NewNamedThread("DOM File", getter_AddRefs(thread));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
mThread = thread;
|
||||
@ -156,6 +141,32 @@ IPCBlobInputStreamThread::Initialize()
|
||||
|
||||
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
|
||||
@ -205,5 +216,48 @@ IPCBlobInputStreamThread::MigrateActorInternal(IPCBlobInputStreamChild* aActor)
|
||||
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
|
||||
} // mozilla namespace
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define mozilla_dom_IPCBlobInputStreamThread_h
|
||||
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIEventTarget.h"
|
||||
|
||||
class nsIThread;
|
||||
|
||||
@ -17,10 +18,12 @@ namespace dom {
|
||||
class IPCBlobInputStreamChild;
|
||||
|
||||
class IPCBlobInputStreamThread final : public nsIObserver
|
||||
, public nsIEventTarget
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSIEVENTTARGET
|
||||
|
||||
static bool
|
||||
IsOnFileEventTarget(nsIEventTarget* aEventTarget);
|
||||
@ -31,9 +34,12 @@ public:
|
||||
void
|
||||
MigrateActor(IPCBlobInputStreamChild* aActor);
|
||||
|
||||
void
|
||||
bool
|
||||
Initialize();
|
||||
|
||||
void
|
||||
InitializeOnMainThread();
|
||||
|
||||
private:
|
||||
~IPCBlobInputStreamThread() = default;
|
||||
|
||||
|
@ -58,10 +58,13 @@ HTMLAnchorElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
|
||||
nsGenericHTMLElement::IsInteractiveHTMLContent(aIgnoreTabindex);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLAnchorElement,
|
||||
nsGenericHTMLElement,
|
||||
nsIDOMHTMLAnchorElement,
|
||||
Link)
|
||||
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLAnchorElement)
|
||||
NS_INTERFACE_TABLE_INHERITED(HTMLAnchorElement,
|
||||
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)
|
||||
|
||||
@ -83,17 +86,6 @@ HTMLAnchorElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> 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
|
||||
HTMLAnchorElement::TabIndexDefault()
|
||||
{
|
||||
@ -268,19 +260,12 @@ HTMLAnchorElement::GetLinkTarget(nsAString& aTarget)
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
HTMLAnchorElement::GetTarget(nsAString& aValue)
|
||||
{
|
||||
if (!GetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue)) {
|
||||
GetBaseTarget(aValue);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLAnchorElement::SetTarget(const nsAString& aValue)
|
||||
{
|
||||
return SetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue, true);
|
||||
}
|
||||
|
||||
nsDOMTokenList*
|
||||
@ -292,64 +277,26 @@ HTMLAnchorElement::RelList()
|
||||
return mRelList;
|
||||
}
|
||||
|
||||
#define IMPL_URI_PART(_part) \
|
||||
NS_IMETHODIMP \
|
||||
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)
|
||||
void
|
||||
HTMLAnchorElement::GetText(nsAString& aText, mozilla::ErrorResult& aRv)
|
||||
{
|
||||
if(!nsContentUtils::GetNodeTextContent(this, true, aText, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
if (NS_WARN_IF(!nsContentUtils::GetNodeTextContent(this, true, aText, fallible))) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLAnchorElement::SetText(const nsAString& aText)
|
||||
void
|
||||
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)
|
||||
{
|
||||
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>
|
||||
HTMLAnchorElement::GetHrefURI() const
|
||||
{
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/Link.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsIDOMHTMLAnchorElement.h"
|
||||
#include "nsDOMTokenList.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -19,7 +18,6 @@ class EventChainPreVisitor;
|
||||
namespace dom {
|
||||
|
||||
class HTMLAnchorElement final : public nsGenericHTMLElement,
|
||||
public nsIDOMHTMLAnchorElement,
|
||||
public Link
|
||||
{
|
||||
public:
|
||||
@ -39,15 +37,15 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLAnchorElement,
|
||||
nsGenericHTMLElement)
|
||||
|
||||
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLAnchorElement, a);
|
||||
|
||||
virtual int32_t TabIndexDefault() override;
|
||||
virtual bool Draggable() const override;
|
||||
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
|
||||
|
||||
// nsIDOMHTMLAnchorElement
|
||||
NS_DECL_NSIDOMHTMLANCHORELEMENT
|
||||
|
||||
// DOM memory reporter participant
|
||||
NS_DECL_ADDSIZEOFEXCLUDINGTHIS
|
||||
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
@ -84,12 +82,15 @@ public:
|
||||
|
||||
// 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)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::href, aValue, rv);
|
||||
}
|
||||
// The XPCOM GetTarget is OK for us
|
||||
void GetTarget(nsAString& aValue);
|
||||
void SetTarget(const nsAString& aValue, mozilla::ErrorResult& rv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::target, aValue, rv);
|
||||
@ -102,7 +103,10 @@ public:
|
||||
{
|
||||
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)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::ping, aValue, rv);
|
||||
@ -119,9 +123,9 @@ public:
|
||||
{
|
||||
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();
|
||||
void GetHreflang(DOMString& aValue)
|
||||
@ -132,6 +136,11 @@ public:
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::hreflang, aValue, rv);
|
||||
}
|
||||
// Needed for docshell
|
||||
void GetType(nsAString& aValue)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::type, aValue);
|
||||
}
|
||||
void GetType(DOMString& aValue)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::type, aValue);
|
||||
@ -140,11 +149,8 @@ public:
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::type, aValue, rv);
|
||||
}
|
||||
// The XPCOM GetText is OK for us
|
||||
void SetText(const nsAString& aValue, mozilla::ErrorResult& rv)
|
||||
{
|
||||
rv = SetText(aValue);
|
||||
}
|
||||
void GetText(nsAString& aValue, mozilla::ErrorResult& rv);
|
||||
void SetText(const nsAString& aValue, mozilla::ErrorResult& rv);
|
||||
|
||||
// Link::GetOrigin is OK for us
|
||||
|
||||
@ -175,7 +181,6 @@ public:
|
||||
// Link::Link::GetHash is OK for us
|
||||
// Link::Link::SetHash is OK for us
|
||||
|
||||
// The XPCOM URI decomposition attributes are fine for us
|
||||
void GetCoords(DOMString& aValue)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::coords, aValue);
|
||||
@ -220,6 +225,7 @@ public:
|
||||
{
|
||||
GetHref(aResult);
|
||||
}
|
||||
void ToString(nsAString& aSource);
|
||||
|
||||
virtual void NodeInfoChanged(nsIDocument* aOldDoc) final override
|
||||
{
|
||||
|
@ -42,6 +42,7 @@ public:
|
||||
|
||||
// nsIDOMHTMLAreaElement
|
||||
NS_DECL_NSIDOMHTMLAREAELEMENT
|
||||
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLAreaElement, area);
|
||||
|
||||
virtual nsresult GetEventTargetParent(
|
||||
EventChainPreVisitor& aVisitor) override;
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
|
||||
// nsIDOMHTMLLinkElement
|
||||
NS_DECL_NSIDOMHTMLLINKELEMENT
|
||||
|
||||
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLLinkElement, link);
|
||||
NS_DECL_ADDSIZEOFEXCLUDINGTHIS
|
||||
|
||||
void LinkAdded();
|
||||
|
@ -8,7 +8,6 @@ with Files("**"):
|
||||
BUG_COMPONENT = ("Core", "DOM")
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMHTMLAnchorElement.idl',
|
||||
'nsIDOMHTMLAreaElement.idl',
|
||||
'nsIDOMHTMLBaseElement.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)
|
||||
#include "mozilla/a11y/AccessibleWrap.h"
|
||||
#include "mozilla/a11y/Compatibility.h"
|
||||
#include "mozilla/a11y/nsWinUtils.h"
|
||||
#endif
|
||||
|
||||
@ -2894,6 +2895,23 @@ TabParent::SetDocShellIsActive(bool isActive)
|
||||
mDocShellIsActive = isActive;
|
||||
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
|
||||
// changing of the process priority.
|
||||
ProcessPriorityManager::TabActivityChanged(this, isActive);
|
||||
|
@ -26,7 +26,7 @@ var dshell = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
addEventListener("click",
|
||||
function(e) {
|
||||
dump(e.target + "\n");
|
||||
if (e.target instanceof Components.interfaces.nsIDOMHTMLAnchorElement &&
|
||||
if (ChromeUtils.getClassName(e.target) === "HTMLAnchorElement" &&
|
||||
dshell == docShell) {
|
||||
var retval = docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIContentFrameMessageManager).
|
||||
|
@ -49,7 +49,7 @@ skip-if = toolkit == 'android' # android(Bug 1189784, timeouts on 4.3 emulator),
|
||||
[test_getUserMedia_addTrackRemoveTrack.html]
|
||||
skip-if = android_version == '18' || os == 'linux' # android(Bug 1189784, timeouts on 4.3 emulator), linux bug 1377450
|
||||
[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_basicVideo.html]
|
||||
[test_getUserMedia_basicVideo_playAfterLoadedmetadata.html]
|
||||
|
11
dom/svg/crashtests/1402798.html
Normal file
11
dom/svg/crashtests/1402798.html
Normal file
@ -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-2.svg
|
||||
load 1347617-3.svg
|
||||
load 1402798.html
|
||||
|
@ -12,9 +12,7 @@
|
||||
<body>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.fetchObserver.enabled", true ],
|
||||
["dom.abortController.enabled", true ],
|
||||
["dom.abortController.fetch.enabled", true ]]}, () => {
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.fetchObserver.enabled", true ]]}, () => {
|
||||
let ifr = document.createElement('iframe');
|
||||
ifr.src = "file_fetch_observer.html";
|
||||
document.body.appendChild(ifr);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "WebBrowserPersistLocalDocument.h"
|
||||
#include "WebBrowserPersistDocumentParent.h"
|
||||
|
||||
#include "mozilla/dom/HTMLAnchorElement.h"
|
||||
#include "mozilla/dom/HTMLInputElement.h"
|
||||
#include "mozilla/dom/HTMLObjectElement.h"
|
||||
#include "mozilla/dom/HTMLSharedElement.h"
|
||||
@ -20,7 +21,6 @@
|
||||
#include "nsIDOMAttr.h"
|
||||
#include "nsIDOMComment.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMHTMLAnchorElement.h"
|
||||
#include "nsIDOMHTMLAreaElement.h"
|
||||
#include "nsIDOMHTMLBaseElement.h"
|
||||
#include "nsIDOMHTMLCollection.h"
|
||||
@ -941,7 +941,7 @@ PersistNodeFixup::FixupNode(nsIDOMNode *aNodeIn,
|
||||
}
|
||||
|
||||
// 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) {
|
||||
rv = GetNodeToFixup(aNodeIn, aNodeOut);
|
||||
if (NS_SUCCEEDED(rv) && *aNodeOut) {
|
||||
|
@ -7,8 +7,7 @@
|
||||
* https://dom.spec.whatwg.org/#abortcontroller
|
||||
*/
|
||||
|
||||
[Constructor(), Exposed=(Window,Worker),
|
||||
Func="AbortController::IsEnabled"]
|
||||
[Constructor(), Exposed=(Window,Worker)]
|
||||
interface AbortController {
|
||||
readonly attribute AbortSignal signal;
|
||||
|
||||
|
@ -7,8 +7,7 @@
|
||||
* https://dom.spec.whatwg.org/#abortsignal
|
||||
*/
|
||||
|
||||
[Exposed=(Window,Worker),
|
||||
Func="AbortController::IsEnabled"]
|
||||
[Exposed=(Window,Worker)]
|
||||
interface AbortSignal : EventTarget {
|
||||
readonly attribute boolean aborted;
|
||||
|
||||
|
@ -31,7 +31,7 @@ interface HTMLAnchorElement : HTMLElement {
|
||||
[CEReactions, SetterThrows]
|
||||
attribute DOMString type;
|
||||
|
||||
[CEReactions, SetterThrows]
|
||||
[CEReactions, Throws]
|
||||
attribute DOMString text;
|
||||
};
|
||||
|
||||
|
@ -27,8 +27,7 @@ interface Request {
|
||||
readonly attribute RequestRedirect redirect;
|
||||
readonly attribute DOMString integrity;
|
||||
|
||||
[Func="AbortController::IsEnabledInFetch",
|
||||
BinaryName="getOrCreateSignal"]
|
||||
[BinaryName="getOrCreateSignal"]
|
||||
readonly attribute AbortSignal signal;
|
||||
|
||||
[Throws,
|
||||
@ -52,7 +51,6 @@ dictionary RequestInit {
|
||||
RequestRedirect redirect;
|
||||
DOMString integrity;
|
||||
|
||||
[Func="AbortController::IsEnabledInFetch"]
|
||||
AbortSignal? signal;
|
||||
|
||||
[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("dom.webkitBlink.dirPicker.enabled", WebkitBlinkDirectoryPickerEnabled, DOM_WEBKITBLINK_DIRPICKER_WEBKITBLINK)
|
||||
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("privacy.resistFingerprinting", ResistFingerprintingEnabled, RESISTFINGERPRINTING_ENABLED)
|
||||
WORKER_SIMPLE_PREF("devtools.enabled", DevToolsEnabled, DEVTOOLS_ENABLED)
|
||||
|
@ -18,11 +18,11 @@
|
||||
#include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::a, etc.
|
||||
#include "nsHTMLTags.h"
|
||||
#include "nsIAtom.h" // for nsIAtom
|
||||
#include "nsIDOMHTMLAnchorElement.h" // for nsIDOMHTMLAnchorElement
|
||||
#include "nsIDOMNode.h" // for nsIDOMNode
|
||||
#include "nsNameSpaceManager.h" // for kNameSpaceID_None
|
||||
#include "nsLiteralString.h" // for NS_LITERAL_STRING
|
||||
#include "nsString.h" // for nsAutoString
|
||||
#include "mozilla/dom/HTMLAnchorElement.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -336,14 +336,18 @@ HTMLEditUtils::IsLink(nsINode* aNode)
|
||||
{
|
||||
MOZ_ASSERT(aNode);
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(aNode);
|
||||
if (anchor) {
|
||||
nsAutoString tmpText;
|
||||
if (NS_SUCCEEDED(anchor->GetHref(tmpText)) && !tmpText.IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
if (!aNode->IsContent()) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContentOrNull(aNode->AsContent());
|
||||
if (!anchor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoString tmpText;
|
||||
anchor->GetHref(tmpText);
|
||||
return !tmpText.IsEmpty();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "nsIDocumentInlines.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIDOMHTMLAnchorElement.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsILinkHandler.h"
|
||||
@ -2594,19 +2593,21 @@ HTMLEditor::InsertLinkAroundSelection(nsIDOMElement* aAnchorElement)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// 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) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString href;
|
||||
nsresult rv = anchor->GetHref(href);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
anchor->GetHref(href);
|
||||
if (href.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
|
||||
// Set all attributes found on the supplied anchor element
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMDocumentFragment.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMHTMLAnchorElement.h"
|
||||
#include "nsIDOMHTMLFrameElement.h"
|
||||
#include "nsIDOMHTMLIFrameElement.h"
|
||||
#include "nsIDOMHTMLImageElement.h"
|
||||
|
@ -608,10 +608,6 @@ GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage,
|
||||
case ImageFormat::SURFACE_TEXTURE:
|
||||
return BlitImage(static_cast<layers::SurfaceTextureImage*>(srcImage), destSize,
|
||||
destOrigin);
|
||||
|
||||
case ImageFormat::EGLIMAGE:
|
||||
return BlitImage(static_cast<layers::EGLImageImage*>(srcImage), destSize,
|
||||
destOrigin);
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
case ImageFormat::MAC_IOSURFACE:
|
||||
@ -647,41 +643,6 @@ GLBlitHelper::BlitImage(layers::SurfaceTextureImage* srcImage, const gfx::IntSiz
|
||||
gfxCriticalError() << "BlitImage(SurfaceTextureImage) not implemented.";
|
||||
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
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -28,7 +28,6 @@ class GPUVideoImage;
|
||||
class PlanarYCbCrImage;
|
||||
class SurfaceTextureImage;
|
||||
class MacIOSurfaceImage;
|
||||
class EGLImageImage;
|
||||
class SurfaceDescriptorD3D10;
|
||||
class SurfaceDescriptorDXGIYCbCr;
|
||||
} // namespace layers
|
||||
@ -133,8 +132,6 @@ public:
|
||||
// Blit onto the current FB.
|
||||
bool BlitImage(layers::SurfaceTextureImage* stImage, const gfx::IntSize& destSize,
|
||||
OriginPos destOrigin) const;
|
||||
bool BlitImage(layers::EGLImageImage* eglImage, const gfx::IntSize& destSize,
|
||||
OriginPos destOrigin) const;
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
bool BlitImage(layers::MacIOSurfaceImage* srcImage, const gfx::IntSize& destSize,
|
||||
|
@ -16,35 +16,6 @@ namespace layers {
|
||||
|
||||
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>
|
||||
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
|
||||
|
||||
class SurfaceTextureImage : public GLImage {
|
||||
|
@ -174,7 +174,6 @@ protected:
|
||||
|
||||
/* Forward declarations for Image derivatives. */
|
||||
class GLImage;
|
||||
class EGLImageImage;
|
||||
class SharedRGBImage;
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
class SurfaceTextureImage;
|
||||
@ -233,7 +232,6 @@ public:
|
||||
virtual TextureClient* GetTextureClient(KnowsCompositor* aForwarder) { return nullptr; }
|
||||
|
||||
/* Access to derived classes. */
|
||||
virtual EGLImageImage* AsEGLImageImage() { return nullptr; }
|
||||
virtual GLImage* AsGLImage() { return nullptr; }
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
virtual SurfaceTextureImage* AsSurfaceTextureImage() { return nullptr; }
|
||||
|
@ -55,11 +55,6 @@ enum class ImageFormat {
|
||||
*/
|
||||
SURFACE_TEXTURE,
|
||||
|
||||
/**
|
||||
* An EGL Image that can be shared across threads.
|
||||
*/
|
||||
EGLIMAGE,
|
||||
|
||||
/**
|
||||
* The D3D9_RGB32_TEXTURE format creates a D3D9SurfaceImage, and wraps a
|
||||
* IDirect3DTexture9 in RGB32 layout.
|
||||
|
@ -400,8 +400,6 @@ AppendToString(std::stringstream& aStream, ImageFormat format,
|
||||
aStream << "ImageFormat::MAC_IOSURFACE"; break;
|
||||
case ImageFormat::SURFACE_TEXTURE:
|
||||
aStream << "ImageFormat::SURFACE_TEXTURE"; break;
|
||||
case ImageFormat::EGLIMAGE:
|
||||
aStream << "ImageFormat::EGLIMAGE"; break;
|
||||
case ImageFormat::D3D9_RGB32_TEXTURE:
|
||||
aStream << "ImageFormat::D3D9_RBG32_TEXTURE"; break;
|
||||
case ImageFormat::OVERLAY_IMAGE:
|
||||
|
@ -118,24 +118,14 @@ ImageClient::CreateTextureClientForImage(Image* aImage, KnowsCompositor* aForwar
|
||||
if (!status) {
|
||||
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
|
||||
} else if (aImage->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
|
||||
SurfaceTextureImage* typedImage = aImage->AsSurfaceTextureImage();
|
||||
texture = AndroidSurfaceTextureData::CreateTextureClient(
|
||||
typedImage->GetHandle(), size, typedImage->GetContinuous(), typedImage->GetOriginPos(),
|
||||
aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
|
||||
} else if (aImage->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
|
||||
gfx::IntSize size = aImage->GetSize();
|
||||
SurfaceTextureImage* typedImage = aImage->AsSurfaceTextureImage();
|
||||
texture = AndroidSurfaceTextureData::CreateTextureClient(
|
||||
typedImage->GetHandle(), size, typedImage->GetContinuous(), typedImage->GetOriginPos(),
|
||||
aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
|
||||
#endif
|
||||
} else {
|
||||
MOZ_ASSERT(false, "Bad ImageFormat.");
|
||||
}
|
||||
} else {
|
||||
RefPtr<gfx::SourceSurface> surface = aImage->GetAsSourceSurface();
|
||||
MOZ_ASSERT(surface);
|
||||
|
@ -17,62 +17,6 @@ namespace layers {
|
||||
|
||||
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
|
||||
|
||||
|
@ -20,34 +20,6 @@ namespace mozilla {
|
||||
|
||||
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
|
||||
|
||||
class AndroidSurfaceTextureData : public TextureData
|
||||
|
@ -608,12 +608,15 @@ WebRenderDebugPrefChangeCallback(const char* aPrefName, void*)
|
||||
if (Preferences::GetBool(WR_DEBUG_PREF".profiler", false)) {
|
||||
flags |= (1 << 0);
|
||||
}
|
||||
if (Preferences::GetBool(WR_DEBUG_PREF".texture-cache", false)) {
|
||||
if (Preferences::GetBool(WR_DEBUG_PREF".render-targets", false)) {
|
||||
flags |= (1 << 1);
|
||||
}
|
||||
if (Preferences::GetBool(WR_DEBUG_PREF".render-targets", false)) {
|
||||
if (Preferences::GetBool(WR_DEBUG_PREF".texture-cache", false)) {
|
||||
flags |= (1 << 2);
|
||||
}
|
||||
if (Preferences::GetBool(WR_DEBUG_PREF".alpha-primitives", false)) {
|
||||
flags |= (1 << 3);
|
||||
}
|
||||
|
||||
gfx::gfxVars::SetWebRenderDebugFlags(flags);
|
||||
}
|
||||
|
@ -600,7 +600,7 @@ UnknownPropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleV
|
||||
}
|
||||
|
||||
bool
|
||||
UnknownStrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
|
||||
UnknownStrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||
ObjectOpResult& result)
|
||||
{
|
||||
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
|
||||
* 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
|
||||
* parameter, on success, is the new property value after the
|
||||
* set.
|
||||
* (Unicode property identifier) or an int (element index).
|
||||
*/
|
||||
typedef bool
|
||||
(* 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.
|
||||
|
@ -642,7 +642,7 @@ array_length_getter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleV
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
// chain. Ideally the setter should not have been called, but since
|
||||
// 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>());
|
||||
MOZ_ASSERT(arr->lengthIsWritable(),
|
||||
"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
|
||||
|
@ -1327,7 +1327,6 @@ JSContext::JSContext(JSRuntime* runtime, const JS::ContextOptions& options)
|
||||
suppressProfilerSampling(false),
|
||||
tempLifoAlloc_((size_t)TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
debuggerMutations(0),
|
||||
propertyRemovals(0),
|
||||
ionPcScriptCache(nullptr),
|
||||
throwing(false),
|
||||
overRecursed_(false),
|
||||
|
@ -613,13 +613,6 @@ struct JSContext : public JS::RootingContext,
|
||||
|
||||
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().
|
||||
js::ThreadLocalData<js::jit::PcScriptCache*> ionPcScriptCache;
|
||||
|
||||
|
@ -365,14 +365,14 @@ CallJSGetterOp(JSContext* cx, GetterOp op, HandleObject obj, HandleId id,
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!CheckRecursionLimit(cx))
|
||||
return false;
|
||||
|
||||
assertSameCompartment(cx, obj, id, vp);
|
||||
return op(cx, obj, id, vp, result);
|
||||
assertSameCompartment(cx, obj, id, v);
|
||||
return op(cx, obj, id, v, result);
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
@ -195,10 +195,8 @@ js::SetPropertyIgnoringNamedGetter(JSContext* cx, HandleObject obj, HandleId id,
|
||||
RootedObject receiverObj(cx, &receiver.toObject());
|
||||
|
||||
// Nonstandard SpiderMonkey special case: setter ops.
|
||||
if (SetterOp setter = ownDesc.setter()) {
|
||||
RootedValue valCopy(cx, v);
|
||||
return CallJSSetterOp(cx, setter, receiverObj, id, &valCopy, result);
|
||||
}
|
||||
if (SetterOp setter = ownDesc.setter())
|
||||
return CallJSSetterOp(cx, setter, receiverObj, id, v, result);
|
||||
|
||||
// Steps 5.c-d.
|
||||
Rooted<PropertyDescriptor> existingDescriptor(cx);
|
||||
|
@ -476,7 +476,7 @@ MappedArgGetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue
|
||||
}
|
||||
|
||||
static bool
|
||||
MappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
|
||||
MappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||
ObjectOpResult& result)
|
||||
{
|
||||
if (!obj->is<MappedArgumentsObject>())
|
||||
@ -499,9 +499,9 @@ MappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue
|
||||
if (JSID_IS_INT(id)) {
|
||||
unsigned arg = unsigned(JSID_TO_INT(id));
|
||||
if (arg < argsobj->initialLength() && !argsobj->isElementDeleted(arg)) {
|
||||
argsobj->setElement(cx, arg, vp);
|
||||
argsobj->setElement(cx, arg, v);
|
||||
if (arg < script->functionNonDelazifying()->nargs())
|
||||
TypeScript::SetArgument(cx, script, arg, vp);
|
||||
TypeScript::SetArgument(cx, script, arg, v);
|
||||
return result.succeed();
|
||||
}
|
||||
} else {
|
||||
@ -518,7 +518,7 @@ MappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue
|
||||
*/
|
||||
ObjectOpResult ignored;
|
||||
return NativeDeleteProperty(cx, argsobj, id, ignored) &&
|
||||
NativeDefineDataProperty(cx, argsobj, id, vp, attrs, result);
|
||||
NativeDefineDataProperty(cx, argsobj, id, v, attrs, result);
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -726,7 +726,7 @@ UnmappedArgGetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleVal
|
||||
}
|
||||
|
||||
static bool
|
||||
UnmappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
|
||||
UnmappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||
ObjectOpResult& result)
|
||||
{
|
||||
if (!obj->is<UnmappedArgumentsObject>())
|
||||
@ -744,7 +744,7 @@ UnmappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleVal
|
||||
if (JSID_IS_INT(id)) {
|
||||
unsigned arg = unsigned(JSID_TO_INT(id));
|
||||
if (arg < argsobj->initialLength()) {
|
||||
argsobj->setElement(cx, arg, vp);
|
||||
argsobj->setElement(cx, arg, v);
|
||||
return result.succeed();
|
||||
}
|
||||
} else {
|
||||
@ -758,7 +758,7 @@ UnmappedArgSetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleVal
|
||||
*/
|
||||
ObjectOpResult ignored;
|
||||
return NativeDeleteProperty(cx, argsobj, id, ignored) &&
|
||||
NativeDefineDataProperty(cx, argsobj, id, vp, attrs, result);
|
||||
NativeDefineDataProperty(cx, argsobj, id, v, attrs, result);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
|
@ -2503,22 +2503,8 @@ NativeSetExistingDataProperty(JSContext* cx, HandleNativeObject obj, HandleShape
|
||||
|
||||
MOZ_ASSERT(!obj->is<WithEnvironmentObject>()); // See bug 1128681.
|
||||
|
||||
uint32_t sample = cx->propertyRemovals;
|
||||
RootedId id(cx, shape->propid());
|
||||
RootedValue value(cx, v);
|
||||
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.
|
||||
return CallJSSetterOp(cx, shape->setterOp(), obj, id, v, result);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2729,8 +2715,7 @@ SetExistingProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleVa
|
||||
if (shape->hasDefaultSetter())
|
||||
return result.succeed();
|
||||
|
||||
RootedValue valCopy(cx, v);
|
||||
return CallJSSetterOp(cx, shape->setterOp(), obj, id, &valCopy, result);
|
||||
return CallJSSetterOp(cx, shape->setterOp(), obj, id, v, result);
|
||||
}
|
||||
|
||||
// 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
|
||||
* property (shape here) has a slotSpan that does not cover it.
|
||||
*/
|
||||
if (hadSlot && !shape->hasSlot()) {
|
||||
if (oldSlot < obj->slotSpan())
|
||||
obj->freeSlot(cx, oldSlot);
|
||||
/* Note: The optimization based on propertyRemovals is only relevant to the active thread. */
|
||||
if (!cx->helperThread())
|
||||
++cx->propertyRemovals;
|
||||
}
|
||||
if (hadSlot && !shape->hasSlot() && oldSlot < obj->slotSpan())
|
||||
obj->freeSlot(cx, oldSlot);
|
||||
|
||||
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->hasSlot()) {
|
||||
if (shape->hasSlot())
|
||||
obj->freeSlot(cx, shape->slot());
|
||||
if (!cx->helperThread())
|
||||
++cx->propertyRemovals;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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));
|
||||
|
||||
if (!cx->helperThread())
|
||||
++cx->propertyRemovals;
|
||||
obj->checkShapeConsistency();
|
||||
}
|
||||
|
||||
|
@ -440,14 +440,14 @@ sandbox_moved(JSObject* obj, JSObject* old)
|
||||
|
||||
static bool
|
||||
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);
|
||||
if (!JS_GetPrototype(cx, obj, &proto))
|
||||
return false;
|
||||
|
||||
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
|
||||
|
@ -762,7 +762,7 @@ nsIPresShell::nsIPresShell()
|
||||
, mFrozen(false)
|
||||
, mIsFirstPaint(false)
|
||||
, mObservesMutationsForPrint(false)
|
||||
, mSuppressInterruptibleReflows(false)
|
||||
, mWasLastReflowInterrupted(false)
|
||||
, mScrollPositionClampingScrollPortSizeSet(false)
|
||||
, mNeedLayoutFlush(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
|
||||
// be good.
|
||||
|
||||
if (flushType >= (mSuppressInterruptibleReflows
|
||||
if (flushType >= (SuppressInterruptibleReflows()
|
||||
? FlushType::Layout
|
||||
: FlushType::InterruptibleLayout) &&
|
||||
!mIsDestroying) {
|
||||
@ -4232,7 +4232,7 @@ PresShell::DoFlushPendingNotifications(mozilla::ChangesToFlush aFlush)
|
||||
if (!didLayoutFlush && flushType >= FlushType::InterruptibleLayout &&
|
||||
!mIsDestroying) {
|
||||
// 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.
|
||||
SetNeedLayoutFlush();
|
||||
}
|
||||
@ -9457,7 +9457,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
|
||||
// Any FlushPendingNotifications with interruptible reflows
|
||||
// should be suppressed now. We don't want to do extra reflow work
|
||||
// before our reflow event happens.
|
||||
mSuppressInterruptibleReflows = true;
|
||||
mWasLastReflowInterrupted = true;
|
||||
MaybeScheduleReflow();
|
||||
}
|
||||
|
||||
|
@ -1581,6 +1581,21 @@ public:
|
||||
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.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -1794,7 +1809,8 @@ protected:
|
||||
bool mIsFirstPaint : 1;
|
||||
bool mObservesMutationsForPrint : 1;
|
||||
|
||||
bool mSuppressInterruptibleReflows : 1;
|
||||
// Whether the most recent interruptible reflow was actually interrupted:
|
||||
bool mWasLastReflowInterrupted : 1;
|
||||
bool mScrollPositionClampingScrollPortSizeSet : 1;
|
||||
|
||||
// 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);
|
||||
shell->mObservingLayoutFlushes = false;
|
||||
shell->mSuppressInterruptibleReflows = false;
|
||||
shell->mWasLastReflowInterrupted = false;
|
||||
FlushType flushType = HasPendingAnimations(shell)
|
||||
? FlushType::Layout
|
||||
: FlushType::InterruptibleLayout;
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsIDOMHTMLAnchorElement.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include <algorithm>
|
||||
#ifdef ACCESSIBILITY
|
||||
@ -81,6 +80,7 @@
|
||||
|
||||
#include "mozilla/dom/Link.h"
|
||||
#include "SVGImageContext.h"
|
||||
#include "mozilla/dom/HTMLAnchorElement.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -1993,7 +1993,7 @@ nsImageFrame::GetAnchorHREFTargetAndNode(nsIURI** aHref, nsString& aTarget,
|
||||
}
|
||||
status = (*aHref != nullptr);
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(content));
|
||||
RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromContent(content);
|
||||
if (anchor) {
|
||||
anchor->GetTarget(aTarget);
|
||||
}
|
||||
|
@ -104,7 +104,6 @@ static const char kPrintingPromptService[] = "@mozilla.org/embedcomp/printingpro
|
||||
#include "nsILayoutHistoryState.h"
|
||||
#include "nsFrameManager.h"
|
||||
#include "mozilla/ReflowInput.h"
|
||||
#include "nsIDOMHTMLAnchorElement.h"
|
||||
#include "nsIDOMHTMLAreaElement.h"
|
||||
#include "nsIDOMHTMLLinkElement.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
|
||||
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
|
||||
== 508908-1.xul 508908-1-ref.xul
|
||||
skip-if(isDebugBuild) == 508908-1.xul 508908-1-ref.xul
|
||||
== 508919-1.xhtml 508919-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
|
||||
|
@ -372,7 +372,8 @@ include ../../toolkit/themes/osx/reftests/reftest.list
|
||||
include ../../toolkit/content/tests/reftests/reftest.list
|
||||
|
||||
# -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
|
||||
include transform-3d/reftest.list
|
||||
|
@ -356,6 +356,9 @@ class RemoteReftest(RefTest):
|
||||
debuggerInfo=debuggerInfo,
|
||||
symbolsPath=symbolsPath,
|
||||
timeout=timeout)
|
||||
if status == 1:
|
||||
# when max run time exceeded, avoid restart
|
||||
lastTestSeen = RefTest.TEST_SEEN_FINAL
|
||||
return status, lastTestSeen
|
||||
|
||||
def cleanup(self, profileDir):
|
||||
|
@ -429,9 +429,9 @@ class RefTest(object):
|
||||
self._populate_logger(options)
|
||||
|
||||
# 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
|
||||
VERIFY_REPEAT_SINGLE_BROWSER = 10
|
||||
VERIFY_REPEAT_SINGLE_BROWSER = 5
|
||||
|
||||
def step1():
|
||||
stepOptions = copy.deepcopy(options)
|
||||
@ -448,12 +448,34 @@ class RefTest(object):
|
||||
break
|
||||
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 = [
|
||||
("1. Run each test %d times in one browser." % VERIFY_REPEAT,
|
||||
step1),
|
||||
("2. Run each test %d times in a new browser each time." %
|
||||
VERIFY_REPEAT_SINGLE_BROWSER,
|
||||
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 = {}
|
||||
|
@ -484,10 +484,13 @@ public final class IntentHelper implements BundleEventListener {
|
||||
*/
|
||||
private void openNoHandler(final GeckoBundle msg, final EventCallback callback) {
|
||||
final String uri = msg.getString("uri");
|
||||
final GeckoBundle errorResponse = new GeckoBundle();
|
||||
|
||||
if (TextUtils.isEmpty(uri)) {
|
||||
Log.w(LOGTAG, "Received empty URL - loading about:neterror");
|
||||
callback.sendError(getUnknownProtocolErrorPageUri(""));
|
||||
errorResponse.putString("uri", getUnknownProtocolErrorPageUri(""));
|
||||
errorResponse.putBoolean("isFallback", false);
|
||||
callback.sendError(errorResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -505,7 +508,9 @@ public final class IntentHelper implements BundleEventListener {
|
||||
|
||||
// Don't log the exception to prevent leaking URIs.
|
||||
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;
|
||||
}
|
||||
|
||||
@ -513,9 +518,10 @@ public final class IntentHelper implements BundleEventListener {
|
||||
// https://developer.chrome.com/multidevice/android/intents
|
||||
final String fallbackUrl = intent.getStringExtra(EXTRA_BROWSER_FALLBACK_URL);
|
||||
if (isFallbackUrlValid(fallbackUrl)) {
|
||||
errorResponse.putString("uri", fallbackUrl);
|
||||
errorResponse.putBoolean("isFallback", true);
|
||||
// Opens the page in JS.
|
||||
callback.sendError(fallbackUrl);
|
||||
|
||||
callback.sendError(errorResponse);
|
||||
} else if (intent.getPackage() != null) {
|
||||
// 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
|
||||
@ -552,7 +558,9 @@ public final class IntentHelper implements BundleEventListener {
|
||||
//
|
||||
// Don't log the URI to prevent leaking it.
|
||||
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) {
|
||||
// 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));
|
||||
try {
|
||||
return Strings.browser.GetStringFromName("browser.menu.context." + uri.scheme);
|
||||
@ -2820,7 +2820,7 @@ var NativeWindow = {
|
||||
|
||||
// Returns a url associated with a node
|
||||
_getUrl: function(node) {
|
||||
if ((node instanceof Ci.nsIDOMHTMLAnchorElement && node.href) ||
|
||||
if ((ChromeUtils.getClassName(node) === "HTMLAnchorElement" && node.href) ||
|
||||
(node instanceof Ci.nsIDOMHTMLAreaElement && node.href)) {
|
||||
return this._getLinkURL(node);
|
||||
} else if (node instanceof Ci.nsIImageLoadingContent && node.currentURI) {
|
||||
@ -3051,7 +3051,7 @@ var NativeWindow = {
|
||||
|
||||
_getLink: function(aElement) {
|
||||
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.nsIDOMHTMLLinkElement ||
|
||||
aElement.getAttributeNS(kXLinkNamespace, "type") == "simple")) {
|
||||
@ -4775,7 +4775,7 @@ var BrowserEventHandler = {
|
||||
|
||||
_getLinkURI: function(aElement) {
|
||||
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))) {
|
||||
try {
|
||||
return Services.io.newURI(aElement.href);
|
||||
|
@ -64,6 +64,8 @@ function startup() {
|
||||
"GeckoViewScroll");
|
||||
ModuleManager.add("resource://gre/modules/GeckoViewTab.jsm",
|
||||
"GeckoViewTab");
|
||||
ModuleManager.add("resource://gre/modules/GeckoViewRemoteDebugger.jsm",
|
||||
"GeckoViewRemoteDebugger");
|
||||
|
||||
// Move focus to the content window at the end of startup,
|
||||
// so things like text selection can work properly.
|
||||
|
@ -65,15 +65,20 @@ ContentDispatchChooser.prototype =
|
||||
|
||||
EventDispatcher.instance.sendRequestForResult(msg).then(() => {
|
||||
// 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
|
||||
// want this to fail silently. If the user entered this on the address bar, though,
|
||||
// we want to show the neterror page.
|
||||
|
||||
let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
let millis = dwu.millisSinceLastUserInput;
|
||||
if (millis > 0 && millis >= 1000) {
|
||||
window.location.href = uri;
|
||||
window.location.href = data.uri;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -496,6 +496,9 @@ public class GeckoView extends LayerView {
|
||||
} else {
|
||||
mSettings = settings;
|
||||
}
|
||||
mSettings.setString(GeckoViewSettings.DEBUGGER_SOCKET_DIR,
|
||||
context.getApplicationInfo().dataDir);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -65,6 +65,11 @@ public final class GeckoViewSettings {
|
||||
public static final Key<Integer> DISPLAY_MODE =
|
||||
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 GeckoBundle mBundle;
|
||||
@ -81,6 +86,9 @@ public final class GeckoViewSettings {
|
||||
setBoolean(USE_PRIVATE_MODE, false);
|
||||
setBoolean(USE_MULTIPROCESS, true);
|
||||
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) {
|
||||
@ -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() {
|
||||
return mBundle;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ public class GeckoViewActivity extends Activity {
|
||||
private static final String LOGTAG = "GeckoViewActivity";
|
||||
private static final String DEFAULT_URL = "https://mozilla.org";
|
||||
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;
|
||||
private static final int REQUEST_PERMISSIONS = 2;
|
||||
@ -95,6 +96,9 @@ public class GeckoViewActivity extends Activity {
|
||||
mGeckoView.getSettings().setBoolean(
|
||||
GeckoViewSettings.USE_MULTIPROCESS,
|
||||
intent.getBooleanExtra(USE_MULTIPROCESS_EXTRA, true));
|
||||
mGeckoView.getSettings().setBoolean(
|
||||
GeckoViewSettings.USE_REMOTE_DEBUGGER,
|
||||
intent.getBooleanExtra(USE_REMOTE_DEBUGGER_EXTRA, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -443,10 +443,8 @@
|
||||
@BINPATH@/features/*
|
||||
|
||||
; DevTools
|
||||
#ifndef MOZ_GECKOVIEW_JAR
|
||||
@BINPATH@/chrome/devtools@JAREXT@
|
||||
@BINPATH@/chrome/devtools.manifest
|
||||
#endif
|
||||
|
||||
; [Default Preferences]
|
||||
; All the pref files must be part of base to prevent migration bugs
|
||||
|
110
mobile/android/modules/geckoview/GeckoViewRemoteDebugger.jsm
Normal file
110
mobile/android/modules/geckoview/GeckoViewRemoteDebugger.jsm
Normal file
@ -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.
|
||||
class GeckoViewTab extends GeckoViewModule {
|
||||
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],
|
||||
selectedTab: this.browser.tab,
|
||||
|
||||
|
@ -11,6 +11,7 @@ EXTRA_JS_MODULES += [
|
||||
'GeckoViewModule.jsm',
|
||||
'GeckoViewNavigation.jsm',
|
||||
'GeckoViewProgress.jsm',
|
||||
'GeckoViewRemoteDebugger.jsm',
|
||||
'GeckoViewScroll.jsm',
|
||||
'GeckoViewSettings.jsm',
|
||||
'GeckoViewTab.jsm',
|
||||
|
@ -880,6 +880,7 @@ pref("gfx.webrender.blob-images", false);
|
||||
// WebRender debugging utilities.
|
||||
pref("gfx.webrender.debug.texture-cache", false);
|
||||
pref("gfx.webrender.debug.render-targets", false);
|
||||
pref("gfx.webrender.debug.alpha-primitives", false);
|
||||
pref("gfx.webrender.debug.profiler", false);
|
||||
|
||||
// Whether webrender should be used as much as possible.
|
||||
@ -5075,12 +5076,6 @@ pref("dom.battery.enabled", true);
|
||||
// Streams API
|
||||
pref("dom.streams.enabled", false);
|
||||
|
||||
// Abort API
|
||||
pref("dom.abortController.enabled", true);
|
||||
|
||||
// Fetch + Abort API
|
||||
pref("dom.abortController.fetch.enabled", true);
|
||||
|
||||
// Push
|
||||
|
||||
pref("dom.push.enabled", false);
|
||||
|
@ -2326,9 +2326,9 @@ toolbar#nav-bar {
|
||||
"""
|
||||
|
||||
# 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
|
||||
VERIFY_REPEAT_SINGLE_BROWSER = 10
|
||||
VERIFY_REPEAT_SINGLE_BROWSER = 5
|
||||
|
||||
def step1():
|
||||
stepOptions = copy.deepcopy(options)
|
||||
@ -2352,12 +2352,41 @@ toolbar#nav-bar {
|
||||
break
|
||||
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 = [
|
||||
("1. Run each test %d times in one browser." % VERIFY_REPEAT,
|
||||
step1),
|
||||
("2. Run each test %d times in a new browser each time." %
|
||||
VERIFY_REPEAT_SINGLE_BROWSER,
|
||||
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 = {}
|
||||
|
@ -101,8 +101,8 @@ def create_parser(mach_interface=False):
|
||||
add_arg('--geckoProfileEntries', dest="gecko_profile_entries", type=int,
|
||||
help="How many samples to take with the profiler")
|
||||
add_arg('--extension', dest='extensions', action='append',
|
||||
default=['${talos}/talos-powers/talos-powers-signed.xpi',
|
||||
'${talos}/pageloader/pageloader-signed.xpi'],
|
||||
default=['${talos}/talos-powers',
|
||||
'${talos}/pageloader'],
|
||||
help="Extension to install while running")
|
||||
add_arg('--fast', action='store_true',
|
||||
help="Run tp tests as tp_fast")
|
||||
|
@ -194,7 +194,9 @@ DEFAULTS = dict(
|
||||
'identity.fxaccounts.migrateToDevEdition': False,
|
||||
'plugin.state.flash': 0,
|
||||
'media.libavcodec.allow-obsolete': True,
|
||||
'extensions.legacy.enabled': True
|
||||
'extensions.legacy.enabled': True,
|
||||
'xpinstall.signatures.required': False,
|
||||
'extensions.allow-non-mpc-extensions': True
|
||||
}
|
||||
)
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user