зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1311605 - Support save page for RDM content. r=ochameau
MozReview-Commit-ID: J8d9J2GRkf5 --HG-- extra : rebase_source : 4948d1dc518a85239cd86fbcd73cd1e4d55b76ca
This commit is contained in:
Родитель
14a2b3bc99
Коммит
b158ffd8b6
|
@ -9,6 +9,10 @@ const Services = require("Services");
|
|||
const { Task } = require("devtools/shared/task");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const { BrowserElementWebNavigation } = require("./web-navigation");
|
||||
const { getStack } = require("devtools/shared/platform/stack");
|
||||
|
||||
// A symbol used to hold onto the frame loader from the outer browser while tunneling.
|
||||
const FRAME_LOADER = Symbol("devtools/responsive/frame-loader");
|
||||
|
||||
function debug(msg) {
|
||||
// console.log(msg);
|
||||
|
@ -77,6 +81,34 @@ function tunnelToInnerBrowser(outer, inner) {
|
|||
throw new Error("The inner browser must be remote.");
|
||||
}
|
||||
|
||||
// Various browser methods access the `frameLoader` property, including:
|
||||
// * `saveBrowser` from contentAreaUtils.js
|
||||
// * `docShellIsActive` from remote-browser.xml
|
||||
// * `hasContentOpener` from remote-browser.xml
|
||||
// * `preserveLayers` from remote-browser.xml
|
||||
// * `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`.
|
||||
outer[FRAME_LOADER] = outer.frameLoader;
|
||||
Object.defineProperty(outer, "frameLoader", {
|
||||
get() {
|
||||
let stack = getStack();
|
||||
// One exception is `receiveMessage` from SessionStore.jsm. SessionStore
|
||||
// expects data updates to come in as messages targeted to a <xul:browser>.
|
||||
// In addition, it verifies[1] correctness by checking that the received
|
||||
// message's `targetFrameLoader` property matches the `frameLoader` of the
|
||||
// <xul:browser>. To keep SessionStore functioning as expected, we give it the
|
||||
// outer `frameLoader` as if nothing has changed.
|
||||
// [1]: https://dxr.mozilla.org/mozilla-central/rev/b1b18f25c0ea69d9ee57c4198d577dfcd0129ce1/browser/components/sessionstore/SessionStore.jsm#716
|
||||
if (stack.caller.filename.endsWith("SessionStore.jsm")) {
|
||||
return outer[FRAME_LOADER];
|
||||
}
|
||||
return inner.frameLoader;
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
});
|
||||
|
||||
// The `permanentKey` property on a <xul:browser> is used to index into various maps
|
||||
// held by the session store. When you swap content around with
|
||||
// `_swapBrowserDocShells`, these keys are also swapped so they follow the content.
|
||||
|
@ -152,35 +184,6 @@ function tunnelToInnerBrowser(outer, inner) {
|
|||
outer[property] = inner[property];
|
||||
}
|
||||
|
||||
// Wants to access the content's `frameLoader`, so we'll redirect it to
|
||||
// inner browser.
|
||||
Object.defineProperty(outer, "hasContentOpener", {
|
||||
get() {
|
||||
return inner.frameLoader.tabParent.hasContentOpener;
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
});
|
||||
|
||||
// Wants to access the content's `frameLoader`, so we'll redirect it to
|
||||
// inner browser.
|
||||
Object.defineProperty(outer, "docShellIsActive", {
|
||||
get() {
|
||||
return inner.frameLoader.tabParent.docShellIsActive;
|
||||
},
|
||||
set(value) {
|
||||
inner.frameLoader.tabParent.docShellIsActive = value;
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
});
|
||||
|
||||
// Wants to access the content's `frameLoader`, so we'll redirect it to
|
||||
// inner browser.
|
||||
outer.preserveLayers = value => {
|
||||
inner.frameLoader.tabParent.preserveLayers(value);
|
||||
};
|
||||
|
||||
// Expose `PopupNotifications` on the content's owner global.
|
||||
// This is used by PermissionUI.jsm for permission doorhangers.
|
||||
// Note: This pollutes the responsive.html tool UI's global.
|
||||
|
@ -253,13 +256,6 @@ function tunnelToInnerBrowser(outer, inner) {
|
|||
outer.destroy();
|
||||
outer.style.MozBinding = "";
|
||||
|
||||
// Reset overridden XBL properties and methods. Deleting the override
|
||||
// means it will fallback to the original XBL binding definitions which
|
||||
// are on the prototype.
|
||||
delete outer.hasContentOpener;
|
||||
delete outer.docShellIsActive;
|
||||
delete outer.preserveLayers;
|
||||
|
||||
// Reset @remote since this is now back to a regular, non-remote browser
|
||||
outer.setAttribute("remote", "false");
|
||||
|
||||
|
@ -273,6 +269,12 @@ function tunnelToInnerBrowser(outer, inner) {
|
|||
mmTunnel.destroy();
|
||||
mmTunnel = null;
|
||||
|
||||
// Reset overridden XBL properties and methods. Deleting the override
|
||||
// means it will fallback to the original XBL binding definitions which
|
||||
// are on the prototype.
|
||||
delete outer.frameLoader;
|
||||
delete outer[FRAME_LOADER];
|
||||
|
||||
// Invalidate outer's permanentKey so that SessionStore stops associating
|
||||
// things that happen to the outer browser with the content inside in the
|
||||
// inner browser.
|
||||
|
@ -296,7 +298,7 @@ function copyPermanentKey(outer, inner) {
|
|||
// no direct mechanism to do so. As a workaround, we wait until the one errant message
|
||||
// has gone by, and then we copy the permanentKey after that, since the permanentKey is
|
||||
// what SessionStore uses to identify each browser.
|
||||
let outerMM = outer.frameLoader.messageManager;
|
||||
let outerMM = outer[FRAME_LOADER].messageManager;
|
||||
let onHistoryEntry = message => {
|
||||
let history = message.data.data.history;
|
||||
if (!history || !history.entries) {
|
||||
|
@ -427,17 +429,17 @@ MessageManagerTunnel.prototype = {
|
|||
],
|
||||
|
||||
get outerParentMM() {
|
||||
if (!this.outer.frameLoader) {
|
||||
if (!this.outer[FRAME_LOADER]) {
|
||||
return null;
|
||||
}
|
||||
return this.outer.frameLoader.messageManager;
|
||||
return this.outer[FRAME_LOADER].messageManager;
|
||||
},
|
||||
|
||||
get outerChildMM() {
|
||||
// This is only possible because we require the outer browser to be
|
||||
// non-remote, so we're able to reach into its window and use the child
|
||||
// side message manager there.
|
||||
let docShell = this.outer.frameLoader.docShell;
|
||||
let docShell = this.outer[FRAME_LOADER].docShell;
|
||||
return docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
},
|
||||
|
|
Загрузка…
Ссылка в новой задаче