Bug 1441935 - Modifications on top of the generated MozBrowser Custom Element r=mconley

In order to make the history easier to navigate, this changeset includes the
modifications required to make <xul:browser> actually work as a Custom Element,
and switches the app to use it instead of the XBL browser.

Differential Revision: https://phabricator.services.mozilla.com/D14911

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Brian Grinstead 2019-01-10 01:45:43 +00:00
parent 5b6fac1c1c
commit f6c12a437b
15 changed files with 161 additions and 137 deletions

View File

@ -346,7 +346,7 @@ var FullZoom = {
// The browser is sometimes half-destroyed because this method is called
// by content pref service callbacks, which themselves can be called at any
// time, even after browsers are closed.
if (!aBrowser.parentNode || aBrowser.isSyntheticDocument) {
if (!aBrowser.mInitialized || aBrowser.isSyntheticDocument) {
this._executeSoon(aCallback);
return;
}
@ -434,7 +434,7 @@ var FullZoom = {
// hasn't been received yet. In that case, the browser is unusable, it
// has no properties, so return false. Check for this case by getting a
// property, say, docShell.
return map.get(browser) === this.token && browser.parentNode;
return map.get(browser) === this.token && browser.mInitialized;
},
};
},

View File

@ -113,7 +113,7 @@ window._gBrowser = {
/**
* `_createLazyBrowser` will define properties on the unbound lazy browser
* which correspond to properties defined in XBL which will be bound to
* which correspond to properties defined in MozBrowser which will be bound to
* the browser when it is inserted into the document. If any of these
* properties are accessed by consumers, `_insertBrowser` is called and
* the browser is inserted to ensure that things don't break. This list
@ -3093,14 +3093,14 @@ window._gBrowser = {
if (aTab.linkedPanel) {
this._outerWindowIDBrowserMap.delete(browser.outerWindowID);
// Because of the way XBL works (fields just set JS
// properties on the element) and the code we have in place
// Because of the fact that we are setting JS properties on
// the browser elements, and we have code in place
// to preserve the JS objects for any elements that have
// JS properties set on them, the browser element won't be
// destroyed until the document goes away. So we force a
// cleanup ourselves.
// This has to happen before we remove the child so that the
// XBL implementation of nsIObserver still works.
// This has to happen before we remove the child since functions
// like `getBrowserContainer` expect the browser to be parented.
browser.destroy();
}

View File

@ -40,7 +40,7 @@ function swapToInnerBrowser({ tab, containerURL, getInnerBrowser }) {
// Dispatch a custom event each time the _viewport content_ is swapped from one browser
// to another. DevTools server code uses this to follow the content if there is an
// active DevTools connection. While browser.xml does dispatch it's own SwapDocShells
// active DevTools connection. While browser.js does dispatch it's own SwapDocShells
// event, this one is easier for DevTools to follow because it's only emitted once per
// transition, instead of twice like SwapDocShells.
const dispatchDevToolsBrowserSwap = (from, to) => {
@ -421,7 +421,7 @@ function addXULBrowserDecorations(browser) {
}
// It's not necessary for these to actually do anything. These properties are
// swapped between browsers in browser.xml's `swapDocShells`, and then their
// swapped between browsers in browser.js's `swapDocShells`, and then their
// `swapBrowser` methods are called, so we define them here for that to work
// without errors. During the swap process above, these will move from the
// the new inner browser to the original tab's browser (step 4) and then to

View File

@ -19,7 +19,7 @@ function debug(msg) {
}
/**
* Properties swapped between browsers by browser.xml's `swapDocShells`.
* Properties swapped between browsers by browser.js's `swapDocShells`.
*/
const SWAPPED_BROWSER_STATE = [
"_remoteFinder",
@ -64,8 +64,8 @@ const PROPERTIES_FROM_BROWSER_WINDOW = [
*
* The inner <iframe mozbrowser> element is _just_ the page content. It is not
* enough to to replace <xul:browser> on its own. <xul:browser> comes along
* with lots of associated functionality via XBL binding defined for such
* elements in browser.xml, and the Firefox UI depends on these various things
* with lots of associated functionality via a Custom Element defined for such
* elements in browser.js, and the Firefox UI depends on these various things
* to make the UI function.
*
* By mapping various methods, properties, and messages from the outer browser
@ -103,9 +103,9 @@ function tunnelToInnerBrowser(outer, inner) {
// Various browser methods access the `frameLoader` property, including:
// * `saveBrowser` from contentAreaUtils.js
// * `docShellIsActive` from browser.xml
// * `hasContentOpener` from browser.xml
// * `preserveLayers` from browser.xml
// * `docShellIsActive` from browser.js
// * `hasContentOpener` from browser.js
// * `preserveLayers` from browser.js
// * `receiveMessage` from SessionStore.jsm
// In general, these methods are interested in the `frameLoader` for the content,
// so we redirect them to the inner browser's `frameLoader`.
@ -153,12 +153,12 @@ function tunnelToInnerBrowser(outer, inner) {
// which we can use to route messages of interest to the inner browser instead.
// Note: The _actual_ messageManager accessible from
// `browser.frameLoader.messageManager` is not overridable and is left unchanged.
// Only the XBL getter `browser.messageManager` is overridden. Browser UI code
// always uses this getter instead of `browser.frameLoader.messageManager` directly,
// Only the Custom Element getter `browser.messageManager` is overridden. This
// getter is always used instead of `browser.frameLoader.messageManager` directly,
// so this has the effect of overriding the message manager for browser UI code.
mmTunnel = new MessageManagerTunnel(outer, inner);
// Clear out any cached state that references the XBL binding's non-remote state,
// Clear out any cached state that references the Custom Element's non-remote state,
// such as form fill controllers. Otherwise they will remain in place and leak the
// outer docshell.
outer.destroy();
@ -193,9 +193,9 @@ function tunnelToInnerBrowser(outer, inner) {
outer._remoteWebNavigation = webNavigation;
outer._remoteWebNavigationImpl = webNavigation;
// Now that we've flipped to the remote browser XBL binding, add `progressListener`
// Now that we've flipped to the remote browser mode, add `progressListener`
// onto the remote version of `webProgress`. Normally tabbrowser.xml does this step
// when it creates a new browser, etc. Since we manually changed the XBL binding
// when it creates a new browser, etc. Since we manually changed the mode
// above, it caused a fresh webProgress object to be created which does not have any
// listeners added. So, we get the listener that gBrowser is using for the tab and
// reattach it here.
@ -305,7 +305,7 @@ function tunnelToInnerBrowser(outer, inner) {
// Remove the progress listener we added manually.
outer.webProgress.removeProgressListener(filteredProgressListener);
// Reset the XBL binding back to the original state.
// Reset the Custom Element back to the original state.
outer.destroy();
// Reset @remote since this is now back to a regular, non-remote browser
@ -388,7 +388,7 @@ MessageManagerTunnel.prototype = {
],
OUTER_TO_INNER_MESSAGES: [
// Messages sent from remote-browser.xml
// Messages sent from browser.js
"Browser:PurgeSessionHistory",
"InPermitUnload",
"PermitUnload",
@ -422,7 +422,7 @@ MessageManagerTunnel.prototype = {
"Content:SecurityChange",
"Content:StateChange",
"Content:StatusChange",
// Messages sent to remote-browser.xml
// Messages sent to browser.js
"DOMTitleChanged",
"ImageDocumentLoaded",
"Forms:ShowDropDown",
@ -440,7 +440,7 @@ MessageManagerTunnel.prototype = {
],
OUTER_TO_INNER_MESSAGE_PREFIXES: [
// Messages sent from browser.xml
// Messages sent from browser.js
"Autoscroll:",
// Messages sent from nsContextMenu.js
"ContextMenu:",
@ -463,7 +463,7 @@ MessageManagerTunnel.prototype = {
],
INNER_TO_OUTER_MESSAGE_PREFIXES: [
// Messages sent to browser.xml
// Messages sent to browser.js
"Autoscroll:",
// Messages sent to nsContextMenu.js
"ContextMenu:",

View File

@ -86,7 +86,7 @@ function matchRequest(channel, filters) {
return true;
}
} catch (e) {
// outerWindowID getter from browser.xml (non-remote <xul:browser>) may
// outerWindowID getter from browser.js (non-remote <xul:browser>) may
// throw when closing a tab while resources are still loading.
}
}

View File

@ -31,7 +31,11 @@
Services.obs.addObserver(crashObserver, 'ipc:content-shutdown');
BrowserTestUtils.crashBrowser(document.getElementById('thebrowser'), true, false);
// Allow the browser to get connected before using the messageManager to cause
// a crash:
addEventListener("DOMContentLoaded", () => {
BrowserTestUtils.crashBrowser(document.getElementById('thebrowser'), true, false);
});
]]></script>
</window>

View File

@ -76,7 +76,7 @@ bool AutoscrollAnimation::DoSample(FrameMetrics& aFrameMetrics,
}
void AutoscrollAnimation::Cancel(CancelAnimationFlags aFlags) {
// The cancellation was initiated by browser.xml, so there's no need to
// The cancellation was initiated by browser.js, so there's no need to
// notify it.
if (aFlags & TriggeredExternally) {
return;

View File

@ -4,7 +4,7 @@
#filter substitution
// For browser.xml binding
// For browser.js element
//
// cacheRatio* is a ratio that determines the amount of pixels to cache. The
// ratio is multiplied by the viewport width or height to get the displayport's

View File

@ -5378,7 +5378,7 @@ var XPInstallObserver = {
};
/**
* Handler for blocked popups, triggered by DOMUpdateBlockedPopups events in browser.xml
* Handler for blocked popups, triggered by DOMUpdateBlockedPopups events in browser.js
*/
var PopupBlockerObserver = {
onUpdateBlockedPopups: function onUpdateBlockedPopups(aEvent) {

View File

@ -13,7 +13,8 @@ Services.obs.addObserver({
observe(doc) {
if (doc.nodePrincipal.isSystemPrincipal && (
doc.contentType == "application/vnd.mozilla.xul+xml" ||
doc.contentType == "application/xhtml+xml"
doc.contentType == "application/xhtml+xml" ||
doc.contentType == "text/html"
)) {
Services.scriptloader.loadSubScript(
"chrome://global/content/customElements.js", doc.ownerGlobal);

View File

@ -290,6 +290,10 @@ window.MozElementMixin = MozElementMixin;
window.MozXULElement = MozXULElement;
window.MozElements = MozElements;
customElements.setElementCreationCallback("browser", () => {
Services.scriptloader.loadSubScript("chrome://global/content/elements/browser-custom-element.js", window);
});
// For now, don't load any elements in the extension dummy document.
// We will want to load <browser> when that's migrated (bug 1441935).
const isDummyDocument = document.documentURI == "chrome://extensions/content/dummy.xul";

View File

@ -90,6 +90,7 @@ toolkit.jar:
content/global/bindings/tree.xml (widgets/tree.xml)
content/global/bindings/videocontrols.xml (widgets/videocontrols.xml)
* content/global/bindings/wizard.xml (widgets/wizard.xml)
content/global/elements/browser-custom-element.js (widgets/browser-custom-element.js)
content/global/elements/datetimebox.js (widgets/datetimebox.js)
content/global/elements/findbar.js (widgets/findbar.js)
content/global/elements/editor.js (widgets/editor.js)

View File

@ -1,8 +1,6 @@
/* 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/. */
/* eslint-disable */
* 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";
@ -10,17 +8,50 @@
// leaking to window scope.
{
class MozBrowser extends MozXULElement {
const elementsToDestroyOnUnload = new Set();
window.addEventListener("unload", () => {
for (let element of elementsToDestroyOnUnload.values()) {
element.destroy();
}
elementsToDestroyOnUnload.clear();
}, { mozSystemGroup: true, once: true });
class MozBrowser extends MozElementMixin(XULFrameElement) {
static get observedAttributes() {
return ["remote"];
}
attributeChangedCallback(name, oldValue, newValue) {
// When we have already been set up via connectedCallback and the
// and the [remote] value changes, we need to start over. This used
// to happen due to a XBL binding change.
if (name === "remote" && oldValue != newValue && this.isConnectedAndReady) {
this.destroy();
this.construct();
}
}
constructor() {
super();
this.onPageHide = this.onPageHide.bind(this);
/**
* These are managed by the tabbrowser:
*/
this.droppedLinkHandler = null;
this.mIconURL = null;
this.lastURI = null;
this.addEventListener("keypress", (event) => {
if (event.keyCode != KeyEvent.DOM_VK_F7) {
return;
}
if (event.defaultPrevented || !event.isTrusted)
if (event.defaultPrevented || !event.isTrusted) {
return;
}
const kPrefShortcutEnabled = "accessibility.browsewithcaret_shortcut.enabled";
const kPrefWarnOnEnable = "accessibility.warn_on_browsewithcaret";
@ -35,8 +66,7 @@ class MozBrowser extends MozXULElement {
var warn = this.mPrefs.getBoolPref(kPrefWarnOnEnable, true);
if (warn && !browseWithCaretOn) {
var checkValue = { value: false };
var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Ci.nsIPromptService);
var promptService = Services.prompt;
var buttonPressed = promptService.confirmEx(window,
this.mStrBundle.GetStringFromName("browsewithcaret.checkWindowTitle"),
@ -67,8 +97,9 @@ class MozBrowser extends MozXULElement {
}, { mozSystemGroup: true });
this.addEventListener("dragover", (event) => {
if (!this.droppedLinkHandler || event.defaultPrevented)
if (!this.droppedLinkHandler || event.defaultPrevented) {
return;
}
// For drags that appear to be internal text (for example, tab drags),
// set the dropEffect to 'none'. This prevents the drop even if some
@ -85,8 +116,7 @@ class MozBrowser extends MozXULElement {
if (this.isRemoteBrowser)
return;
let linkHandler = Cc["@mozilla.org/content/dropped-link-handler;1"].
getService(Ci.nsIDroppedLinkHandler);
let linkHandler = Services.droppedLinkHandler;
if (linkHandler.canDropLink(event, false))
event.preventDefault();
}, { mozSystemGroup: true });
@ -94,11 +124,11 @@ class MozBrowser extends MozXULElement {
this.addEventListener("drop", (event) => {
// No need to handle "drop" in e10s, since nsDocShellTreeOwner.cpp in the child process
// handles that case using "@mozilla.org/content/dropped-link-handler;1" service.
if (!this.droppedLinkHandler || event.defaultPrevented || this.isRemoteBrowser)
if (!this.droppedLinkHandler || event.defaultPrevented || this.isRemoteBrowser) {
return;
}
let linkHandler = Cc["@mozilla.org/content/dropped-link-handler;1"].
getService(Ci.nsIDroppedLinkHandler);
let linkHandler = Services.droppedLinkHandler;
try {
// Pass true to prevent the dropping of javascript:/data: URIs
var links = linkHandler.dropLinks(event, true);
@ -123,14 +153,39 @@ class MozBrowser extends MozXULElement {
}
connectedCallback() {
if (this.delayConnectedCallback()) {
return;
resetFields() {
if (this.observer) {
try {
Services.obs.removeObserver(this.observer, "browser:purge-session-history");
} catch (ex) {
// It's not clear why this sometimes throws an exception.
}
this.observer = null;
}
this.textContent = "";
this.appendChild(MozXULElement.parseXULToFragment(`
<children></children>
`));
let browser = this;
this.observer = {
observe(aSubject, aTopic, aState) {
if (aTopic == "browser:purge-session-history") {
browser.purgeSessionHistory();
} else if (aTopic == "apz:cancel-autoscroll") {
if (aState == browser._autoScrollScrollId) {
// Set this._autoScrollScrollId to null, so in stopScroll() we
// don't call stopApzAutoscroll() (since it's APZ that
// initiated the stopping).
browser._autoScrollScrollId = null;
browser._autoScrollPresShellId = null;
browser._autoScrollPopup.hidePopup();
}
}
},
QueryInterface: ChromeUtils.generateQI([
Ci.nsIObserver,
Ci.nsISupportsWeakReference,
]),
};
this._documentURI = null;
@ -187,7 +242,7 @@ class MozBrowser extends MozXULElement {
this._isSyntheticDocument = false;
this.mPrefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
this.mPrefs = Services.prefs;
this._mStrBundle = null;
@ -223,17 +278,6 @@ class MozBrowser extends MozXULElement {
this._userTypedValue = null;
this.droppedLinkHandler = null;
this.mIconURL = null;
/**
* This is managed by the tabbrowser
*/
this.lastURI = null;
this.mDestroyed = false;
this._AUTOSCROLL_SNAP = 10;
this._scrolling = false;
@ -254,9 +298,21 @@ class MozBrowser extends MozXULElement {
this._autoScrollPresShellId = null;
this._permitUnloadId = 0;
}
connectedCallback() {
// We typically use this to avoid running JS that triggers a layout during parse
// (see comment on the delayConnectedCallback implementation). In this case, we
// are using it to avoid a leak - see https://bugzilla.mozilla.org/show_bug.cgi?id=1441935#c20.
if (this.delayConnectedCallback()) {
return;
}
this.construct();
}
disconnectedCallback() {
this.destroy();
}
get autoscrollEnabled() {
@ -312,11 +368,11 @@ class MozBrowser extends MozXULElement {
}
get autoCompletePopup() {
return document.getElementById(this.getAttribute('autocompletepopup'))
return document.getElementById(this.getAttribute("autocompletepopup"));
}
get dateTimePicker() {
return document.getElementById(this.getAttribute('datetimepicker'))
return document.getElementById(this.getAttribute("datetimepicker"));
}
set docShellIsActive(val) {
@ -385,7 +441,7 @@ class MozBrowser extends MozXULElement {
}
get isRemoteBrowser() {
return (this.getAttribute('remote') == 'true');
return (this.getAttribute("remote") == "true");
}
get remoteType() {
@ -490,11 +546,11 @@ class MozBrowser extends MozXULElement {
* Note that this overrides webNavigation on XULFrameElement, and duplicates the return value for the non-remote case
*/
get webNavigation() {
return this.isRemoteBrowser ? this._remoteWebNavigation : this.docShell.QueryInterface(Components.interfaces.nsIWebNavigation);
return this.isRemoteBrowser ? this._remoteWebNavigation : this.docShell && this.docShell.QueryInterface(Ci.nsIWebNavigation);
}
get webProgress() {
return this.isRemoteBrowser ? this._remoteWebProgress : this.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebProgress);
return this.isRemoteBrowser ? this._remoteWebProgress : this.docShell && this.docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebProgress);
}
get sessionHistory() {
@ -544,13 +600,15 @@ class MozBrowser extends MozXULElement {
}
set showWindowResizer(val) {
if (val) this.setAttribute('showresizer', 'true');
else this.removeAttribute('showresizer');
return val;
if (val) {
this.setAttribute("showresizer", "true");
} else {
this.removeAttribute("showresizer");
}
}
get showWindowResizer() {
return this.getAttribute('showresizer') == 'true';
return this.getAttribute("showresizer") == "true";
}
set fullZoom(val) {
@ -622,8 +680,7 @@ class MozBrowser extends MozXULElement {
if (!this._mStrBundle) {
// need to create string bundle manually instead of using <xul:stringbundle/>
// see bug 63370 for details
this._mStrBundle = Cc["@mozilla.org/intl/stringbundle;1"]
.getService(Ci.nsIStringBundleService)
this._mStrBundle = Services.strings
.createBundle("chrome://global/locale/browser.properties");
}
return this._mStrBundle;
@ -950,6 +1007,9 @@ class MozBrowser extends MozXULElement {
}
construct() {
elementsToDestroyOnUnload.add(this);
this.resetFields();
this.mInitialized = true;
if (this.isRemoteBrowser) {
/*
* Don't try to send messages from this function. The message manager for
@ -998,7 +1058,7 @@ class MozBrowser extends MozXULElement {
}
if (!this.hasAttribute("disablehistory")) {
Services.obs.addObserver(this, "browser:purge-session-history", true);
Services.obs.addObserver(this.observer, "browser:purge-session-history", true);
}
let rc_js = "resource://gre/modules/RemoteController.js";
@ -1014,9 +1074,7 @@ class MozBrowser extends MozXULElement {
// loader when creating the docShell as long as this xul:browser
// doesn't have the 'disablehistory' attribute set.
if (this.docShell && this.webNavigation.sessionHistory) {
var os = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
os.addObserver(this, "browser:purge-session-history", true);
Services.obs.addObserver(this.observer, "browser:purge-session-history", true);
// enable global history if we weren't told otherwise
if (!this.hasAttribute("disableglobalhistory") && !this.isRemoteBrowser) {
@ -1079,14 +1137,20 @@ class MozBrowser extends MozXULElement {
* we are removed from a tabbrowser. This will be explicitly called by tabbrowser.
*/
destroy() {
elementsToDestroyOnUnload.delete(this);
// Make sure that any open select is closed.
if (this._selectParentHelper) {
let menulist = document.getElementById(this.getAttribute("selectmenulist"));
this._selectParentHelper.hide(menulist, this);
}
if (this.mDestroyed)
this.resetFields();
if (!this.mInitialized)
return;
this.mDestroyed = true;
this.mInitialized = false;
if (this.isRemoteBrowser) {
try {
@ -1095,32 +1159,9 @@ class MozBrowser extends MozXULElement {
// This can fail when this browser element is not attached to a
// BrowserDOMWindow.
}
if (!this.hasAttribute("disablehistory")) {
let Services = ChromeUtils.import("resource://gre/modules/Services.jsm", {}).Services;
try {
Services.obs.removeObserver(this, "browser:purge-session-history");
} catch (ex) {
// It's not clear why this sometimes throws an exception.
}
}
return;
}
if (this.docShell && this.webNavigation.sessionHistory) {
var os = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
try {
os.removeObserver(this, "browser:purge-session-history");
} catch (ex) {
// It's not clear why this sometimes throws an exception.
}
}
this._fastFind = null;
this._webBrowserFind = null;
this.lastURI = null;
if (!this.isRemoteBrowser) {
@ -1164,9 +1205,8 @@ class MozBrowser extends MozXULElement {
// If APZ is handling the autoscroll, it may decide to cancel
// it of its own accord, so register an observer to allow it
// to notify us of that.
var os = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
os.addObserver(this, "apz:cancel-autoscroll", true);
var os = Services.obs;
os.addObserver(this.observer, "apz:cancel-autoscroll", true);
usingApz = tabParent.startApzAutoscroll(
data.screenX, data.screenY,
@ -1225,7 +1265,6 @@ class MozBrowser extends MozXULElement {
}
break;
}
}
return undefined;
}
@ -1312,22 +1351,6 @@ class MozBrowser extends MozXULElement {
}
}
observe(aSubject, aTopic, aState) {
if (aTopic == "browser:purge-session-history") {
this.purgeSessionHistory();
} else if (aTopic == "apz:cancel-autoscroll") {
if (aState == this._autoScrollScrollId) {
// Set this._autoScrollScrollId to null, so in stopScroll() we
// don't call stopApzAutoscroll() (since it's APZ that
// initiated the stopping).
this._autoScrollScrollId = null;
this._autoScrollPresShellId = null;
this._autoScrollPopup.hidePopup();
}
}
}
purgeSessionHistory() {
if (this.isRemoteBrowser) {
try {
@ -1374,10 +1397,8 @@ class MozBrowser extends MozXULElement {
window.removeEventListener("keyup", this, true);
this.messageManager.sendAsyncMessage("Autoscroll:Stop");
var os = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
try {
os.removeObserver(this, "apz:cancel-autoscroll");
Services.obs.removeObserver(this.observer, "apz:cancel-autoscroll");
} catch (ex) {
// It's not clear why this sometimes throws an exception
}
@ -1769,7 +1790,7 @@ class MozBrowser extends MozXULElement {
}
return {
permitUnload: this.docShell.contentViewer.permitUnload(aPermitUnloadFlags),
timedOut: false
timedOut: false,
};
}
@ -1815,12 +1836,9 @@ class MozBrowser extends MozXULElement {
this.docShell.getContentBlockingLog() :
Promise.reject("docshell isn't available");
}
disconnectedCallback() {
this.destroy();
}
}
MozXULElement.implementCustomInterface(MozBrowser, [Ci.nsIObserver, Ci.nsIBrowser]);
MozXULElement.implementCustomInterface(MozBrowser, [Ci.nsIBrowser, Ci.nsIFrameLoaderOwner]);
customElements.define("browser", MozBrowser);
}

View File

@ -172,10 +172,6 @@ iframe {
}
}
browser {
-moz-binding: url("chrome://global/content/bindings/browser.xml#browser");
}
/*********** popup notification ************/
popupnotification {
-moz-binding: url("chrome://global/content/bindings/notification.xml#popup-notification");

View File

@ -107,7 +107,7 @@ var E10SUtils = {
return NOT_REMOTE;
}
// loadURI in browser.xml treats null as about:blank
// loadURI in browser.js treats null as about:blank
if (!aURL) {
aURL = "about:blank";
}