diff --git a/accessible/base/NotificationController.cpp b/accessible/base/NotificationController.cpp index d08500458221..8263c7b54d83 100644 --- a/accessible/base/NotificationController.cpp +++ b/accessible/base/NotificationController.cpp @@ -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. diff --git a/accessible/windows/msaa/RootAccessibleWrap.cpp b/accessible/windows/msaa/RootAccessibleWrap.cpp index ed99b20a669f..4475844516c6 100644 --- a/accessible/windows/msaa/RootAccessibleWrap.cpp +++ b/accessible/windows/msaa/RootAccessibleWrap.cpp @@ -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(); diff --git a/browser/branding/aurora/pref/firefox-branding.js b/browser/branding/aurora/pref/firefox-branding.js index df0d1613ebed..bfd29a3c4cde 100644 --- a/browser/branding/aurora/pref/firefox-branding.js +++ b/browser/branding/aurora/pref/firefox-branding.js @@ -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 diff --git a/browser/components/distribution.js b/browser/components/distribution.js index 3d0229e998c2..9d0b6082316b 100644 --- a/browser/components/distribution.js +++ b/browser/components/distribution.js @@ -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; diff --git a/browser/components/tests/unit/test_distribution.js b/browser/components/tests/unit/test_distribution.js index b722ba5a4a54..8c7ea429b683 100644 --- a/browser/components/tests/unit/test_distribution.js +++ b/browser/components/tests/unit/test_distribution.js @@ -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() { diff --git a/browser/components/tests/unit/test_distribution_cachedexistence.js b/browser/components/tests/unit/test_distribution_cachedexistence.js new file mode 100644 index 000000000000..25fecb9a27f0 --- /dev/null +++ b/browser/components/tests/unit/test_distribution_cachedexistence.js @@ -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); +}); diff --git a/browser/components/tests/unit/xpcshell.ini b/browser/components/tests/unit/xpcshell.ini index c2f461966a88..cce6ba2897b7 100644 --- a/browser/components/tests/unit/xpcshell.ini +++ b/browser/components/tests/unit/xpcshell.ini @@ -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] diff --git a/browser/modules/PluginContent.jsm b/browser/modules/PluginContent.jsm index 678369d7e3ec..4a74650ebadd 100644 --- a/browser/modules/PluginContent.jsm +++ b/browser/modules/PluginContent.jsm @@ -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; diff --git a/devtools/client/shared/curl.js b/devtools/client/shared/curl.js index 73e33ebc06db..ec50b7fe02a1 100644 --- a/devtools/client/shared/curl.js +++ b/devtools/client/shared/curl.js @@ -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) { diff --git a/devtools/client/shared/vendor/WasmDis.js b/devtools/client/shared/vendor/WasmDis.js index 6282690c6705..5921ab4bad21 100644 --- a/devtools/client/shared/vendor/WasmDis.js +++ b/devtools/client/shared/vendor/WasmDis.js @@ -747,4 +747,3 @@ var WasmDisassembler = (function () { return WasmDisassembler; }()); exports.WasmDisassembler = WasmDisassembler; -//# sourceMappingURL=WasmDis.js.map \ No newline at end of file diff --git a/devtools/client/shared/vendor/WasmParser.js b/devtools/client/shared/vendor/WasmParser.js index 8bee4f741a2b..4fb440b91b1d 100644 --- a/devtools/client/shared/vendor/WasmParser.js +++ b/devtools/client/shared/vendor/WasmParser.js @@ -1400,4 +1400,3 @@ if (!exports.bytesToString) { return decodeURIComponent(escape(str)); }; } -//# sourceMappingURL=WasmParser.js.map \ No newline at end of file diff --git a/devtools/server/actors/object.js b/devtools/server/actors/object.js index b11862b7ba54..d1c79a7c0a23 100644 --- a/devtools/server/actors/object.js +++ b/devtools/server/actors/object.js @@ -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; diff --git a/devtools/server/main.js b/devtools/server/main.js index 379bc3eb78a6..f2461e88b598 100644 --- a/devtools/server/main.js +++ b/devtools/server/main.js @@ -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) { diff --git a/devtools/server/tests/unit/test_objectgrips-17.js b/devtools/server/tests/unit/test_objectgrips-17.js index 9c0f5236928a..a56ef7b6b4d6 100644 --- a/devtools/server/tests/unit/test_objectgrips-17.js +++ b/devtools/server/tests/unit/test_objectgrips-17.js @@ -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, " contains the [[ProxyTarget]]."); let handler = preview.ownProperties[""].value; strictEqual(handler, grip.proxyHandler, " 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(!("" in preview), "The preview has no property."); ok(!("" in preview), "The preview has no 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."); } } - diff --git a/devtools/shared/webconsole/test/test_consoleapi.html b/devtools/shared/webconsole/test/test_consoleapi.html index fe926f5661eb..d99cb01a38f4 100644 --- a/devtools/shared/webconsole/test/test_consoleapi.html +++ b/devtools/shared/webconsole/test/test_consoleapi.html @@ -149,7 +149,7 @@ function doConsoleCalls(aState) { type: "object", actor: /[a-z]/, - class: "Object", + class: "Inaccessible", }, ], }, diff --git a/docshell/base/nsContextMenuInfo.cpp b/docshell/base/nsContextMenuInfo.cpp index 2197540b41b6..4bca372ddf5b 100644 --- a/docshell/base/nsContextMenuInfo.cpp +++ b/docshell/base/nsContextMenuInfo.cpp @@ -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 content(do_QueryInterface(mAssociatedLink)); - nsAutoString localName; - if (content) { - content->GetLocalName(localName); - } - - nsCOMPtr linkContent; - ToLowerCase(localName); - if (localName.EqualsLiteral("a") || - localName.EqualsLiteral("area") || - localName.EqualsLiteral("link")) { - bool hasAttr; - content->HasAttribute(NS_LITERAL_STRING("href"), &hasAttr); + nsCOMPtr content(do_QueryInterface(mAssociatedLink)); + nsCOMPtr linkContent; + if (content && + content->IsAnyOfHTMLElements(nsGkAtoms::a, + nsGkAtoms::area, + nsGkAtoms::link)) { + bool hasAttr = content->HasAttr(kNameSpaceID_None, nsGkAtoms::href); if (hasAttr) { linkContent = content; - nsCOMPtr anchor(do_QueryInterface(linkContent)); + RefPtr anchor = HTMLAnchorElement::FromContent(linkContent); if (anchor) { anchor->GetHref(aHRef); } else { - nsCOMPtr area(do_QueryInterface(linkContent)); + RefPtr area = HTMLAreaElement::FromContent(linkContent); if (area) { area->GetHref(aHRef); } else { - nsCOMPtr link(do_QueryInterface(linkContent)); + RefPtr 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 anchor( - do_QueryInterface(linkContent)); + RefPtr anchor = HTMLAnchorElement::FromContent(linkContent); if (anchor) { anchor->GetHref(aHRef); } diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index e1c89fb528af..b90428559d20 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -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 anchor(do_QueryInterface(aContent)); + RefPtr anchor = HTMLAnchorElement::FromContent(aContent); if (anchor) { anchor->GetType(typeHint); NS_ConvertUTF16toUTF8 utf8Hint(typeHint); diff --git a/dom/abort/AbortController.cpp b/dom/abort/AbortController.cpp index 3430109a8e39..b0b7ed59faec 100644 --- a/dom/abort/AbortController.cpp +++ b/dom/abort/AbortController.cpp @@ -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::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv) { diff --git a/dom/abort/AbortController.h b/dom/abort/AbortController.h index 05151ded14c6..cf96768b99b6 100644 --- a/dom/abort/AbortController.h +++ b/dom/abort/AbortController.h @@ -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 Constructor(const GlobalObject& aGlobal, ErrorResult& aRv); diff --git a/dom/abort/tests/file_abort_controller.html b/dom/abort/tests/file_abort_controller.html deleted file mode 100644 index a06fa3926597..000000000000 --- a/dom/abort/tests/file_abort_controller.html +++ /dev/null @@ -1,65 +0,0 @@ - diff --git a/dom/abort/tests/file_abort_controller_fetch.html b/dom/abort/tests/file_abort_controller_fetch.html deleted file mode 100644 index ea959fdca83b..000000000000 --- a/dom/abort/tests/file_abort_controller_fetch.html +++ /dev/null @@ -1,72 +0,0 @@ - diff --git a/dom/abort/tests/mochitest.ini b/dom/abort/tests/mochitest.ini index 36e12bae8749..9817a9e9aa10 100644 --- a/dom/abort/tests/mochitest.ini +++ b/dom/abort/tests/mochitest.ini @@ -1,7 +1,5 @@ [DEFAULT] support-files = - file_abort_controller.html - file_abort_controller_fetch.html worker_abort_controller_fetch.js slow.sjs diff --git a/dom/abort/tests/test_abort_controller.html b/dom/abort/tests/test_abort_controller.html index 2230dced357b..398b491ba5a9 100644 --- a/dom/abort/tests/test_abort_controller.html +++ b/dom/abort/tests/test_abort_controller.html @@ -12,27 +12,61 @@ diff --git a/dom/abort/tests/test_abort_controller_fetch.html b/dom/abort/tests/test_abort_controller_fetch.html index 24e005d1cb0c..334f25194d0f 100644 --- a/dom/abort/tests/test_abort_controller_fetch.html +++ b/dom/abort/tests/test_abort_controller_fetch.html @@ -12,28 +12,68 @@ diff --git a/dom/base/DirectionalityUtils.cpp b/dom/base/DirectionalityUtils.cpp index 69f1fecf746c..6df783e1a0cb 100644 --- a/dom/base/DirectionalityUtils.cpp +++ b/dom/base/DirectionalityUtils.cpp @@ -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()); } diff --git a/dom/base/crashtests/1400701.html b/dom/base/crashtests/1400701.html new file mode 100644 index 000000000000..fe1eef5d50f5 --- /dev/null +++ b/dom/base/crashtests/1400701.html @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/dom/base/crashtests/crashtests.list b/dom/base/crashtests/crashtests.list index 93c67d5e73ef..5df309d6b763 100644 --- a/dom/base/crashtests/crashtests.list +++ b/dom/base/crashtests/crashtests.list @@ -224,3 +224,4 @@ load 1383478.html load 1383780.html pref(clipboard.autocopy,true) load 1385272-1.html load 1393806.html +load 1400701.html diff --git a/dom/base/nsContentAreaDragDrop.cpp b/dom/base/nsContentAreaDragDrop.cpp index dcf1d3dde73b..ed7f61db1a50 100644 --- a/dom/base/nsContentAreaDragDrop.cpp +++ b/dom/base/nsContentAreaDragDrop.cpp @@ -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 area; // client-side image map nsCOMPtr image; - nsCOMPtr link; nsCOMPtr 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 linkNode; - if (area) { + RefPtr areaElem = HTMLAreaElement::FromContentOrNull(draggedNode); + if (areaElem) { // use the alt text (or, if missing, the href) as the title - HTMLAreaElement* areaElem = static_cast(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 diff --git a/dom/browser-element/BrowserElementChildPreload.js b/dom/browser-element/BrowserElementChildPreload.js index fc796ea71535..5c24b2b5827c 100644 --- a/dom/browser-element/BrowserElementChildPreload.js +++ b/dom/browser-element/BrowserElementChildPreload.js @@ -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, diff --git a/dom/file/ipc/IPCBlobInputStream.cpp b/dom/file/ipc/IPCBlobInputStream.cpp index 29095c3ee624..24e641f9c977 100644 --- a/dom/file/ipc/IPCBlobInputStream.cpp +++ b/dom/file/ipc/IPCBlobInputStream.cpp @@ -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 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 asyncStream = do_QueryInterface(mRemoteStream); if (!asyncStream || !nonBlocking) { - nsCOMPtr sts = - do_GetService(kStreamTransportServiceCID, &rv); + // Let's make the stream async using the DOMFile thread. + nsCOMPtr pipeIn; + nsCOMPtr pipeOut; + rv = NS_NewPipe2(getter_AddRefs(pipeIn), + getter_AddRefs(pipeOut), + true, true); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } - nsCOMPtr transport; - rv = sts->CreateInputTransport(mRemoteStream, - /* aCloseWhenDone */ true, - getter_AddRefs(transport)); + RefPtr 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 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); diff --git a/dom/file/ipc/IPCBlobInputStreamChild.cpp b/dom/file/ipc/IPCBlobInputStreamChild.cpp index e29a2bc578b9..25e370502af9 100644 --- a/dom/file/ipc/IPCBlobInputStreamChild.cpp +++ b/dom/file/ipc/IPCBlobInputStreamChild.cpp @@ -187,6 +187,8 @@ IPCBlobInputStreamChild::ActorDestroy(IProtocol::ActorDestroyReason aReason) // thread. RefPtr thread = IPCBlobInputStreamThread::GetOrCreate(); + MOZ_ASSERT(thread, "We cannot continue without DOMFile thread."); + ResetManager(); thread->MigrateActor(this); return; diff --git a/dom/file/ipc/IPCBlobInputStreamThread.cpp b/dom/file/ipc/IPCBlobInputStreamThread.cpp index f405913988a1..29e9d9fa662e 100644 --- a/dom/file/ipc/IPCBlobInputStreamThread.cpp +++ b/dom/file/ipc/IPCBlobInputStreamThread.cpp @@ -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 = new ThreadInitializeRunnable(); - SystemGroup::Dispatch(TaskCategory::Other, runnable.forget()); - return; - } - - nsCOMPtr 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 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 = new ThreadInitializeRunnable(); + SystemGroup::Dispatch(TaskCategory::Other, runnable.forget()); + return true; + } + + InitializeOnMainThread(); + return true; +} + +void +IPCBlobInputStreamThread::InitializeOnMainThread() +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsCOMPtr 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 aRunnable, + uint32_t aFlags) +{ + nsCOMPtr 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 runnable(aRunnable); + return Dispatch(runnable.forget(), aFlags); +} + +NS_IMETHODIMP +IPCBlobInputStreamThread::DelayedDispatch(already_AddRefed, uint32_t) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + } // dom namespace } // mozilla namespace diff --git a/dom/file/ipc/IPCBlobInputStreamThread.h b/dom/file/ipc/IPCBlobInputStreamThread.h index 241fd8647972..1845aa220a3c 100644 --- a/dom/file/ipc/IPCBlobInputStreamThread.h +++ b/dom/file/ipc/IPCBlobInputStreamThread.h @@ -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; diff --git a/dom/html/HTMLAnchorElement.cpp b/dom/html/HTMLAnchorElement.cpp index c411ecb7d7da..7b20e2a3ae0e 100644 --- a/dom/html/HTMLAnchorElement.cpp +++ b/dom/html/HTMLAnchorElement.cpp @@ -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 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 HTMLAnchorElement::GetHrefURI() const { diff --git a/dom/html/HTMLAnchorElement.h b/dom/html/HTMLAnchorElement.h index b6af1180c14a..e26bb14563e3 100644 --- a/dom/html/HTMLAnchorElement.h +++ b/dom/html/HTMLAnchorElement.h @@ -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 { diff --git a/dom/html/HTMLAreaElement.h b/dom/html/HTMLAreaElement.h index 47d1a962d37d..df811112bc2e 100644 --- a/dom/html/HTMLAreaElement.h +++ b/dom/html/HTMLAreaElement.h @@ -42,6 +42,7 @@ public: // nsIDOMHTMLAreaElement NS_DECL_NSIDOMHTMLAREAELEMENT + NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLAreaElement, area); virtual nsresult GetEventTargetParent( EventChainPreVisitor& aVisitor) override; diff --git a/dom/html/HTMLLinkElement.h b/dom/html/HTMLLinkElement.h index 3ee187856812..c8ec652b68d4 100644 --- a/dom/html/HTMLLinkElement.h +++ b/dom/html/HTMLLinkElement.h @@ -35,7 +35,7 @@ public: // nsIDOMHTMLLinkElement NS_DECL_NSIDOMHTMLLINKELEMENT - + NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLLinkElement, link); NS_DECL_ADDSIZEOFEXCLUDINGTHIS void LinkAdded(); diff --git a/dom/interfaces/html/moz.build b/dom/interfaces/html/moz.build index bbbe3b191b3c..f670c33357be 100644 --- a/dom/interfaces/html/moz.build +++ b/dom/interfaces/html/moz.build @@ -8,7 +8,6 @@ with Files("**"): BUG_COMPONENT = ("Core", "DOM") XPIDL_SOURCES += [ - 'nsIDOMHTMLAnchorElement.idl', 'nsIDOMHTMLAreaElement.idl', 'nsIDOMHTMLBaseElement.idl', 'nsIDOMHTMLButtonElement.idl', diff --git a/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl b/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl deleted file mode 100644 index 8a38cdf95108..000000000000 --- a/dom/interfaces/html/nsIDOMHTMLAnchorElement.idl +++ /dev/null @@ -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(); -}; diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index d84976072367..80ddeb22ee68 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -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); diff --git a/dom/ipc/remote-test.js b/dom/ipc/remote-test.js index dd21415cd740..58e2e74b2b95 100644 --- a/dom/ipc/remote-test.js +++ b/dom/ipc/remote-test.js @@ -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). diff --git a/dom/media/tests/mochitest/mochitest.ini b/dom/media/tests/mochitest/mochitest.ini index c207ad578668..420832b85ea1 100644 --- a/dom/media/tests/mochitest/mochitest.ini +++ b/dom/media/tests/mochitest/mochitest.ini @@ -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] diff --git a/dom/svg/crashtests/1402798.html b/dom/svg/crashtests/1402798.html new file mode 100644 index 000000000000..43d7a77e868b --- /dev/null +++ b/dom/svg/crashtests/1402798.html @@ -0,0 +1,11 @@ + + + + +aa diff --git a/dom/svg/crashtests/crashtests.list b/dom/svg/crashtests/crashtests.list index fc2f7c8f68aa..8e20e9e37e85 100644 --- a/dom/svg/crashtests/crashtests.list +++ b/dom/svg/crashtests/crashtests.list @@ -93,3 +93,4 @@ load 1329093-2.html load 1347617-1.svg load 1347617-2.svg load 1347617-3.svg +load 1402798.html diff --git a/dom/tests/mochitest/fetch/test_fetch_observer.html b/dom/tests/mochitest/fetch/test_fetch_observer.html index 7475e06901f2..2b6c0362d264 100644 --- a/dom/tests/mochitest/fetch/test_fetch_observer.html +++ b/dom/tests/mochitest/fetch/test_fetch_observer.html @@ -12,9 +12,7 @@