зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1648149 - Move GeckoViewContent to Actor. r=snorp
Differential Revision: https://phabricator.services.mozilla.com/D84040
This commit is contained in:
Родитель
10bb01cfc6
Коммит
4c8aa34ba2
|
@ -20,6 +20,7 @@ skip-if = toolkit == 'android' || e10s || os == 'mac' # mac(select form control
|
|||
[test_bug477531.html]
|
||||
[test_bug477700.html]
|
||||
[test_bug478219.xhtml]
|
||||
skip-if = toolkit == 'android' # Bug 1658807
|
||||
[test_bug534785.html]
|
||||
[test_bug542914.html]
|
||||
[test_bug549170.html]
|
||||
|
|
|
@ -10,14 +10,81 @@ var { XPCOMUtils } = ChromeUtils.import(
|
|||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// This needs to match ScreenLength.java
|
||||
const SCREEN_LENGTH_TYPE_PIXEL = 0;
|
||||
const SCREEN_LENGTH_TYPE_VISUAL_VIEWPORT_WIDTH = 1;
|
||||
const SCREEN_LENGTH_TYPE_VISUAL_VIEWPORT_HEIGHT = 2;
|
||||
const SCREEN_LENGTH_DOCUMENT_WIDTH = 3;
|
||||
const SCREEN_LENGTH_DOCUMENT_HEIGHT = 4;
|
||||
|
||||
// This need to match PanZoomController.java
|
||||
const SCROLL_BEHAVIOR_SMOOTH = 0;
|
||||
const SCROLL_BEHAVIOR_AUTO = 1;
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
SessionHistory: "resource://gre/modules/sessionstore/SessionHistory.jsm",
|
||||
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
|
||||
ManifestObtainer: "resource://gre/modules/ManifestObtainer.jsm",
|
||||
PrivacyFilter: "resource://gre/modules/sessionstore/PrivacyFilter.jsm",
|
||||
SessionHistory: "resource://gre/modules/sessionstore/SessionHistory.jsm",
|
||||
Utils: "resource://gre/modules/sessionstore/Utils.jsm",
|
||||
});
|
||||
|
||||
var EXPORTED_SYMBOLS = ["GeckoViewContentChild"];
|
||||
|
||||
class GeckoViewContentChild extends GeckoViewActorChild {
|
||||
toPixels(aLength, aType) {
|
||||
const { contentWindow } = this;
|
||||
if (aType === SCREEN_LENGTH_TYPE_PIXEL) {
|
||||
return aLength;
|
||||
} else if (aType === SCREEN_LENGTH_TYPE_VISUAL_VIEWPORT_WIDTH) {
|
||||
return aLength * contentWindow.visualViewport.width;
|
||||
} else if (aType === SCREEN_LENGTH_TYPE_VISUAL_VIEWPORT_HEIGHT) {
|
||||
return aLength * contentWindow.visualViewport.height;
|
||||
} else if (aType === SCREEN_LENGTH_DOCUMENT_WIDTH) {
|
||||
return aLength * contentWindow.document.body.scrollWidth;
|
||||
} else if (aType === SCREEN_LENGTH_DOCUMENT_HEIGHT) {
|
||||
return aLength * contentWindow.document.body.scrollHeight;
|
||||
}
|
||||
|
||||
return aLength;
|
||||
}
|
||||
|
||||
toScrollBehavior(aBehavior) {
|
||||
const { contentWindow } = this;
|
||||
if (!contentWindow) {
|
||||
return 0;
|
||||
}
|
||||
const { windowUtils } = contentWindow;
|
||||
if (aBehavior === SCROLL_BEHAVIOR_SMOOTH) {
|
||||
return windowUtils.SCROLL_MODE_SMOOTH;
|
||||
} else if (aBehavior === SCROLL_BEHAVIOR_AUTO) {
|
||||
return windowUtils.SCROLL_MODE_INSTANT;
|
||||
}
|
||||
return windowUtils.SCROLL_MODE_SMOOTH;
|
||||
}
|
||||
|
||||
notifyParentOfViewportFit() {
|
||||
if (this.triggerViewportFitChange) {
|
||||
this.contentWindow.cancelIdleCallback(this.triggerViewportFitChange);
|
||||
}
|
||||
this.triggerViewportFitChange = this.contentWindow.requestIdleCallback(
|
||||
() => {
|
||||
this.triggerViewportFitChange = null;
|
||||
const viewportFit = this.contentWindow.windowUtils.getViewportFitInfo();
|
||||
if (this.lastViewportFit === viewportFit) {
|
||||
return;
|
||||
}
|
||||
this.lastViewportFit = viewportFit;
|
||||
this.eventDispatcher.sendRequest({
|
||||
type: "GeckoView:DOMMetaViewportFit",
|
||||
viewportfit: viewportFit,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
collectSessionState() {
|
||||
const { docShell, contentWindow } = this;
|
||||
const history = SessionHistory.collect(docShell);
|
||||
|
@ -49,14 +116,371 @@ class GeckoViewContentChild extends GeckoViewActorChild {
|
|||
return { history, formdata, scrolldata };
|
||||
}
|
||||
|
||||
loadEntry(loadOptions, history) {
|
||||
if (!loadOptions) {
|
||||
history.QueryInterface(Ci.nsISHistory).reloadCurrentEntry();
|
||||
return;
|
||||
}
|
||||
|
||||
const webNavigation = this.docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
|
||||
const {
|
||||
referrerInfo,
|
||||
triggeringPrincipal,
|
||||
uri,
|
||||
flags,
|
||||
csp,
|
||||
headers,
|
||||
} = loadOptions;
|
||||
|
||||
webNavigation.loadURI(uri, {
|
||||
triggeringPrincipal: E10SUtils.deserializePrincipal(triggeringPrincipal),
|
||||
referrerInfo: E10SUtils.deserializeReferrerInfo(referrerInfo),
|
||||
loadFlags: flags,
|
||||
csp: E10SUtils.deserializeCSP(csp),
|
||||
headers,
|
||||
});
|
||||
}
|
||||
|
||||
receiveMessage(message) {
|
||||
const { name } = message;
|
||||
debug`receiveMessage: ${name}`;
|
||||
|
||||
switch (name) {
|
||||
case "GeckoView:DOMFullscreenEntered":
|
||||
this.contentWindow?.windowUtils.handleFullscreenRequests();
|
||||
break;
|
||||
case "GeckoView:DOMFullscreenExited":
|
||||
this.contentWindow?.windowUtils.exitFullscreen();
|
||||
break;
|
||||
case "GeckoView:ZoomToInput": {
|
||||
const { contentWindow } = this;
|
||||
const dwu = contentWindow.windowUtils;
|
||||
|
||||
const zoomToFocusedInput = function() {
|
||||
if (!dwu.flushApzRepaints()) {
|
||||
dwu.zoomToFocusedInput();
|
||||
return;
|
||||
}
|
||||
Services.obs.addObserver(function apzFlushDone() {
|
||||
Services.obs.removeObserver(apzFlushDone, "apz-repaints-flushed");
|
||||
dwu.zoomToFocusedInput();
|
||||
}, "apz-repaints-flushed");
|
||||
};
|
||||
|
||||
const { force } = message.data;
|
||||
|
||||
let gotResize = false;
|
||||
const onResize = function() {
|
||||
gotResize = true;
|
||||
if (dwu.isMozAfterPaintPending) {
|
||||
contentWindow.addEventListener(
|
||||
"MozAfterPaint",
|
||||
() => zoomToFocusedInput(),
|
||||
{ capture: true, once: true }
|
||||
);
|
||||
} else {
|
||||
zoomToFocusedInput();
|
||||
}
|
||||
};
|
||||
|
||||
contentWindow.addEventListener("resize", onResize, { capture: true });
|
||||
|
||||
// When the keyboard is displayed, we can get one resize event,
|
||||
// multiple resize events, or none at all. Try to handle all these
|
||||
// cases by allowing resizing within a set interval, and still zoom to
|
||||
// input if there is no resize event at the end of the interval.
|
||||
contentWindow.setTimeout(() => {
|
||||
contentWindow.removeEventListener("resize", onResize, {
|
||||
capture: true,
|
||||
});
|
||||
if (!gotResize && force) {
|
||||
onResize();
|
||||
}
|
||||
}, 500);
|
||||
break;
|
||||
}
|
||||
case "GeckoView:RestoreState": {
|
||||
const { contentWindow, docShell } = this;
|
||||
const { history, formdata, scrolldata, loadOptions } = message.data;
|
||||
|
||||
if (history) {
|
||||
const restoredHistory = SessionHistory.restore(docShell, history);
|
||||
|
||||
contentWindow.addEventListener(
|
||||
"load",
|
||||
_ => {
|
||||
if (formdata) {
|
||||
Utils.restoreFrameTreeData(
|
||||
contentWindow,
|
||||
formdata,
|
||||
(frame, data) => {
|
||||
// restore() will return false, and thus abort restoration for the
|
||||
// current |frame| and its descendants, if |data.url| is given but
|
||||
// doesn't match the loaded document's URL.
|
||||
return SessionStoreUtils.restoreFormData(
|
||||
frame.document,
|
||||
data
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
{ capture: true, mozSystemGroup: true, once: true }
|
||||
);
|
||||
|
||||
const scrollRestore = _ => {
|
||||
if (contentWindow.location != "about:blank") {
|
||||
if (scrolldata) {
|
||||
Utils.restoreFrameTreeData(
|
||||
contentWindow,
|
||||
scrolldata,
|
||||
(frame, data) => {
|
||||
if (data.scroll) {
|
||||
SessionStoreUtils.restoreScrollPosition(frame, data);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
contentWindow.removeEventListener("pageshow", scrollRestore, {
|
||||
capture: true,
|
||||
mozSystemGroup: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
contentWindow.addEventListener("pageshow", scrollRestore, {
|
||||
capture: true,
|
||||
mozSystemGroup: true,
|
||||
});
|
||||
|
||||
const progressFilter = Cc[
|
||||
"@mozilla.org/appshell/component/browser-status-filter;1"
|
||||
].createInstance(Ci.nsIWebProgress);
|
||||
const flags = Ci.nsIWebProgress.NOTIFY_LOCATION;
|
||||
|
||||
const progressListener = {
|
||||
QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener"]),
|
||||
|
||||
onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags) {
|
||||
debug`onLocationChange`;
|
||||
|
||||
if (
|
||||
scrolldata &&
|
||||
scrolldata.zoom &&
|
||||
scrolldata.zoom.displaySize
|
||||
) {
|
||||
const utils = contentWindow.windowUtils;
|
||||
// Restore zoom level.
|
||||
utils.setRestoreResolution(
|
||||
scrolldata.zoom.resolution,
|
||||
scrolldata.zoom.displaySize.width,
|
||||
scrolldata.zoom.displaySize.height
|
||||
);
|
||||
}
|
||||
|
||||
progressFilter.removeProgressListener(this);
|
||||
const webProgress = docShell
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
webProgress.removeProgressListener(progressFilter);
|
||||
},
|
||||
};
|
||||
|
||||
progressFilter.addProgressListener(progressListener, flags);
|
||||
const webProgress = docShell
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
webProgress.addProgressListener(progressFilter, flags);
|
||||
|
||||
this.loadEntry(loadOptions, restoredHistory);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "GeckoView:UpdateInitData": {
|
||||
// Provide a hook for native code to detect a transfer.
|
||||
Services.obs.notifyObservers(
|
||||
this.docShell,
|
||||
"geckoview-content-global-transferred"
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "GeckoView:ScrollBy": {
|
||||
const x = {};
|
||||
const y = {};
|
||||
const { contentWindow } = this;
|
||||
const {
|
||||
widthValue,
|
||||
widthType,
|
||||
heightValue,
|
||||
heightType,
|
||||
behavior,
|
||||
} = message.data;
|
||||
contentWindow.windowUtils.getVisualViewportOffset(x, y);
|
||||
contentWindow.windowUtils.scrollToVisual(
|
||||
x.value + this.toPixels(widthValue, widthType),
|
||||
y.value + this.toPixels(heightValue, heightType),
|
||||
contentWindow.windowUtils.UPDATE_TYPE_MAIN_THREAD,
|
||||
this.toScrollBehavior(behavior)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "GeckoView:ScrollTo": {
|
||||
const { contentWindow } = this;
|
||||
const {
|
||||
widthValue,
|
||||
widthType,
|
||||
heightValue,
|
||||
heightType,
|
||||
behavior,
|
||||
} = message.data;
|
||||
contentWindow.windowUtils.scrollToVisual(
|
||||
this.toPixels(widthValue, widthType),
|
||||
this.toPixels(heightValue, heightType),
|
||||
contentWindow.windowUtils.UPDATE_TYPE_MAIN_THREAD,
|
||||
this.toScrollBehavior(behavior)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "CollectSessionState": {
|
||||
return this.collectSessionState();
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
handleEvent(aEvent) {
|
||||
debug`handleEvent: ${aEvent.type}`;
|
||||
|
||||
switch (aEvent.type) {
|
||||
case "contextmenu": {
|
||||
function nearestParentAttribute(aNode, aAttribute) {
|
||||
while (
|
||||
aNode &&
|
||||
aNode.hasAttribute &&
|
||||
!aNode.hasAttribute(aAttribute)
|
||||
) {
|
||||
aNode = aNode.parentNode;
|
||||
}
|
||||
return aNode && aNode.getAttribute && aNode.getAttribute(aAttribute);
|
||||
}
|
||||
|
||||
function createAbsoluteUri(aBaseUri, aUri) {
|
||||
if (!aUri || !aBaseUri || !aBaseUri.displaySpec) {
|
||||
return null;
|
||||
}
|
||||
return Services.io.newURI(aUri, null, aBaseUri).displaySpec;
|
||||
}
|
||||
|
||||
const node = aEvent.composedTarget;
|
||||
const baseUri = node.ownerDocument.baseURIObject;
|
||||
const uri = createAbsoluteUri(
|
||||
baseUri,
|
||||
nearestParentAttribute(node, "href")
|
||||
);
|
||||
const title = nearestParentAttribute(node, "title");
|
||||
const alt = nearestParentAttribute(node, "alt");
|
||||
const elementType = ChromeUtils.getClassName(node);
|
||||
const isImage = elementType === "HTMLImageElement";
|
||||
const isMedia =
|
||||
elementType === "HTMLVideoElement" ||
|
||||
elementType === "HTMLAudioElement";
|
||||
const elementSrc =
|
||||
(isImage || isMedia) && (node.currentSrc || node.src);
|
||||
|
||||
if (uri || isImage || isMedia) {
|
||||
const msg = {
|
||||
type: "GeckoView:ContextMenu",
|
||||
screenX: aEvent.screenX,
|
||||
screenY: aEvent.screenY,
|
||||
baseUri: (baseUri && baseUri.displaySpec) || null,
|
||||
uri,
|
||||
title,
|
||||
alt,
|
||||
elementType,
|
||||
elementSrc: elementSrc || null,
|
||||
};
|
||||
|
||||
this.eventDispatcher.sendRequest(msg);
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "MozDOMFullscreen:Request": {
|
||||
this.sendAsyncMessage("GeckoView:DOMFullscreenRequest", {});
|
||||
break;
|
||||
}
|
||||
case "MozDOMFullscreen:Entered":
|
||||
case "MozDOMFullscreen:Exited":
|
||||
// Content may change fullscreen state by itself, and we should ensure
|
||||
// that the parent always exits fullscreen when content has left
|
||||
// full screen mode.
|
||||
if (this.contentWindow?.document.fullscreenElement) {
|
||||
break;
|
||||
}
|
||||
// fall-through
|
||||
case "MozDOMFullscreen:Exit":
|
||||
this.sendAsyncMessage("GeckoView:DOMFullscreenExit", {});
|
||||
break;
|
||||
case "DOMMetaViewportFitChanged":
|
||||
if (aEvent.originalTarget.ownerGlobal == this.contentWindow) {
|
||||
this.notifyParentOfViewportFit();
|
||||
}
|
||||
break;
|
||||
case "DOMTitleChanged":
|
||||
this.eventDispatcher.sendRequest({
|
||||
type: "GeckoView:DOMTitleChanged",
|
||||
title: this.contentWindow.document.title,
|
||||
});
|
||||
break;
|
||||
case "DOMWindowClose":
|
||||
if (!aEvent.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
aEvent.preventDefault();
|
||||
this.eventDispatcher.sendRequest({
|
||||
type: "GeckoView:DOMWindowClose",
|
||||
});
|
||||
break;
|
||||
case "mozcaretstatechanged":
|
||||
if (
|
||||
aEvent.reason === "presscaret" ||
|
||||
aEvent.reason === "releasecaret"
|
||||
) {
|
||||
this.eventDispatcher.sendRequest({
|
||||
type: "GeckoView:PinOnScreen",
|
||||
pinned: aEvent.reason === "presscaret",
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "DOMContentLoaded": {
|
||||
if (aEvent.originalTarget.ownerGlobal == this.contentWindow) {
|
||||
// If loaded content doesn't have viewport-fit, parent still
|
||||
// uses old value of previous content.
|
||||
this.notifyParentOfViewportFit();
|
||||
}
|
||||
this.contentWindow.requestIdleCallback(async () => {
|
||||
const manifest = await ManifestObtainer.contentObtainManifest(
|
||||
this.contentWindow
|
||||
);
|
||||
if (manifest) {
|
||||
this.eventDispatcher.sendRequest({
|
||||
type: "GeckoView:WebAppManifest",
|
||||
manifest,
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "MozFirstContentfulPaint": {
|
||||
this.eventDispatcher.sendRequest({
|
||||
type: "GeckoView:FirstContentfulPaint",
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["GeckoViewContentParent"];
|
||||
|
||||
const { GeckoViewUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/GeckoViewUtils.jsm"
|
||||
);
|
||||
|
||||
const { debug, warn } = GeckoViewUtils.initLogging("GeckoViewContentParent"); // eslint-disable-line no-unused-vars
|
||||
|
||||
class GeckoViewContentParent extends JSWindowActorParent {
|
||||
async receiveMessage(aMsg) {
|
||||
debug`receiveMessage: ${aMsg.name} ${aMsg}`;
|
||||
|
||||
const browser = this.browsingContext.top.embedderElement;
|
||||
const window = browser.ownerGlobal;
|
||||
|
||||
switch (aMsg.name) {
|
||||
case "GeckoView:DOMFullscreenExit": {
|
||||
window.windowUtils.remoteFrameFullscreenReverted();
|
||||
break;
|
||||
}
|
||||
|
||||
case "GeckoView:DOMFullscreenRequest": {
|
||||
window.windowUtils.remoteFrameFullscreenChanged(browser);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ with Files('**'):
|
|||
FINAL_TARGET_FILES.actors += [
|
||||
'BrowserTabParent.jsm',
|
||||
'GeckoViewContentChild.jsm',
|
||||
'GeckoViewContentParent.jsm',
|
||||
'LoadURIDelegateChild.jsm',
|
||||
'WebBrowserChromeChild.jsm',
|
||||
]
|
||||
|
|
|
@ -1,498 +0,0 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 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/. */
|
||||
|
||||
const { GeckoViewChildModule } = ChromeUtils.import(
|
||||
"resource://gre/modules/GeckoViewChildModule.jsm"
|
||||
);
|
||||
var { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// This needs to match ScreenLength.java
|
||||
const SCREEN_LENGTH_TYPE_PIXEL = 0;
|
||||
const SCREEN_LENGTH_TYPE_VISUAL_VIEWPORT_WIDTH = 1;
|
||||
const SCREEN_LENGTH_TYPE_VISUAL_VIEWPORT_HEIGHT = 2;
|
||||
const SCREEN_LENGTH_DOCUMENT_WIDTH = 3;
|
||||
const SCREEN_LENGTH_DOCUMENT_HEIGHT = 4;
|
||||
|
||||
// This need to match PanZoomController.java
|
||||
const SCROLL_BEHAVIOR_SMOOTH = 0;
|
||||
const SCROLL_BEHAVIOR_AUTO = 1;
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
|
||||
ManifestObtainer: "resource://gre/modules/ManifestObtainer.jsm",
|
||||
PrivacyFilter: "resource://gre/modules/sessionstore/PrivacyFilter.jsm",
|
||||
SessionHistory: "resource://gre/modules/sessionstore/SessionHistory.jsm",
|
||||
});
|
||||
|
||||
class GeckoViewContentChild extends GeckoViewChildModule {
|
||||
onInit() {
|
||||
debug`onInit`;
|
||||
|
||||
// We don't load this in the global namespace because
|
||||
// a Utils.jsm in a11y will clobber us.
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
Utils: "resource://gre/modules/sessionstore/Utils.jsm",
|
||||
});
|
||||
|
||||
this.timeoutsSuspended = false;
|
||||
this.lastViewportFit = "";
|
||||
this.triggerViewportFitChange = null;
|
||||
|
||||
this.messageManager.addMessageListener(
|
||||
"GeckoView:DOMFullscreenEntered",
|
||||
this
|
||||
);
|
||||
this.messageManager.addMessageListener(
|
||||
"GeckoView:DOMFullscreenExited",
|
||||
this
|
||||
);
|
||||
this.messageManager.addMessageListener("GeckoView:RestoreState", this);
|
||||
this.messageManager.addMessageListener("GeckoView:UpdateInitData", this);
|
||||
this.messageManager.addMessageListener("GeckoView:ZoomToInput", this);
|
||||
this.messageManager.addMessageListener("GeckoView:ScrollBy", this);
|
||||
this.messageManager.addMessageListener("GeckoView:ScrollTo", this);
|
||||
|
||||
const options = {
|
||||
mozSystemGroup: true,
|
||||
capture: false,
|
||||
};
|
||||
addEventListener("mozcaretstatechanged", this, options);
|
||||
|
||||
// Notify WebExtension process script that this tab is ready for extension content to load.
|
||||
Services.obs.notifyObservers(
|
||||
this.messageManager,
|
||||
"tab-content-frameloader-created"
|
||||
);
|
||||
}
|
||||
|
||||
onEnable() {
|
||||
debug`onEnable`;
|
||||
|
||||
addEventListener("DOMTitleChanged", this, false);
|
||||
addEventListener("DOMWindowClose", this, false);
|
||||
addEventListener("MozDOMFullscreen:Entered", this, false);
|
||||
addEventListener("MozDOMFullscreen:Exit", this, false);
|
||||
addEventListener("MozDOMFullscreen:Exited", this, false);
|
||||
addEventListener("MozDOMFullscreen:Request", this, false);
|
||||
addEventListener("contextmenu", this, { capture: true });
|
||||
addEventListener("DOMContentLoaded", this, false);
|
||||
addEventListener("MozFirstContentfulPaint", this, false);
|
||||
addEventListener("DOMMetaViewportFitChanged", this, false);
|
||||
}
|
||||
|
||||
onDisable() {
|
||||
debug`onDisable`;
|
||||
|
||||
removeEventListener("DOMTitleChanged", this);
|
||||
removeEventListener("DOMWindowClose", this);
|
||||
removeEventListener("MozDOMFullscreen:Entered", this);
|
||||
removeEventListener("MozDOMFullscreen:Exit", this);
|
||||
removeEventListener("MozDOMFullscreen:Exited", this);
|
||||
removeEventListener("MozDOMFullscreen:Request", this);
|
||||
removeEventListener("contextmenu", this, { capture: true });
|
||||
removeEventListener("DOMContentLoaded", this);
|
||||
removeEventListener("MozFirstContentfulPaint", this);
|
||||
removeEventListener("DOMMetaViewportFitChanged", this);
|
||||
}
|
||||
|
||||
toPixels(aLength, aType) {
|
||||
if (aType === SCREEN_LENGTH_TYPE_PIXEL) {
|
||||
return aLength;
|
||||
} else if (aType === SCREEN_LENGTH_TYPE_VISUAL_VIEWPORT_WIDTH) {
|
||||
return aLength * content.visualViewport.width;
|
||||
} else if (aType === SCREEN_LENGTH_TYPE_VISUAL_VIEWPORT_HEIGHT) {
|
||||
return aLength * content.visualViewport.height;
|
||||
} else if (aType === SCREEN_LENGTH_DOCUMENT_WIDTH) {
|
||||
return aLength * content.document.body.scrollWidth;
|
||||
} else if (aType === SCREEN_LENGTH_DOCUMENT_HEIGHT) {
|
||||
return aLength * content.document.body.scrollHeight;
|
||||
}
|
||||
|
||||
return aLength;
|
||||
}
|
||||
|
||||
toScrollBehavior(aBehavior) {
|
||||
if (!content) {
|
||||
return 0;
|
||||
}
|
||||
if (aBehavior === SCROLL_BEHAVIOR_SMOOTH) {
|
||||
return content.windowUtils.SCROLL_MODE_SMOOTH;
|
||||
} else if (aBehavior === SCROLL_BEHAVIOR_AUTO) {
|
||||
return content.windowUtils.SCROLL_MODE_INSTANT;
|
||||
}
|
||||
return content.windowUtils.SCROLL_MODE_SMOOTH;
|
||||
}
|
||||
|
||||
notifyParentOfViewportFit() {
|
||||
if (this.triggerViewportFitChange) {
|
||||
content.cancelIdleCallback(this.triggerViewportFitChange);
|
||||
}
|
||||
this.triggerViewportFitChange = content.requestIdleCallback(() => {
|
||||
this.triggerViewportFitChange = null;
|
||||
const viewportFit = content.windowUtils.getViewportFitInfo();
|
||||
if (this.lastViewportFit === viewportFit) {
|
||||
return;
|
||||
}
|
||||
this.lastViewportFit = viewportFit;
|
||||
this.eventDispatcher.sendRequest({
|
||||
type: "GeckoView:DOMMetaViewportFit",
|
||||
viewportfit: viewportFit,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
receiveMessage(aMsg) {
|
||||
debug`receiveMessage: ${aMsg.name}`;
|
||||
|
||||
switch (aMsg.name) {
|
||||
case "GeckoView:DOMFullscreenEntered":
|
||||
if (content) {
|
||||
content.windowUtils.handleFullscreenRequests();
|
||||
}
|
||||
break;
|
||||
|
||||
case "GeckoView:DOMFullscreenExited":
|
||||
if (content) {
|
||||
content.windowUtils.exitFullscreen();
|
||||
}
|
||||
break;
|
||||
case "GeckoView:ZoomToInput": {
|
||||
const dwu = content.windowUtils;
|
||||
|
||||
const zoomToFocusedInput = function() {
|
||||
if (!dwu.flushApzRepaints()) {
|
||||
dwu.zoomToFocusedInput();
|
||||
return;
|
||||
}
|
||||
Services.obs.addObserver(function apzFlushDone() {
|
||||
Services.obs.removeObserver(apzFlushDone, "apz-repaints-flushed");
|
||||
dwu.zoomToFocusedInput();
|
||||
}, "apz-repaints-flushed");
|
||||
};
|
||||
|
||||
const { force } = aMsg.data;
|
||||
|
||||
let gotResize = false;
|
||||
const onResize = function() {
|
||||
gotResize = true;
|
||||
if (dwu.isMozAfterPaintPending) {
|
||||
addEventListener(
|
||||
"MozAfterPaint",
|
||||
function paintDone() {
|
||||
removeEventListener("MozAfterPaint", paintDone, {
|
||||
capture: true,
|
||||
});
|
||||
zoomToFocusedInput();
|
||||
},
|
||||
{ capture: true }
|
||||
);
|
||||
} else {
|
||||
zoomToFocusedInput();
|
||||
}
|
||||
};
|
||||
|
||||
addEventListener("resize", onResize, { capture: true });
|
||||
|
||||
// When the keyboard is displayed, we can get one resize event,
|
||||
// multiple resize events, or none at all. Try to handle all these
|
||||
// cases by allowing resizing within a set interval, and still zoom to
|
||||
// input if there is no resize event at the end of the interval.
|
||||
content.setTimeout(() => {
|
||||
removeEventListener("resize", onResize, { capture: true });
|
||||
if (!gotResize && force) {
|
||||
onResize();
|
||||
}
|
||||
}, 500);
|
||||
break;
|
||||
}
|
||||
|
||||
case "GeckoView:RestoreState":
|
||||
const { history, formdata, scrolldata, loadOptions } = aMsg.data;
|
||||
this._savedState = { history, formdata, scrolldata };
|
||||
|
||||
if (history) {
|
||||
const restoredHistory = SessionHistory.restore(docShell, history);
|
||||
|
||||
addEventListener(
|
||||
"load",
|
||||
_ => {
|
||||
if (formdata) {
|
||||
this.Utils.restoreFrameTreeData(
|
||||
content,
|
||||
formdata,
|
||||
(frame, data) => {
|
||||
// restore() will return false, and thus abort restoration for the
|
||||
// current |frame| and its descendants, if |data.url| is given but
|
||||
// doesn't match the loaded document's URL.
|
||||
return SessionStoreUtils.restoreFormData(
|
||||
frame.document,
|
||||
data
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
{ capture: true, mozSystemGroup: true, once: true }
|
||||
);
|
||||
|
||||
const scrollRestore = _ => {
|
||||
if (content.location != "about:blank") {
|
||||
if (scrolldata) {
|
||||
this.Utils.restoreFrameTreeData(
|
||||
content,
|
||||
scrolldata,
|
||||
(frame, data) => {
|
||||
if (data.scroll) {
|
||||
SessionStoreUtils.restoreScrollPosition(frame, data);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
delete this._savedState;
|
||||
removeEventListener("pageshow", scrollRestore, {
|
||||
capture: true,
|
||||
mozSystemGroup: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
addEventListener("pageshow", scrollRestore, {
|
||||
capture: true,
|
||||
mozSystemGroup: true,
|
||||
});
|
||||
|
||||
if (!this.progressFilter) {
|
||||
this.progressFilter = Cc[
|
||||
"@mozilla.org/appshell/component/browser-status-filter;1"
|
||||
].createInstance(Ci.nsIWebProgress);
|
||||
this.flags = Ci.nsIWebProgress.NOTIFY_LOCATION;
|
||||
}
|
||||
|
||||
this.progressFilter.addProgressListener(this, this.flags);
|
||||
const webProgress = docShell
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
webProgress.addProgressListener(this.progressFilter, this.flags);
|
||||
|
||||
this.loadEntry(loadOptions, restoredHistory);
|
||||
}
|
||||
break;
|
||||
|
||||
case "GeckoView:UpdateInitData":
|
||||
// Provide a hook for native code to detect a transfer.
|
||||
Services.obs.notifyObservers(
|
||||
docShell,
|
||||
"geckoview-content-global-transferred"
|
||||
);
|
||||
break;
|
||||
case "GeckoView:ScrollBy":
|
||||
const x = {};
|
||||
const y = {};
|
||||
content.windowUtils.getVisualViewportOffset(x, y);
|
||||
content.windowUtils.scrollToVisual(
|
||||
x.value + this.toPixels(aMsg.data.widthValue, aMsg.data.widthType),
|
||||
y.value + this.toPixels(aMsg.data.heightValue, aMsg.data.heightType),
|
||||
content.windowUtils.UPDATE_TYPE_MAIN_THREAD,
|
||||
this.toScrollBehavior(aMsg.data.behavior)
|
||||
);
|
||||
break;
|
||||
case "GeckoView:ScrollTo":
|
||||
content.windowUtils.scrollToVisual(
|
||||
this.toPixels(aMsg.data.widthValue, aMsg.data.widthType),
|
||||
this.toPixels(aMsg.data.heightValue, aMsg.data.heightType),
|
||||
content.windowUtils.UPDATE_TYPE_MAIN_THREAD,
|
||||
this.toScrollBehavior(aMsg.data.behavior)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
loadEntry(loadOptions, history) {
|
||||
if (!loadOptions) {
|
||||
history.QueryInterface(Ci.nsISHistory).reloadCurrentEntry();
|
||||
return;
|
||||
}
|
||||
|
||||
const webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
|
||||
const {
|
||||
referrerInfo,
|
||||
triggeringPrincipal,
|
||||
uri,
|
||||
flags,
|
||||
csp,
|
||||
headers,
|
||||
} = loadOptions;
|
||||
|
||||
webNavigation.loadURI(uri, {
|
||||
triggeringPrincipal: E10SUtils.deserializePrincipal(triggeringPrincipal),
|
||||
referrerInfo: E10SUtils.deserializeReferrerInfo(referrerInfo),
|
||||
loadFlags: flags,
|
||||
csp: E10SUtils.deserializeCSP(csp),
|
||||
headers,
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
handleEvent(aEvent) {
|
||||
debug`handleEvent: ${aEvent.type}`;
|
||||
|
||||
switch (aEvent.type) {
|
||||
case "contextmenu":
|
||||
function nearestParentAttribute(aNode, aAttribute) {
|
||||
while (
|
||||
aNode &&
|
||||
aNode.hasAttribute &&
|
||||
!aNode.hasAttribute(aAttribute)
|
||||
) {
|
||||
aNode = aNode.parentNode;
|
||||
}
|
||||
return aNode && aNode.getAttribute && aNode.getAttribute(aAttribute);
|
||||
}
|
||||
|
||||
function createAbsoluteUri(aBaseUri, aUri) {
|
||||
if (!aUri || !aBaseUri || !aBaseUri.displaySpec) {
|
||||
return null;
|
||||
}
|
||||
return Services.io.newURI(aUri, null, aBaseUri).displaySpec;
|
||||
}
|
||||
|
||||
const node = aEvent.composedTarget;
|
||||
const baseUri = node.ownerDocument.baseURIObject;
|
||||
const uri = createAbsoluteUri(
|
||||
baseUri,
|
||||
nearestParentAttribute(node, "href")
|
||||
);
|
||||
const title = nearestParentAttribute(node, "title");
|
||||
const alt = nearestParentAttribute(node, "alt");
|
||||
const elementType = ChromeUtils.getClassName(node);
|
||||
const isImage = elementType === "HTMLImageElement";
|
||||
const isMedia =
|
||||
elementType === "HTMLVideoElement" ||
|
||||
elementType === "HTMLAudioElement";
|
||||
const elementSrc =
|
||||
(isImage || isMedia) && (node.currentSrc || node.src);
|
||||
|
||||
if (uri || isImage || isMedia) {
|
||||
const msg = {
|
||||
type: "GeckoView:ContextMenu",
|
||||
screenX: aEvent.screenX,
|
||||
screenY: aEvent.screenY,
|
||||
baseUri: (baseUri && baseUri.displaySpec) || null,
|
||||
uri,
|
||||
title,
|
||||
alt,
|
||||
elementType,
|
||||
elementSrc: elementSrc || null,
|
||||
};
|
||||
|
||||
this.eventDispatcher.sendRequest(msg);
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
break;
|
||||
case "MozDOMFullscreen:Request":
|
||||
sendAsyncMessage("GeckoView:DOMFullscreenRequest");
|
||||
break;
|
||||
case "MozDOMFullscreen:Entered":
|
||||
case "MozDOMFullscreen:Exited":
|
||||
// Content may change fullscreen state by itself, and we should ensure
|
||||
// that the parent always exits fullscreen when content has left
|
||||
// full screen mode.
|
||||
if (content && content.document.fullscreenElement) {
|
||||
break;
|
||||
}
|
||||
// fall-through
|
||||
case "MozDOMFullscreen:Exit":
|
||||
sendAsyncMessage("GeckoView:DOMFullscreenExit");
|
||||
break;
|
||||
case "DOMMetaViewportFitChanged":
|
||||
if (aEvent.originalTarget.ownerGlobal == content) {
|
||||
this.notifyParentOfViewportFit();
|
||||
}
|
||||
break;
|
||||
case "DOMTitleChanged":
|
||||
this.eventDispatcher.sendRequest({
|
||||
type: "GeckoView:DOMTitleChanged",
|
||||
title: content.document.title,
|
||||
});
|
||||
break;
|
||||
case "DOMWindowClose":
|
||||
if (!aEvent.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
aEvent.preventDefault();
|
||||
this.eventDispatcher.sendRequest({
|
||||
type: "GeckoView:DOMWindowClose",
|
||||
});
|
||||
break;
|
||||
case "mozcaretstatechanged":
|
||||
if (
|
||||
aEvent.reason === "presscaret" ||
|
||||
aEvent.reason === "releasecaret"
|
||||
) {
|
||||
this.eventDispatcher.sendRequest({
|
||||
type: "GeckoView:PinOnScreen",
|
||||
pinned: aEvent.reason === "presscaret",
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "DOMContentLoaded": {
|
||||
if (aEvent.originalTarget.ownerGlobal == content) {
|
||||
// If loaded content doesn't have viewport-fit, parent still
|
||||
// uses old value of previous content.
|
||||
this.notifyParentOfViewportFit();
|
||||
}
|
||||
content.requestIdleCallback(async () => {
|
||||
const manifest = await ManifestObtainer.contentObtainManifest(
|
||||
content
|
||||
);
|
||||
if (manifest) {
|
||||
this.eventDispatcher.sendRequest({
|
||||
type: "GeckoView:WebAppManifest",
|
||||
manifest,
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "MozFirstContentfulPaint":
|
||||
this.eventDispatcher.sendRequest({
|
||||
type: "GeckoView:FirstContentfulPaint",
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// WebProgress event handler.
|
||||
onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags) {
|
||||
debug`onLocationChange`;
|
||||
|
||||
if (this._savedState) {
|
||||
const scrolldata = this._savedState.scrolldata;
|
||||
if (scrolldata && scrolldata.zoom && scrolldata.zoom.displaySize) {
|
||||
const utils = content.windowUtils;
|
||||
// Restore zoom level.
|
||||
utils.setRestoreResolution(
|
||||
scrolldata.zoom.resolution,
|
||||
scrolldata.zoom.displaySize.width,
|
||||
scrolldata.zoom.displaySize.height
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.progressFilter.removeProgressListener(this);
|
||||
const webProgress = docShell
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
webProgress.removeProgressListener(this.progressFilter);
|
||||
}
|
||||
}
|
||||
|
||||
const { debug, warn } = GeckoViewContentChild.initLogging("GeckoViewContent"); // eslint-disable-line no-unused-vars
|
||||
const module = GeckoViewContentChild.create(this);
|
|
@ -0,0 +1,12 @@
|
|||
/* 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/. */
|
||||
|
||||
/* This is needed for extensions to load content scripts */
|
||||
|
||||
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// Send this notification from the content process so that the
|
||||
// ExtensionPolicyService can register this content frame and be ready to load
|
||||
// content scripts
|
||||
Services.obs.notifyObservers(this, "tab-content-frameloader-created");
|
|
@ -235,7 +235,7 @@ var ModuleManager = {
|
|||
module.enabled = true;
|
||||
});
|
||||
|
||||
this.messageManager.sendAsyncMessage(
|
||||
this.getActor("GeckoViewContent").sendAsyncMessage(
|
||||
"GeckoView:RestoreState",
|
||||
sessionState
|
||||
);
|
||||
|
@ -508,11 +508,16 @@ function startup() {
|
|||
|
||||
const browser = createBrowser();
|
||||
ModuleManager.init(browser, [
|
||||
{
|
||||
name: "ExtensionContent",
|
||||
onInit: {
|
||||
frameScript: "chrome://geckoview/content/extension-content.js",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "GeckoViewContent",
|
||||
onInit: {
|
||||
resource: "resource://gre/modules/GeckoViewContent.jsm",
|
||||
frameScript: "chrome://geckoview/content/GeckoViewContentChild.js",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -9,10 +9,10 @@ geckoview.jar:
|
|||
content/config.js
|
||||
% override chrome://global/content/config.xhtml chrome://geckoview/content/config.xhtml
|
||||
|
||||
content/extension-content.js
|
||||
content/geckoview.xhtml
|
||||
content/geckoview.js
|
||||
content/GeckoViewAutofillChild.js
|
||||
content/GeckoViewContentChild.js
|
||||
content/GeckoViewMediaChild.js
|
||||
content/GeckoViewProgressChild.js
|
||||
content/GeckoViewPromptChild.js
|
||||
|
|
|
@ -29,8 +29,25 @@ const JSWINDOWACTORS = {
|
|||
},
|
||||
},
|
||||
GeckoViewContent: {
|
||||
parent: {
|
||||
moduleURI: "resource:///actors/GeckoViewContentParent.jsm",
|
||||
},
|
||||
child: {
|
||||
moduleURI: "resource:///actors/GeckoViewContentChild.jsm",
|
||||
events: {
|
||||
DOMContentLoaded: {},
|
||||
DOMMetaViewportFitChanged: {},
|
||||
DOMTitleChanged: {},
|
||||
DOMWindowClose: {},
|
||||
"MozDOMFullscreen:Entered": {},
|
||||
"MozDOMFullscreen:Exit": {},
|
||||
"MozDOMFullscreen:Exited": {},
|
||||
"MozDOMFullscreen:Request": {},
|
||||
MozFirstContentfulPaint: {},
|
||||
contextmenu: { capture: true },
|
||||
mozcaretstatechanged: { capture: true, mozSystemGroup: true },
|
||||
},
|
||||
allFrames: true,
|
||||
},
|
||||
},
|
||||
LoadURIDelegate: {
|
||||
|
|
|
@ -25,11 +25,12 @@ class GeckoViewContent extends GeckoViewModule {
|
|||
"GeckoView:DisplayMatches",
|
||||
"GeckoView:FindInPage",
|
||||
"GeckoView:RestoreState",
|
||||
"GeckoView:SetActive",
|
||||
"GeckoView:SetFocused",
|
||||
"GeckoView:ZoomToInput",
|
||||
"GeckoView:ScrollBy",
|
||||
"GeckoView:ScrollTo",
|
||||
"GeckoView:SetActive",
|
||||
"GeckoView:SetFocused",
|
||||
"GeckoView:UpdateInitData",
|
||||
"GeckoView:ZoomToInput",
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -53,12 +54,6 @@ class GeckoViewContent extends GeckoViewModule {
|
|||
/* untrusted */ false
|
||||
);
|
||||
|
||||
this.messageManager.addMessageListener("GeckoView:DOMFullscreenExit", this);
|
||||
this.messageManager.addMessageListener(
|
||||
"GeckoView:DOMFullscreenRequest",
|
||||
this
|
||||
);
|
||||
|
||||
Services.obs.addObserver(this, "oop-frameloader-crashed");
|
||||
Services.obs.addObserver(this, "ipc:content-shutdown");
|
||||
}
|
||||
|
@ -80,26 +75,46 @@ class GeckoViewContent extends GeckoViewModule {
|
|||
/* capture */ true
|
||||
);
|
||||
|
||||
this.messageManager.removeMessageListener(
|
||||
"GeckoView:DOMFullscreenExit",
|
||||
this
|
||||
);
|
||||
this.messageManager.removeMessageListener(
|
||||
"GeckoView:DOMFullscreenRequest",
|
||||
this
|
||||
);
|
||||
|
||||
Services.obs.removeObserver(this, "oop-frameloader-crashed");
|
||||
Services.obs.removeObserver(this, "ipc:content-shutdown");
|
||||
}
|
||||
|
||||
get actor() {
|
||||
return this.getActor("GeckoViewContent");
|
||||
}
|
||||
|
||||
// Goes up the browsingContext chain and sends the message every time
|
||||
// we cross the process boundary so that every process in the chain is
|
||||
// notified.
|
||||
sendToAllChildren(aEvent, aData) {
|
||||
let { browsingContext } = this.actor;
|
||||
|
||||
while (browsingContext) {
|
||||
if (!browsingContext.currentWindowGlobal) {
|
||||
break;
|
||||
}
|
||||
|
||||
const currentPid = browsingContext.currentWindowGlobal.osPid;
|
||||
const parentPid = browsingContext.parent?.currentWindowGlobal.osPid;
|
||||
|
||||
if (currentPid != parentPid) {
|
||||
const actor = browsingContext.currentWindowGlobal.getActor(
|
||||
"GeckoViewContent"
|
||||
);
|
||||
actor.sendAsyncMessage(aEvent, aData);
|
||||
}
|
||||
|
||||
browsingContext = browsingContext.parent;
|
||||
}
|
||||
}
|
||||
|
||||
// Bundle event handler.
|
||||
onEvent(aEvent, aData, aCallback) {
|
||||
debug`onEvent: event=${aEvent}, data=${aData}`;
|
||||
|
||||
switch (aEvent) {
|
||||
case "GeckoViewContent:ExitFullScreen":
|
||||
this.messageManager.sendAsyncMessage("GeckoView:DOMFullscreenExited");
|
||||
this.sendToAllChildren("GeckoView:DOMFullscreenExited");
|
||||
break;
|
||||
case "GeckoView:ClearMatches": {
|
||||
this._clearMatches();
|
||||
|
@ -114,13 +129,18 @@ class GeckoViewContent extends GeckoViewModule {
|
|||
break;
|
||||
}
|
||||
case "GeckoView:ZoomToInput":
|
||||
this.messageManager.sendAsyncMessage(aEvent, aData);
|
||||
this.sendToAllChildren(aEvent, aData);
|
||||
break;
|
||||
case "GeckoView:ScrollBy":
|
||||
this.messageManager.sendAsyncMessage(aEvent, aData);
|
||||
// Unclear if that actually works with oop iframes?
|
||||
this.sendToAllChildren(aEvent, aData);
|
||||
break;
|
||||
case "GeckoView:ScrollTo":
|
||||
this.messageManager.sendAsyncMessage(aEvent, aData);
|
||||
// Unclear if that actually works with oop iframes?
|
||||
this.sendToAllChildren(aEvent, aData);
|
||||
break;
|
||||
case "GeckoView:UpdateInitData":
|
||||
this.sendToAllChildren(aEvent, aData);
|
||||
break;
|
||||
case "GeckoView:SetActive":
|
||||
this.browser.docShellIsActive = !!aData.active;
|
||||
|
@ -135,7 +155,8 @@ class GeckoViewContent extends GeckoViewModule {
|
|||
}
|
||||
break;
|
||||
case "GeckoView:RestoreState":
|
||||
this.messageManager.sendAsyncMessage("GeckoView:RestoreState", aData);
|
||||
// TODO: this needs parent process history to work properly
|
||||
this.actor.sendAsyncMessage("GeckoView:RestoreState", aData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -160,27 +181,11 @@ class GeckoViewContent extends GeckoViewModule {
|
|||
case "MozDOMFullscreen:Entered":
|
||||
if (this.browser == aEvent.target) {
|
||||
// Remote browser; dispatch to content process.
|
||||
this.messageManager.sendAsyncMessage(
|
||||
"GeckoView:DOMFullscreenEntered"
|
||||
);
|
||||
this.sendToAllChildren("GeckoView:DOMFullscreenEntered");
|
||||
}
|
||||
break;
|
||||
case "MozDOMFullscreen:Exited":
|
||||
this.messageManager.sendAsyncMessage("GeckoView:DOMFullscreenExited");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Message manager event handler.
|
||||
receiveMessage(aMsg) {
|
||||
debug`receiveMessage: ${aMsg.name}`;
|
||||
|
||||
switch (aMsg.name) {
|
||||
case "GeckoView:DOMFullscreenExit":
|
||||
this.window.windowUtils.remoteFrameFullscreenReverted();
|
||||
break;
|
||||
case "GeckoView:DOMFullscreenRequest":
|
||||
this.window.windowUtils.remoteFrameFullscreenChanged(aMsg.target);
|
||||
this.sendToAllChildren("GeckoView:DOMFullscreenExited");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,10 @@ class GeckoViewModule {
|
|||
return this.moduleManager.window;
|
||||
}
|
||||
|
||||
getActor(aActorName) {
|
||||
return this.moduleManager.getActor(aActorName);
|
||||
}
|
||||
|
||||
get browser() {
|
||||
return this.moduleManager.browser;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
[close-method.window.html]
|
||||
expected:
|
||||
if (os == "android") and e10s: TIMEOUT
|
||||
[window.close() affects name targeting immediately]
|
||||
expected:
|
||||
if (os == "android") and e10s: TIMEOUT
|
||||
FAIL
|
||||
|
||||
[window.close() queues a task to discard, but window.closed knows immediately]
|
||||
expected:
|
||||
if debug and not webrender and not e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: TIMEOUT
|
||||
if (os == "android"): FAIL
|
||||
|
||||
|
|
|
@ -1,24 +1,18 @@
|
|||
[self-et-al.window.html]
|
||||
expected:
|
||||
if (os == "android") and e10s: TIMEOUT
|
||||
max-asserts: 3
|
||||
[popupWindow.window before, after closing, and after discarding]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: TIMEOUT
|
||||
if (os == "android"): FAIL
|
||||
|
||||
[popupWindow.globalThis before, after closing, and after discarding]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: TIMEOUT
|
||||
if (os == "android"): FAIL
|
||||
|
||||
[popupWindow.frames before, after closing, and after discarding]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: TIMEOUT
|
||||
if (os == "android"): FAIL
|
||||
|
||||
[popupWindow.self before, after closing, and after discarding]
|
||||
expected:
|
||||
if (os == "android") and not e10s: FAIL
|
||||
if (os == "android") and e10s: TIMEOUT
|
||||
if (os == "android"): FAIL
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче