зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1592157, convert LinkHandlerChild.jsm to JSWindowActor to support fission, r=mak
Differential Revision: https://phabricator.services.mozilla.com/D51026 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
11c3c57ab3
Коммит
d12fb42226
|
@ -7,9 +7,6 @@
|
|||
const EXPORTED_SYMBOLS = ["LinkHandlerChild"];
|
||||
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const { ActorChild } = ChromeUtils.import(
|
||||
"resource://gre/modules/ActorChild.jsm"
|
||||
);
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
|
@ -17,7 +14,7 @@ ChromeUtils.defineModuleGetter(
|
|||
"resource:///modules/FaviconLoader.jsm"
|
||||
);
|
||||
|
||||
class LinkHandlerChild extends ActorChild {
|
||||
class LinkHandlerChild extends JSWindowActorChild {
|
||||
constructor(dispatcher) {
|
||||
super(dispatcher);
|
||||
|
||||
|
@ -27,7 +24,7 @@ class LinkHandlerChild extends ActorChild {
|
|||
|
||||
get iconLoader() {
|
||||
if (!this._iconLoader) {
|
||||
this._iconLoader = new FaviconLoader(this.mm);
|
||||
this._iconLoader = new FaviconLoader(this);
|
||||
}
|
||||
return this._iconLoader;
|
||||
}
|
||||
|
@ -40,7 +37,7 @@ class LinkHandlerChild extends ActorChild {
|
|||
) {
|
||||
// Inject the default icon. Use documentURIObject so that we do the right
|
||||
// thing with about:-style error pages. See bug 453442
|
||||
let pageURI = this.content.document.documentURIObject;
|
||||
let pageURI = this.document.documentURIObject;
|
||||
if (["http", "https"].includes(pageURI.scheme)) {
|
||||
this.seenTabIcon = true;
|
||||
this.iconLoader.addDefaultIcon(pageURI);
|
||||
|
@ -49,7 +46,7 @@ class LinkHandlerChild extends ActorChild {
|
|||
}
|
||||
|
||||
onHeadParsed(event) {
|
||||
if (event.target.ownerDocument != this.content.document) {
|
||||
if (event.target.ownerDocument != this.document) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -65,7 +62,7 @@ class LinkHandlerChild extends ActorChild {
|
|||
}
|
||||
|
||||
onPageShow(event) {
|
||||
if (event.target != this.content.document) {
|
||||
if (event.target != this.document) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -77,7 +74,7 @@ class LinkHandlerChild extends ActorChild {
|
|||
}
|
||||
|
||||
onPageHide(event) {
|
||||
if (event.target != this.content.document) {
|
||||
if (event.target != this.document) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -91,7 +88,7 @@ class LinkHandlerChild extends ActorChild {
|
|||
onLinkEvent(event) {
|
||||
let link = event.target;
|
||||
// Ignore sub-frames (bugs 305472, 479408).
|
||||
if (link.ownerGlobal != this.content) {
|
||||
if (link.ownerGlobal != this.contentWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -156,7 +153,7 @@ class LinkHandlerChild extends ActorChild {
|
|||
re.test(link.href)
|
||||
) {
|
||||
let engine = { title: link.title, href: link.href };
|
||||
this.mm.sendAsyncMessage("Link:AddSearch", {
|
||||
this.sendAsyncMessage("Link:AddSearch", {
|
||||
engine,
|
||||
url: link.ownerDocument.documentURI,
|
||||
});
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
/* 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";
|
||||
|
||||
const EXPORTED_SYMBOLS = ["LinkHandlerParent"];
|
||||
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"PlacesUIUtils",
|
||||
"resource:///modules/PlacesUIUtils.jsm"
|
||||
);
|
||||
|
||||
let gTestListeners = new Set();
|
||||
|
||||
class LinkHandlerParent extends JSWindowActorParent {
|
||||
static addListenerForTests(listener) {
|
||||
gTestListeners.add(listener);
|
||||
}
|
||||
|
||||
static removeListenerForTests(listener) {
|
||||
gTestListeners.delete(listener);
|
||||
}
|
||||
|
||||
receiveMessage(aMsg) {
|
||||
let browser = this.browsingContext.top.embedderElement;
|
||||
if (!browser) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (browser.outerBrowser) {
|
||||
// Responsive design mode check
|
||||
browser = browser.outerBrowser;
|
||||
}
|
||||
|
||||
let win = browser.ownerGlobal;
|
||||
|
||||
let gBrowser = win.gBrowser;
|
||||
if (!gBrowser) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aMsg.name) {
|
||||
case "Link:LoadingIcon":
|
||||
if (aMsg.data.canUseForTab) {
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
if (tab.hasAttribute("busy")) {
|
||||
tab.setAttribute("pendingicon", "true");
|
||||
}
|
||||
}
|
||||
|
||||
this.notifyTestListeners("LoadingIcon", aMsg.data);
|
||||
break;
|
||||
|
||||
case "Link:SetIcon":
|
||||
this.setIconFromLink(
|
||||
gBrowser,
|
||||
browser,
|
||||
aMsg.data.pageURL,
|
||||
aMsg.data.originalURL,
|
||||
aMsg.data.canUseForTab,
|
||||
aMsg.data.expiration,
|
||||
aMsg.data.iconURL
|
||||
);
|
||||
|
||||
this.notifyTestListeners("SetIcon", aMsg.data);
|
||||
break;
|
||||
|
||||
case "Link:SetFailedIcon":
|
||||
if (aMsg.data.canUseForTab) {
|
||||
this.clearPendingIcon(gBrowser, browser);
|
||||
}
|
||||
|
||||
this.notifyTestListeners("SetFailedIcon", aMsg.data);
|
||||
break;
|
||||
|
||||
case "Link:AddSearch":
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
if (!tab) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (win.BrowserSearch) {
|
||||
win.BrowserSearch.addEngine(
|
||||
browser,
|
||||
aMsg.data.engine,
|
||||
Services.io.newURI(aMsg.data.url)
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
notifyTestListeners(name, data) {
|
||||
for (let listener of gTestListeners) {
|
||||
listener(name, data);
|
||||
}
|
||||
}
|
||||
|
||||
clearPendingIcon(gBrowser, aBrowser) {
|
||||
let tab = gBrowser.getTabForBrowser(aBrowser);
|
||||
tab.removeAttribute("pendingicon");
|
||||
}
|
||||
|
||||
setIconFromLink(
|
||||
gBrowser,
|
||||
aBrowser,
|
||||
aPageURL,
|
||||
aOriginalURL,
|
||||
aCanUseForTab,
|
||||
aExpiration,
|
||||
aIconURL
|
||||
) {
|
||||
let tab = gBrowser.getTabForBrowser(aBrowser);
|
||||
if (!tab) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aCanUseForTab) {
|
||||
this.clearPendingIcon(gBrowser, aBrowser);
|
||||
}
|
||||
|
||||
let iconURI;
|
||||
try {
|
||||
iconURI = Services.io.newURI(aIconURL);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
return;
|
||||
}
|
||||
if (iconURI.scheme != "data") {
|
||||
try {
|
||||
Services.scriptSecurityManager.checkLoadURIWithPrincipal(
|
||||
aBrowser.contentPrincipal,
|
||||
iconURI,
|
||||
Services.scriptSecurityManager.ALLOW_CHROME
|
||||
);
|
||||
} catch (ex) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
PlacesUIUtils.loadFavicon(
|
||||
aBrowser,
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
Services.io.newURI(aPageURL),
|
||||
Services.io.newURI(aOriginalURL),
|
||||
aExpiration,
|
||||
iconURI
|
||||
);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
|
||||
if (aCanUseForTab) {
|
||||
gBrowser.setIcon(tab, aIconURL, aOriginalURL);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -39,6 +39,7 @@ FINAL_TARGET_FILES.actors += [
|
|||
'FormValidationParent.jsm',
|
||||
'LightweightThemeChild.jsm',
|
||||
'LinkHandlerChild.jsm',
|
||||
'LinkHandlerParent.jsm',
|
||||
'NetErrorChild.jsm',
|
||||
'OfflineAppsChild.jsm',
|
||||
'PageInfoChild.jsm',
|
||||
|
|
|
@ -1807,7 +1807,6 @@ var gBrowserInit = {
|
|||
// loading the frame script to ensure that we don't miss any
|
||||
// message sent between when the frame script is loaded and when
|
||||
// the listener is registered.
|
||||
DOMEventHandler.init();
|
||||
LanguageDetectionListener.init();
|
||||
BrowserOnClick.init();
|
||||
CaptivePortalWatcher.init();
|
||||
|
@ -4147,120 +4146,6 @@ var newWindowButtonObserver = {
|
|||
}
|
||||
},
|
||||
};
|
||||
const DOMEventHandler = {
|
||||
init() {
|
||||
let mm = window.messageManager;
|
||||
mm.addMessageListener("Link:LoadingIcon", this);
|
||||
mm.addMessageListener("Link:SetIcon", this);
|
||||
mm.addMessageListener("Link:SetFailedIcon", this);
|
||||
mm.addMessageListener("Link:AddSearch", this);
|
||||
},
|
||||
|
||||
receiveMessage(aMsg) {
|
||||
switch (aMsg.name) {
|
||||
case "Link:LoadingIcon":
|
||||
if (aMsg.data.canUseForTab) {
|
||||
this.setPendingIcon(aMsg.target);
|
||||
}
|
||||
break;
|
||||
|
||||
case "Link:SetIcon":
|
||||
this.setIconFromLink(
|
||||
aMsg.target,
|
||||
aMsg.data.pageURL,
|
||||
aMsg.data.originalURL,
|
||||
aMsg.data.canUseForTab,
|
||||
aMsg.data.expiration,
|
||||
aMsg.data.iconURL
|
||||
);
|
||||
break;
|
||||
|
||||
case "Link:SetFailedIcon":
|
||||
if (aMsg.data.canUseForTab) {
|
||||
this.clearPendingIcon(aMsg.target);
|
||||
}
|
||||
break;
|
||||
|
||||
case "Link:AddSearch":
|
||||
this.addSearch(aMsg.target, aMsg.data.engine, aMsg.data.url);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
setPendingIcon(aBrowser) {
|
||||
let tab = gBrowser.getTabForBrowser(aBrowser);
|
||||
if (tab.hasAttribute("busy")) {
|
||||
tab.setAttribute("pendingicon", "true");
|
||||
}
|
||||
},
|
||||
|
||||
clearPendingIcon(aBrowser) {
|
||||
let tab = gBrowser.getTabForBrowser(aBrowser);
|
||||
tab.removeAttribute("pendingicon");
|
||||
},
|
||||
|
||||
setIconFromLink(
|
||||
aBrowser,
|
||||
aPageURL,
|
||||
aOriginalURL,
|
||||
aCanUseForTab,
|
||||
aExpiration,
|
||||
aIconURL
|
||||
) {
|
||||
let tab = gBrowser.getTabForBrowser(aBrowser);
|
||||
if (!tab) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aCanUseForTab) {
|
||||
this.clearPendingIcon(aBrowser);
|
||||
}
|
||||
|
||||
let iconURI;
|
||||
try {
|
||||
iconURI = Services.io.newURI(aIconURL);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
return;
|
||||
}
|
||||
if (iconURI.scheme != "data") {
|
||||
try {
|
||||
Services.scriptSecurityManager.checkLoadURIWithPrincipal(
|
||||
aBrowser.contentPrincipal,
|
||||
iconURI,
|
||||
Services.scriptSecurityManager.ALLOW_CHROME
|
||||
);
|
||||
} catch (ex) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
PlacesUIUtils.loadFavicon(
|
||||
aBrowser,
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
makeURI(aPageURL),
|
||||
makeURI(aOriginalURL),
|
||||
aExpiration,
|
||||
iconURI
|
||||
);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
|
||||
if (aCanUseForTab) {
|
||||
gBrowser.setIcon(tab, aIconURL, aOriginalURL);
|
||||
}
|
||||
},
|
||||
|
||||
addSearch(aBrowser, aEngine, aURL) {
|
||||
let tab = gBrowser.getTabForBrowser(aBrowser);
|
||||
if (!tab) {
|
||||
return;
|
||||
}
|
||||
|
||||
BrowserSearch.addEngine(aBrowser, aEngine, makeURI(aURL));
|
||||
},
|
||||
};
|
||||
|
||||
const BrowserSearch = {
|
||||
_searchInitComplete: false,
|
||||
|
|
|
@ -18,11 +18,11 @@ function waitForAttributeChange(tab, attr) {
|
|||
function waitForPendingIcon() {
|
||||
return new Promise(resolve => {
|
||||
let listener = () => {
|
||||
window.messageManager.removeMessageListener("Link:LoadingIcon", listener);
|
||||
LinkHandlerParent.removeListenerForTests(listener);
|
||||
resolve();
|
||||
};
|
||||
|
||||
window.messageManager.addMessageListener("Link:LoadingIcon", listener);
|
||||
LinkHandlerParent.addListenerForTests(listener);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -11,43 +11,48 @@ ChromeUtils.defineModuleGetter(
|
|||
"resource://gre/modules/PlacesUtils.jsm"
|
||||
);
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"LinkHandlerParent",
|
||||
"resource:///actors/LinkHandlerParent.jsm"
|
||||
);
|
||||
|
||||
// Clear the network cache between every test to make sure we get a stable state
|
||||
Services.cache2.clear();
|
||||
|
||||
function waitForFaviconMessage(isTabIcon = undefined, expectedURL = undefined) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let listener = msg => {
|
||||
let listener = (name, data) => {
|
||||
if (name != "SetIcon" && name != "SetFailedIcon") {
|
||||
return; // Ignore unhandled messages
|
||||
}
|
||||
|
||||
// If requested filter out loads of the wrong kind of icon.
|
||||
if (isTabIcon != undefined && isTabIcon != msg.data.canUseForTab) {
|
||||
if (isTabIcon != undefined && isTabIcon != data.canUseForTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (expectedURL && msg.data.originalURL != expectedURL) {
|
||||
if (expectedURL && data.originalURL != expectedURL) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.messageManager.removeMessageListener("Link:SetIcon", listener);
|
||||
window.messageManager.removeMessageListener(
|
||||
"Link:SetFailedIcon",
|
||||
listener
|
||||
);
|
||||
LinkHandlerParent.removeListenerForTests(listener);
|
||||
|
||||
if (msg.name == "Link:SetIcon") {
|
||||
if (name == "SetIcon") {
|
||||
resolve({
|
||||
iconURL: msg.data.originalURL,
|
||||
dataURL: msg.data.iconURL,
|
||||
canUseForTab: msg.data.canUseForTab,
|
||||
iconURL: data.originalURL,
|
||||
dataURL: data.iconURL,
|
||||
canUseForTab: data.canUseForTab,
|
||||
});
|
||||
} else {
|
||||
reject({
|
||||
iconURL: msg.data.originalURL,
|
||||
canUseForTab: msg.data.canUseForTab,
|
||||
iconURL: data.originalURL,
|
||||
canUseForTab: data.canUseForTab,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
window.messageManager.addMessageListener("Link:SetIcon", listener);
|
||||
window.messageManager.addMessageListener("Link:SetFailedIcon", listener);
|
||||
LinkHandlerParent.addListenerForTests(listener);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,22 @@ let ACTORS = {
|
|||
allFrames: true,
|
||||
},
|
||||
|
||||
LinkHandler: {
|
||||
parent: {
|
||||
moduleURI: "resource:///actors/LinkHandlerParent.jsm",
|
||||
},
|
||||
child: {
|
||||
moduleURI: "resource:///actors/LinkHandlerChild.jsm",
|
||||
events: {
|
||||
DOMHeadElementParsed: {},
|
||||
DOMLinkAdded: {},
|
||||
DOMLinkChanged: {},
|
||||
pageshow: {},
|
||||
pagehide: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
PageInfo: {
|
||||
child: {
|
||||
moduleURI: "resource:///actors/PageInfoChild.jsm",
|
||||
|
@ -308,19 +324,6 @@ let LEGACY_ACTORS = {
|
|||
},
|
||||
},
|
||||
|
||||
LinkHandler: {
|
||||
child: {
|
||||
module: "resource:///actors/LinkHandlerChild.jsm",
|
||||
events: {
|
||||
DOMHeadElementParsed: {},
|
||||
DOMLinkAdded: {},
|
||||
DOMLinkChanged: {},
|
||||
pageshow: {},
|
||||
pagehide: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
NetError: {
|
||||
child: {
|
||||
module: "resource:///actors/NetErrorChild.jsm",
|
||||
|
|
|
@ -504,8 +504,8 @@ function selectIcons(iconInfos, preferredWidth) {
|
|||
}
|
||||
|
||||
class IconLoader {
|
||||
constructor(mm) {
|
||||
this.mm = mm;
|
||||
constructor(actor) {
|
||||
this.actor = actor;
|
||||
}
|
||||
|
||||
async load(iconInfo) {
|
||||
|
@ -525,7 +525,7 @@ class IconLoader {
|
|||
} catch (ex) {
|
||||
return;
|
||||
}
|
||||
this.mm.sendAsyncMessage("Link:SetIcon", {
|
||||
this.actor.sendAsyncMessage("Link:SetIcon", {
|
||||
pageURL: iconInfo.pageUri.spec,
|
||||
originalURL: iconInfo.iconUri.spec,
|
||||
canUseForTab: !iconInfo.isRichIcon,
|
||||
|
@ -536,7 +536,7 @@ class IconLoader {
|
|||
}
|
||||
|
||||
// Let the main process that a tab icon is possibly coming.
|
||||
this.mm.sendAsyncMessage("Link:LoadingIcon", {
|
||||
this.actor.sendAsyncMessage("Link:LoadingIcon", {
|
||||
originalURL: iconInfo.iconUri.spec,
|
||||
canUseForTab: !iconInfo.isRichIcon,
|
||||
});
|
||||
|
@ -545,7 +545,7 @@ class IconLoader {
|
|||
this._loader = new FaviconLoad(iconInfo);
|
||||
let { dataURL, expiration } = await this._loader.load();
|
||||
|
||||
this.mm.sendAsyncMessage("Link:SetIcon", {
|
||||
this.actor.sendAsyncMessage("Link:SetIcon", {
|
||||
pageURL: iconInfo.pageUri.spec,
|
||||
originalURL: iconInfo.iconUri.spec,
|
||||
canUseForTab: !iconInfo.isRichIcon,
|
||||
|
@ -557,7 +557,7 @@ class IconLoader {
|
|||
Cu.reportError(e);
|
||||
|
||||
// Used mainly for tests currently.
|
||||
this.mm.sendAsyncMessage("Link:SetFailedIcon", {
|
||||
this.actor.sendAsyncMessage("Link:SetFailedIcon", {
|
||||
originalURL: iconInfo.iconUri.spec,
|
||||
canUseForTab: !iconInfo.isRichIcon,
|
||||
});
|
||||
|
@ -578,14 +578,14 @@ class IconLoader {
|
|||
}
|
||||
|
||||
class FaviconLoader {
|
||||
constructor(mm) {
|
||||
this.mm = mm;
|
||||
constructor(actor) {
|
||||
this.actor = actor;
|
||||
this.iconInfos = [];
|
||||
|
||||
// For every page we attempt to find a rich icon and a tab icon. These
|
||||
// objects take care of the load process for each.
|
||||
this.richIconLoader = new IconLoader(mm);
|
||||
this.tabIconLoader = new IconLoader(mm);
|
||||
this.richIconLoader = new IconLoader(actor);
|
||||
this.tabIconLoader = new IconLoader(actor);
|
||||
|
||||
this.iconTask = new DeferredTask(
|
||||
() => this.loadIcons(),
|
||||
|
@ -603,7 +603,7 @@ class FaviconLoader {
|
|||
}
|
||||
|
||||
let preferredWidth =
|
||||
PREFERRED_WIDTH * Math.ceil(this.mm.content.devicePixelRatio);
|
||||
PREFERRED_WIDTH * Math.ceil(this.actor.contentWindow.devicePixelRatio);
|
||||
let { richIcon, tabIcon } = selectIcons(this.iconInfos, preferredWidth);
|
||||
this.iconInfos = [];
|
||||
|
||||
|
@ -638,7 +638,7 @@ class FaviconLoader {
|
|||
width: -1,
|
||||
isRichIcon: false,
|
||||
type: TYPE_ICO,
|
||||
node: this.mm.content.document,
|
||||
node: this.actor.document,
|
||||
});
|
||||
this.iconTask.arm();
|
||||
}
|
||||
|
|
|
@ -462,10 +462,6 @@ MessageManagerTunnel.prototype = {
|
|||
INNER_TO_OUTER_MESSAGES: [
|
||||
// Messages sent to browser.js
|
||||
"Browser:LoadURI",
|
||||
"Link:SetIcon",
|
||||
"Link:SetFailedIcon",
|
||||
"Link:AddFeed",
|
||||
"Link:AddSearch",
|
||||
"PageStyle:StyleSheets",
|
||||
// Messages sent to browser.js
|
||||
"DOMTitleChanged",
|
||||
|
|
Загрузка…
Ссылка в новой задаче