зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1591469, move reader mode to use JSWindowActor instead of message managers, r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D71452
This commit is contained in:
Родитель
c30d408639
Коммит
f9054b8cff
|
@ -6,10 +6,6 @@
|
|||
|
||||
var EXPORTED_SYMBOLS = ["AboutReaderChild"];
|
||||
|
||||
const { ActorChild } = ChromeUtils.import(
|
||||
"resource://gre/modules/ActorChild.jsm"
|
||||
);
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"AboutReader",
|
||||
|
@ -26,25 +22,38 @@ ChromeUtils.defineModuleGetter(
|
|||
"resource://gre/modules/Readerable.jsm"
|
||||
);
|
||||
|
||||
class AboutReaderChild extends ActorChild {
|
||||
constructor(dispatcher) {
|
||||
super(dispatcher);
|
||||
class AboutReaderChild extends JSWindowActorChild {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._reader = null;
|
||||
this._articlePromise = null;
|
||||
this._isLeavingReaderableReaderMode = false;
|
||||
}
|
||||
|
||||
willDestroy() {
|
||||
this.cancelPotentialPendingReadabilityCheck();
|
||||
this.readerModeHidden();
|
||||
}
|
||||
|
||||
readerModeHidden() {
|
||||
if (this._reader) {
|
||||
this._reader.clearActor();
|
||||
}
|
||||
this._reader = null;
|
||||
}
|
||||
|
||||
receiveMessage(message) {
|
||||
switch (message.name) {
|
||||
case "Reader:ToggleReaderMode":
|
||||
if (!this.isAboutReader) {
|
||||
this._articlePromise = ReaderMode.parseDocument(
|
||||
this.content.document
|
||||
).catch(Cu.reportError);
|
||||
ReaderMode.enterReaderMode(this.mm.docShell, this.content);
|
||||
this._articlePromise = ReaderMode.parseDocument(this.document).catch(
|
||||
Cu.reportError
|
||||
);
|
||||
ReaderMode.enterReaderMode(this.docShell, this.contentWindow);
|
||||
} else {
|
||||
this._isLeavingReaderableReaderMode = this.isReaderableAboutReader;
|
||||
ReaderMode.leaveReaderMode(this.mm.docShell, this.content);
|
||||
ReaderMode.leaveReaderMode(this.docShell, this.contentWindow);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -52,37 +61,40 @@ class AboutReaderChild extends ActorChild {
|
|||
this.updateReaderButton(!!(message.data && message.data.isArticle));
|
||||
break;
|
||||
}
|
||||
|
||||
// Forward the message to the reader if it has been created.
|
||||
if (this._reader) {
|
||||
this._reader.receiveMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
get isAboutReader() {
|
||||
if (!this.content) {
|
||||
if (!this.document) {
|
||||
return false;
|
||||
}
|
||||
return this.content.document.documentURI.startsWith("about:reader");
|
||||
return this.document.documentURI.startsWith("about:reader");
|
||||
}
|
||||
|
||||
get isReaderableAboutReader() {
|
||||
return (
|
||||
this.isAboutReader &&
|
||||
!this.content.document.documentElement.dataset.isError
|
||||
);
|
||||
return this.isAboutReader && !this.document.documentElement.dataset.isError;
|
||||
}
|
||||
|
||||
handleEvent(aEvent) {
|
||||
if (aEvent.originalTarget.defaultView != this.content) {
|
||||
if (aEvent.originalTarget.defaultView != this.contentWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aEvent.type) {
|
||||
case "AboutReaderContentLoaded":
|
||||
case "DOMContentLoaded":
|
||||
if (!this.isAboutReader) {
|
||||
this.updateReaderButton();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.content.document.body) {
|
||||
if (this.document.body) {
|
||||
// Update the toolbar icon to show the "reader active" icon.
|
||||
this.mm.sendAsyncMessage("Reader:UpdateReaderButton");
|
||||
new AboutReader(this.mm, this.content, this._articlePromise);
|
||||
this.sendAsyncMessage("Reader:UpdateReaderButton");
|
||||
this._reader = new AboutReader(this, this._articlePromise);
|
||||
this._articlePromise = null;
|
||||
}
|
||||
break;
|
||||
|
@ -92,7 +104,7 @@ class AboutReaderChild extends ActorChild {
|
|||
// this._isLeavingReaderableReaderMode is used here to keep the Reader Mode icon
|
||||
// visible in the location bar when transitioning from reader-mode page
|
||||
// back to the readable source page.
|
||||
this.mm.sendAsyncMessage("Reader:UpdateReaderButton", {
|
||||
this.sendAsyncMessage("Reader:UpdateReaderButton", {
|
||||
isArticle: this._isLeavingReaderableReaderMode,
|
||||
});
|
||||
if (this._isLeavingReaderableReaderMode) {
|
||||
|
@ -107,9 +119,6 @@ class AboutReaderChild extends ActorChild {
|
|||
this.updateReaderButton();
|
||||
}
|
||||
break;
|
||||
case "DOMContentLoaded":
|
||||
this.updateReaderButton();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,9 +132,9 @@ class AboutReaderChild extends ActorChild {
|
|||
if (
|
||||
!Readerable.isEnabledForParseOnLoad ||
|
||||
this.isAboutReader ||
|
||||
!this.content ||
|
||||
!(this.content.document instanceof this.content.HTMLDocument) ||
|
||||
this.content.document.mozSyntheticDocument
|
||||
!this.contentWindow ||
|
||||
!(this.document instanceof this.contentWindow.HTMLDocument) ||
|
||||
this.document.mozSyntheticDocument
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -135,11 +144,14 @@ class AboutReaderChild extends ActorChild {
|
|||
|
||||
cancelPotentialPendingReadabilityCheck() {
|
||||
if (this._pendingReadabilityCheck) {
|
||||
this.mm.removeEventListener(
|
||||
"MozAfterPaint",
|
||||
this._pendingReadabilityCheck
|
||||
);
|
||||
if (this._listenerWindow) {
|
||||
this._listenerWindow.removeEventListener(
|
||||
"MozAfterPaint",
|
||||
this._pendingReadabilityCheck
|
||||
);
|
||||
}
|
||||
delete this._pendingReadabilityCheck;
|
||||
delete this._listenerWindow;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,28 +165,43 @@ class AboutReaderChild extends ActorChild {
|
|||
this,
|
||||
forceNonArticle
|
||||
);
|
||||
this.mm.addEventListener("MozAfterPaint", this._pendingReadabilityCheck);
|
||||
|
||||
this._listenerWindow = this.contentWindow.windowRoot;
|
||||
this.contentWindow.windowRoot.addEventListener(
|
||||
"MozAfterPaint",
|
||||
this._pendingReadabilityCheck
|
||||
);
|
||||
}
|
||||
|
||||
onPaintWhenWaitedFor(forceNonArticle, event) {
|
||||
// In non-e10s, we'll get called for paints other than ours, and so it's
|
||||
// possible that this page hasn't been laid out yet, in which case we
|
||||
// should wait until we get an event that does relate to our layout. We
|
||||
// determine whether any of our this.content got painted by checking if there
|
||||
// are any painted rects.
|
||||
// determine whether any of our this.contentWindow got painted by checking
|
||||
// if there are any painted rects.
|
||||
if (!event.clientRects.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.cancelPotentialPendingReadabilityCheck();
|
||||
|
||||
// Ignore errors from actors that have been unloaded before the
|
||||
// paint event timer fires.
|
||||
let document;
|
||||
try {
|
||||
document = this.document;
|
||||
} catch (ex) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only send updates when there are articles; there's no point updating with
|
||||
// |false| all the time.
|
||||
if (Readerable.isProbablyReaderable(this.content.document)) {
|
||||
this.mm.sendAsyncMessage("Reader:UpdateReaderButton", {
|
||||
if (Readerable.isProbablyReaderable(document)) {
|
||||
this.sendAsyncMessage("Reader:UpdateReaderButton", {
|
||||
isArticle: true,
|
||||
});
|
||||
} else if (forceNonArticle) {
|
||||
this.mm.sendAsyncMessage("Reader:UpdateReaderButton", {
|
||||
this.sendAsyncMessage("Reader:UpdateReaderButton", {
|
||||
isArticle: false,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["ReaderParent"];
|
||||
var EXPORTED_SYMBOLS = ["AboutReaderParent"];
|
||||
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
|
@ -24,61 +24,146 @@ const gStringBundle = Services.strings.createBundle(
|
|||
"chrome://global/locale/aboutReader.properties"
|
||||
);
|
||||
|
||||
var ReaderParent = {
|
||||
// Listeners are added in BrowserGlue.jsm
|
||||
receiveMessage(message) {
|
||||
// A set of all of the AboutReaderParent actors that exist.
|
||||
// See bug 1631146 for a request for a less manual way of doing this.
|
||||
let gAllActors = new Set();
|
||||
|
||||
// A map of message names to listeners that listen to messages
|
||||
// received by the AboutReaderParent actors.
|
||||
let gListeners = new Map();
|
||||
|
||||
class AboutReaderParent extends JSWindowActorParent {
|
||||
didDestroy() {
|
||||
gAllActors.delete(this);
|
||||
}
|
||||
|
||||
isReaderMode(browser) {
|
||||
return browser.currentURI.spec.startsWith("about:reader");
|
||||
}
|
||||
|
||||
static addMessageListener(name, listener) {
|
||||
if (!gListeners.has(name)) {
|
||||
gListeners.set(name, new Set([listener]));
|
||||
} else {
|
||||
gListeners.get(name).add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
static removeMessageListener(name, listener) {
|
||||
if (!gListeners.has(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gListeners.get(name).delete(listener);
|
||||
}
|
||||
|
||||
static broadcastAsyncMessage(name, data) {
|
||||
for (let actor of gAllActors) {
|
||||
// Ignore errors for actors that might not be valid yet or anymore.
|
||||
try {
|
||||
actor.sendAsyncMessage(name, data);
|
||||
} catch (ex) {}
|
||||
}
|
||||
}
|
||||
|
||||
callListeners(message) {
|
||||
let listeners = gListeners.get(message.name);
|
||||
if (!listeners) {
|
||||
return;
|
||||
}
|
||||
|
||||
message.target = this.browsingContext.embedderElement;
|
||||
for (let listener of listeners.values()) {
|
||||
try {
|
||||
listener.receiveMessage(message);
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async receiveMessage(message) {
|
||||
switch (message.name) {
|
||||
case "Reader:FaviconRequest": {
|
||||
if (message.target.messageManager) {
|
||||
try {
|
||||
let preferredWidth = message.data.preferredWidth || 0;
|
||||
let uri = Services.io.newURI(message.data.url);
|
||||
try {
|
||||
let preferredWidth = message.data.preferredWidth || 0;
|
||||
let uri = Services.io.newURI(message.data.url);
|
||||
|
||||
let result = await new Promise(resolve => {
|
||||
PlacesUtils.favicons.getFaviconURLForPage(
|
||||
uri,
|
||||
iconUri => {
|
||||
if (iconUri) {
|
||||
iconUri = PlacesUtils.favicons.getFaviconLinkForIcon(iconUri);
|
||||
message.target.messageManager.sendAsyncMessage(
|
||||
"Reader:FaviconReturn",
|
||||
{
|
||||
url: message.data.url,
|
||||
faviconUrl: iconUri.pathQueryRef.replace(/^favicon:/, ""),
|
||||
}
|
||||
);
|
||||
resolve({
|
||||
url: message.data.url,
|
||||
faviconUrl: iconUri.pathQueryRef.replace(/^favicon:/, ""),
|
||||
});
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
},
|
||||
preferredWidth
|
||||
);
|
||||
} catch (ex) {
|
||||
Cu.reportError(
|
||||
"Error requesting favicon URL for about:reader content: " + ex
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
this.callListeners(message);
|
||||
return result;
|
||||
} catch (ex) {
|
||||
Cu.reportError(
|
||||
"Error requesting favicon URL for about:reader content: " + ex
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "Reader:UpdateReaderButton": {
|
||||
let browser = message.target;
|
||||
let browser = this.browsingContext.embedderElement;
|
||||
if (!browser) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (browser.outerBrowser) {
|
||||
browser = browser.outerBrowser; // handle RDM mode
|
||||
}
|
||||
|
||||
if (message.data && message.data.isArticle !== undefined) {
|
||||
browser.isArticle = message.data.isArticle;
|
||||
}
|
||||
this.updateReaderButton(browser);
|
||||
this.callListeners(message);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
this.callListeners(message);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static updateReaderButton(browser) {
|
||||
let windowGlobal = browser.browsingContext.currentWindowGlobal;
|
||||
let actor = windowGlobal.getActor("AboutReader");
|
||||
actor.updateReaderButton(browser);
|
||||
}
|
||||
|
||||
updateReaderButton(browser) {
|
||||
let win = browser.ownerGlobal;
|
||||
if (browser != win.gBrowser.selectedBrowser) {
|
||||
let tabBrowser = browser.getTabBrowser();
|
||||
if (!tabBrowser || browser != tabBrowser.selectedBrowser) {
|
||||
return;
|
||||
}
|
||||
|
||||
let win = browser.ownerGlobal;
|
||||
|
||||
let button = win.document.getElementById("reader-mode-button");
|
||||
let menuitem = win.document.getElementById("menu_readerModeItem");
|
||||
let key = win.document.getElementById("key_toggleReaderMode");
|
||||
if (browser.currentURI.spec.startsWith("about:reader")) {
|
||||
if (this.isReaderMode(browser)) {
|
||||
gAllActors.add(this);
|
||||
|
||||
let closeText = gStringBundle.GetStringFromName("readerView.close");
|
||||
|
||||
button.setAttribute("readeractive", true);
|
||||
|
@ -115,25 +200,35 @@ var ReaderParent = {
|
|||
Services.obs.notifyObservers(null, "reader-mode-available");
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
forceShowReaderIcon(browser) {
|
||||
static forceShowReaderIcon(browser) {
|
||||
browser.isArticle = true;
|
||||
this.updateReaderButton(browser);
|
||||
},
|
||||
AboutReaderParent.updateReaderButton(browser);
|
||||
}
|
||||
|
||||
buttonClick(event) {
|
||||
static buttonClick(event) {
|
||||
if (event.button != 0) {
|
||||
return;
|
||||
}
|
||||
this.toggleReaderMode(event);
|
||||
},
|
||||
AboutReaderParent.toggleReaderMode(event);
|
||||
}
|
||||
|
||||
toggleReaderMode(event) {
|
||||
static toggleReaderMode(event) {
|
||||
let win = event.target.ownerGlobal;
|
||||
let browser = win.gBrowser.selectedBrowser;
|
||||
browser.messageManager.sendAsyncMessage("Reader:ToggleReaderMode");
|
||||
},
|
||||
if (win.gBrowser) {
|
||||
let browser = win.gBrowser.selectedBrowser;
|
||||
|
||||
let windowGlobal = browser.browsingContext.currentWindowGlobal;
|
||||
let actor = windowGlobal.getActor("AboutReader");
|
||||
if (actor) {
|
||||
if (actor.isReaderMode(browser)) {
|
||||
gAllActors.delete(this);
|
||||
}
|
||||
actor.sendAsyncMessage("Reader:ToggleReaderMode", {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an article for a given URL. This method will download and parse a document.
|
||||
|
@ -152,5 +247,5 @@ var ReaderParent = {
|
|||
Cu.reportError("Error downloading and parsing document: " + e);
|
||||
return null;
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
|
@ -10,6 +10,9 @@ with Files("**"):
|
|||
with Files("ContentSearch*.jsm"):
|
||||
BUG_COMPONENT = ("Firefox", "Search")
|
||||
|
||||
with Files("AboutReaderParent.jsm"):
|
||||
BUG_COMPONENT = ("Toolkit", "Reader Mode")
|
||||
|
||||
with Files("LightweightThemeChild.jsm"):
|
||||
BUG_COMPONENT = ("WebExtensions", "Themes")
|
||||
|
||||
|
@ -34,6 +37,7 @@ FINAL_TARGET_FILES.actors += [
|
|||
'AboutProtectionsChild.jsm',
|
||||
'AboutProtectionsParent.jsm',
|
||||
'AboutReaderChild.jsm',
|
||||
'AboutReaderParent.jsm',
|
||||
'AboutTabCrashedChild.jsm',
|
||||
'AboutTabCrashedParent.jsm',
|
||||
'BlockedSiteChild.jsm',
|
||||
|
|
|
@ -334,7 +334,7 @@ var FullZoom = {
|
|||
async reduce() {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
if (browser.currentURI.spec.startsWith("about:reader")) {
|
||||
browser.messageManager.sendAsyncMessage("Reader:ZoomOut");
|
||||
browser.sendMessageToActor("Reader:ZoomOut", {}, "AboutReader");
|
||||
} else if (this._isPDFViewer(browser)) {
|
||||
browser.messageManager.sendAsyncMessage("PDFJS:ZoomOut");
|
||||
} else {
|
||||
|
@ -351,7 +351,7 @@ var FullZoom = {
|
|||
async enlarge() {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
if (browser.currentURI.spec.startsWith("about:reader")) {
|
||||
browser.messageManager.sendAsyncMessage("Reader:ZoomIn");
|
||||
browser.sendMessageToActor("Reader:ZoomIn", {}, "AboutReader");
|
||||
} else if (this._isPDFViewer(browser)) {
|
||||
browser.messageManager.sendAsyncMessage("PDFJS:ZoomIn");
|
||||
} else {
|
||||
|
@ -371,7 +371,7 @@ var FullZoom = {
|
|||
changeZoomBy(aBrowser, aValue) {
|
||||
if (aBrowser.currentURI.spec.startsWith("about:reader")) {
|
||||
const message = aValue > 0 ? "Reader::ZoomIn" : "Reader:ZoomOut";
|
||||
aBrowser.messageManager.sendAsyncMessage(message);
|
||||
aBrowser.sendMessageToActor(message, {}, "AboutReader");
|
||||
return;
|
||||
} else if (this._isPDFViewer(aBrowser)) {
|
||||
const message = aValue > 0 ? "PDFJS::ZoomIn" : "PDFJS:ZoomOut";
|
||||
|
@ -412,7 +412,7 @@ var FullZoom = {
|
|||
reset: function FullZoom_reset(browser = gBrowser.selectedBrowser) {
|
||||
let forceValue;
|
||||
if (browser.currentURI.spec.startsWith("about:reader")) {
|
||||
browser.messageManager.sendAsyncMessage("Reader:ResetZoom");
|
||||
browser.sendMessageToActor("Reader:ResetZoom", {}, "AboutReader");
|
||||
} else if (this._isPDFViewer(browser)) {
|
||||
browser.messageManager.sendAsyncMessage("PDFJS:ZoomReset");
|
||||
// Ensure that the UI elements of the PDF viewer won't be zoomed in/out
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<command id="View:PageSource" oncommand="BrowserViewSource(window.gBrowser.selectedBrowser);"/>
|
||||
<command id="View:PageInfo" oncommand="BrowserPageInfo();"/>
|
||||
<command id="View:FullScreen" oncommand="BrowserFullScreen();"/>
|
||||
<command id="View:ReaderView" oncommand="ReaderParent.toggleReaderMode(event);"/>
|
||||
<command id="View:ReaderView" oncommand="AboutReaderParent.toggleReaderMode(event);"/>
|
||||
<command id="View:PictureInPicture" oncommand="PictureInPicture.onCommand(event);"/>
|
||||
<command id="cmd_find" oncommand="gLazyFindCommand('onFindCommand')"/>
|
||||
<command id="cmd_findAgain" oncommand="gLazyFindCommand('onFindAgainCommand', false)"/>
|
||||
|
|
|
@ -16,6 +16,7 @@ ChromeUtils.import("resource://gre/modules/NotificationDB.jsm");
|
|||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
AboutNewTab: "resource:///modules/AboutNewTab.jsm",
|
||||
AboutReaderParent: "resource:///actors/AboutReaderParent.jsm",
|
||||
AddonManager: "resource://gre/modules/AddonManager.jsm",
|
||||
AMTelemetry: "resource://gre/modules/AddonManager.jsm",
|
||||
NewTabPagePreloading: "resource:///modules/NewTabPagePreloading.jsm",
|
||||
|
@ -60,7 +61,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
PromiseUtils: "resource://gre/modules/PromiseUtils.jsm",
|
||||
// TODO (Bug 1529552): Remove once old urlbar code goes away.
|
||||
ReaderMode: "resource://gre/modules/ReaderMode.jsm",
|
||||
ReaderParent: "resource:///modules/ReaderParent.jsm",
|
||||
RFPHelper: "resource://gre/modules/RFPHelper.jsm",
|
||||
SafeBrowsing: "resource://gre/modules/SafeBrowsing.jsm",
|
||||
Sanitizer: "resource:///modules/Sanitizer.jsm",
|
||||
|
@ -5283,7 +5283,7 @@ var XULBrowserWindow = {
|
|||
}
|
||||
Services.obs.notifyObservers(null, "touchbar-location-change", location);
|
||||
UpdateBackForwardCommands(gBrowser.webNavigation);
|
||||
ReaderParent.updateReaderButton(gBrowser.selectedBrowser);
|
||||
AboutReaderParent.updateReaderButton(gBrowser.selectedBrowser);
|
||||
|
||||
if (!gMultiProcessBrowser) {
|
||||
// Bug 1108553 - Cannot rotate images with e10s
|
||||
|
@ -5886,9 +5886,13 @@ var TabsProgressListener = {
|
|||
if (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) {
|
||||
// Reader mode cares about history.pushState and friends.
|
||||
// FIXME: The content process should manage this directly (bug 1445351).
|
||||
aBrowser.messageManager.sendAsyncMessage("Reader:PushState", {
|
||||
isArticle: aBrowser.isArticle,
|
||||
});
|
||||
aBrowser.sendMessageToActor(
|
||||
"Reader:PushState",
|
||||
{
|
||||
isArticle: aBrowser.isArticle,
|
||||
},
|
||||
"AboutReader"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1027,7 +1027,7 @@
|
|||
tooltip="dynamic-shortcut-tooltip"
|
||||
role="button"
|
||||
hidden="true"
|
||||
onclick="ReaderParent.buttonClick(event);"/>
|
||||
onclick="AboutReaderParent.buttonClick(event);"/>
|
||||
<toolbarbutton id="urlbar-zoom-button"
|
||||
onclick="FullZoom.reset();"
|
||||
tooltip="dynamic-shortcut-tooltip"
|
||||
|
|
|
@ -45,7 +45,6 @@ const whitelist = {
|
|||
"resource:///actors/SearchTelemetryChild.jsm",
|
||||
"resource:///actors/PromptChild.jsm",
|
||||
"resource://gre/actors/AutoCompleteChild.jsm",
|
||||
"resource://gre/modules/ActorChild.jsm",
|
||||
"resource://gre/modules/ActorManagerChild.jsm",
|
||||
"resource://gre/modules/E10SUtils.jsm",
|
||||
"resource://gre/modules/Readerable.jsm",
|
||||
|
|
|
@ -157,6 +157,21 @@ let ACTORS = {
|
|||
matches: ["about:protections"],
|
||||
},
|
||||
|
||||
AboutReader: {
|
||||
parent: {
|
||||
moduleURI: "resource:///actors/AboutReaderParent.jsm",
|
||||
},
|
||||
child: {
|
||||
moduleURI: "resource:///actors/AboutReaderChild.jsm",
|
||||
events: {
|
||||
DOMContentLoaded: {},
|
||||
pageshow: { mozSystemGroup: true },
|
||||
pagehide: { mozSystemGroup: true },
|
||||
},
|
||||
},
|
||||
messageManagerGroups: ["browsers"],
|
||||
},
|
||||
|
||||
AboutTabCrashed: {
|
||||
parent: {
|
||||
moduleURI: "resource:///actors/AboutTabCrashedParent.jsm",
|
||||
|
@ -521,20 +536,6 @@ let ACTORS = {
|
|||
};
|
||||
|
||||
let LEGACY_ACTORS = {
|
||||
AboutReader: {
|
||||
child: {
|
||||
module: "resource:///actors/AboutReaderChild.jsm",
|
||||
group: "browsers",
|
||||
events: {
|
||||
AboutReaderContentLoaded: { wantUntrusted: true },
|
||||
DOMContentLoaded: {},
|
||||
pageshow: { mozSystemGroup: true },
|
||||
pagehide: { mozSystemGroup: true },
|
||||
},
|
||||
messages: ["Reader:ToggleReaderMode", "Reader:PushState"],
|
||||
},
|
||||
},
|
||||
|
||||
URIFixup: {
|
||||
child: {
|
||||
module: "resource:///actors/URIFixupChild.jsm",
|
||||
|
@ -700,7 +701,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
AboutLoginsParent: "resource:///modules/AboutLoginsParent.jsm",
|
||||
AsyncPrefs: "resource://gre/modules/AsyncPrefs.jsm",
|
||||
PluginManager: "resource:///actors/PluginParent.jsm",
|
||||
ReaderParent: "resource:///modules/ReaderParent.jsm",
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,6 +25,11 @@ ChromeUtils.defineModuleGetter(
|
|||
"PromiseUtils",
|
||||
"resource://gre/modules/PromiseUtils.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"AboutReaderParent",
|
||||
"resource:///actors/AboutReaderParent.jsm"
|
||||
);
|
||||
|
||||
var { ExtensionError } = ExtensionUtils;
|
||||
|
||||
|
@ -352,7 +357,7 @@ class TabTracker extends TabTrackerBase {
|
|||
windowTracker.addOpenListener(this._handleWindowOpen);
|
||||
windowTracker.addCloseListener(this._handleWindowClose);
|
||||
|
||||
Services.mm.addMessageListener("Reader:UpdateReaderButton", this);
|
||||
AboutReaderParent.addMessageListener("Reader:UpdateReaderButton", this);
|
||||
|
||||
/* eslint-disable mozilla/balanced-listeners */
|
||||
this.on("tab-detached", this._handleTabDestroyed);
|
||||
|
|
|
@ -1489,8 +1489,11 @@ this.tabs = class extends ExtensionAPI {
|
|||
);
|
||||
}
|
||||
let nativeTab = getTabOrActive(tabId);
|
||||
nativeTab.linkedBrowser.messageManager.sendAsyncMessage(
|
||||
"Reader:ToggleReaderMode"
|
||||
|
||||
nativeTab.linkedBrowser.sendMessageToActor(
|
||||
"Reader:ToggleReaderMode",
|
||||
{},
|
||||
"AboutReader"
|
||||
);
|
||||
},
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ const { XPCOMUtils } = ChromeUtils.import(
|
|||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
|
||||
EveryWindow: "resource:///modules/EveryWindow.jsm",
|
||||
AboutReaderParent: "resource:///actors/AboutReaderParent.jsm",
|
||||
});
|
||||
|
||||
const FEW_MINUTES = 15 * 60 * 1000; // 15 mins
|
||||
|
@ -99,7 +100,7 @@ this.ASRouterTriggerListeners = new Map([
|
|||
init(triggerHandler, hosts, patterns) {
|
||||
if (!this._initialized) {
|
||||
this.receiveMessage = this.receiveMessage.bind(this);
|
||||
Services.mm.addMessageListener(this.readerModeEvent, this);
|
||||
AboutReaderParent.addMessageListener(this.readerModeEvent, this);
|
||||
this._triggerHandler = triggerHandler;
|
||||
this._initialized = true;
|
||||
}
|
||||
|
@ -128,7 +129,7 @@ this.ASRouterTriggerListeners = new Map([
|
|||
|
||||
uninit() {
|
||||
if (this._initialized) {
|
||||
Services.mm.removeMessageListener(this.readerModeEvent, this);
|
||||
AboutReaderParent.removeMessageListener(this.readerModeEvent, this);
|
||||
this._initialized = false;
|
||||
this._triggerHandler = null;
|
||||
this._hosts = new Set();
|
||||
|
|
|
@ -63,7 +63,10 @@ add_task(async function check_openArticleURL() {
|
|||
// Send a message from the content page (the TEST_URL) to the parent
|
||||
// This should trigger the `receiveMessage` cb in the articleTrigger
|
||||
await ContentTask.spawn(win.gBrowser.selectedBrowser, null, async () => {
|
||||
sendAsyncMessage("Reader:UpdateReaderButton", { isArticle: true });
|
||||
let readerActor = content.windowGlobalChild.getActor("AboutReader");
|
||||
readerActor.sendAsyncMessage("Reader:UpdateReaderButton", {
|
||||
isArticle: true,
|
||||
});
|
||||
});
|
||||
|
||||
await listenerTriggered.then(data =>
|
||||
|
|
|
@ -29,6 +29,11 @@ ChromeUtils.defineModuleGetter(
|
|||
"ReaderMode",
|
||||
"resource://gre/modules/ReaderMode.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"AboutReaderParent",
|
||||
"resource:///actors/AboutReaderParent.jsm"
|
||||
);
|
||||
|
||||
var EXPORTED_SYMBOLS = ["SaveToPocket"];
|
||||
|
||||
|
@ -244,8 +249,8 @@ var SaveToPocket = {
|
|||
this.updateElements(false);
|
||||
Services.obs.addObserver(this, "browser-delayed-startup-finished");
|
||||
}
|
||||
Services.mm.addMessageListener("Reader:OnSetup", this);
|
||||
Services.mm.addMessageListener("Reader:Clicked-pocket-button", this);
|
||||
AboutReaderParent.addMessageListener("Reader:OnSetup", this);
|
||||
AboutReaderParent.addMessageListener("Reader:Clicked-pocket-button", this);
|
||||
},
|
||||
|
||||
observe(subject, topic, data) {
|
||||
|
@ -265,7 +270,7 @@ var SaveToPocket = {
|
|||
|
||||
onPrefChange(pref, oldValue, newValue) {
|
||||
if (!newValue) {
|
||||
Services.mm.broadcastAsyncMessage("Reader:RemoveButton", {
|
||||
AboutReaderParent.broadcastAsyncMessage("Reader:RemoveButton", {
|
||||
id: "pocket-button",
|
||||
});
|
||||
PocketOverlay.shutdown();
|
||||
|
@ -277,7 +282,7 @@ var SaveToPocket = {
|
|||
// If we don't have this, there's also no possibility of there being a reader
|
||||
// mode tab already loaded. We'll get an Reader:OnSetup message when that happens.
|
||||
if (this._readerButtonData.title) {
|
||||
Services.mm.broadcastAsyncMessage(
|
||||
AboutReaderParent.broadcastAsyncMessage(
|
||||
"Reader:AddButton",
|
||||
this._readerButtonData
|
||||
);
|
||||
|
@ -319,9 +324,10 @@ var SaveToPocket = {
|
|||
this._readerButtonData.title = button.getAttribute("tooltiptext");
|
||||
}
|
||||
// Tell the reader about our button.
|
||||
message.target.messageManager.sendAsyncMessage(
|
||||
message.target.sendMessageToActor(
|
||||
"Reader:AddButton",
|
||||
this._readerButtonData
|
||||
this._readerButtonData,
|
||||
"AboutReader"
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -46,8 +46,8 @@ ChromeUtils.defineModuleGetter(
|
|||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"ReaderParent",
|
||||
"resource:///modules/ReaderParent.jsm"
|
||||
"AboutReaderParent",
|
||||
"resource:///actors/AboutReaderParent.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
|
@ -662,14 +662,14 @@ var UITour = {
|
|||
}
|
||||
|
||||
case "forceShowReaderIcon": {
|
||||
ReaderParent.forceShowReaderIcon(browser);
|
||||
AboutReaderParent.forceShowReaderIcon(browser);
|
||||
break;
|
||||
}
|
||||
|
||||
case "toggleReaderMode": {
|
||||
let targetPromise = this.getTarget(window, "readerMode-urlBar");
|
||||
targetPromise.then(target => {
|
||||
ReaderParent.toggleReaderMode({ target: target.node });
|
||||
AboutReaderParent.toggleReaderMode({ target: target.node });
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -79,9 +79,6 @@ with Files("PermissionUI.jsm"):
|
|||
with Files("ProcessHangMonitor.jsm"):
|
||||
BUG_COMPONENT = ("Core", "DOM: Content Processes")
|
||||
|
||||
with Files("ReaderParent.jsm"):
|
||||
BUG_COMPONENT = ("Toolkit", "Reader Mode")
|
||||
|
||||
with Files("Sanitizer.jsm"):
|
||||
BUG_COMPONENT = ("Firefox", "Preferences")
|
||||
|
||||
|
@ -145,7 +142,6 @@ EXTRA_JS_MODULES += [
|
|||
'PermissionUI.jsm',
|
||||
'PingCentre.jsm',
|
||||
'ProcessHangMonitor.jsm',
|
||||
'ReaderParent.jsm',
|
||||
'Sanitizer.jsm',
|
||||
'SelectionChangedMenulist.jsm',
|
||||
'SiteDataManager.jsm',
|
||||
|
|
|
@ -21,8 +21,7 @@ var gStrings = Services.strings.createBundle(
|
|||
"chrome://global/locale/narrate.properties"
|
||||
);
|
||||
|
||||
function NarrateControls(mm, win, languagePromise) {
|
||||
this._mm = mm;
|
||||
function NarrateControls(win, languagePromise) {
|
||||
this._winRef = Cu.getWeakReference(win);
|
||||
this._languagePromise = languagePromise;
|
||||
|
||||
|
|
|
@ -47,7 +47,8 @@ const zoomOnMeta =
|
|||
const gIsFirefoxDesktop =
|
||||
Services.appinfo.ID == "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
|
||||
|
||||
var AboutReader = function(mm, win, articlePromise) {
|
||||
var AboutReader = function(actor, articlePromise) {
|
||||
let win = actor.contentWindow;
|
||||
let url = this._getOriginalUrl(win);
|
||||
if (!(url.startsWith("http://") || url.startsWith("https://"))) {
|
||||
let errorMsg =
|
||||
|
@ -62,14 +63,7 @@ var AboutReader = function(mm, win, articlePromise) {
|
|||
|
||||
let doc = win.document;
|
||||
|
||||
this._mm = mm;
|
||||
this._mm.addMessageListener("Reader:CloseDropdown", this);
|
||||
this._mm.addMessageListener("Reader:AddButton", this);
|
||||
this._mm.addMessageListener("Reader:RemoveButton", this);
|
||||
this._mm.addMessageListener("Reader:GetStoredArticleData", this);
|
||||
this._mm.addMessageListener("Reader:ZoomIn", this);
|
||||
this._mm.addMessageListener("Reader:ZoomOut", this);
|
||||
this._mm.addMessageListener("Reader:ResetZoom", this);
|
||||
this._actor = actor;
|
||||
|
||||
this._docRef = Cu.getWeakReference(doc);
|
||||
this._winRef = Cu.getWeakReference(win);
|
||||
|
@ -136,7 +130,7 @@ var AboutReader = function(mm, win, articlePromise) {
|
|||
|
||||
if (gIsFirefoxDesktop) {
|
||||
// we're ready for any external setup, send a signal for that.
|
||||
this._mm.sendAsyncMessage("Reader:OnSetup");
|
||||
this._actor.sendAsyncMessage("Reader:OnSetup");
|
||||
}
|
||||
|
||||
let colorSchemeValues = JSON.parse(
|
||||
|
@ -193,7 +187,7 @@ var AboutReader = function(mm, win, articlePromise) {
|
|||
this._setupLineHeightButtons();
|
||||
|
||||
if (win.speechSynthesis && Services.prefs.getBoolPref("narrate.enabled")) {
|
||||
new NarrateControls(mm, win, this._languagePromise);
|
||||
new NarrateControls(win, this._languagePromise);
|
||||
}
|
||||
|
||||
this._loadArticle();
|
||||
|
@ -292,26 +286,8 @@ AboutReader.prototype = {
|
|||
));
|
||||
},
|
||||
|
||||
// Provides unique view Id.
|
||||
get viewId() {
|
||||
let _viewId = Cc["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Ci.nsIUUIDGenerator)
|
||||
.generateUUID()
|
||||
.toString();
|
||||
Object.defineProperty(this, "viewId", { value: _viewId });
|
||||
|
||||
return _viewId;
|
||||
},
|
||||
|
||||
receiveMessage(message) {
|
||||
switch (message.name) {
|
||||
// Triggered by Android user pressing BACK while the banner font-dropdown is open.
|
||||
case "Reader:CloseDropdown": {
|
||||
// Just close it.
|
||||
this._closeDropdowns();
|
||||
break;
|
||||
}
|
||||
|
||||
case "Reader:AddButton": {
|
||||
if (
|
||||
message.data.id &&
|
||||
|
@ -334,7 +310,7 @@ AboutReader.prototype = {
|
|||
let tb = this._toolbarElement;
|
||||
tb.appendChild(btn);
|
||||
this._setupButton(message.data.id, button => {
|
||||
this._mm.sendAsyncMessage(
|
||||
this._actor.sendAsyncMessage(
|
||||
"Reader:Clicked-" + button.dataset.buttonid,
|
||||
{ article: this._article }
|
||||
);
|
||||
|
@ -351,12 +327,6 @@ AboutReader.prototype = {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case "Reader:GetStoredArticleData": {
|
||||
this._mm.sendAsyncMessage("Reader:StoredArticleData", {
|
||||
article: this._article,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "Reader:ZoomIn": {
|
||||
this._changeFontSize(+1);
|
||||
break;
|
||||
|
@ -405,7 +375,6 @@ AboutReader.prototype = {
|
|||
}
|
||||
|
||||
let isScrollingUp = this._scrollOffset > vv.pageTop;
|
||||
this._setSystemUIVisibility(isScrollingUp);
|
||||
this._setToolbarVisibility(isScrollingUp);
|
||||
}
|
||||
|
||||
|
@ -464,35 +433,18 @@ AboutReader.prototype = {
|
|||
// Close the Banners Font-dropdown, cleanup Android BackPressListener.
|
||||
this._closeDropdowns();
|
||||
|
||||
this._mm.removeMessageListener("Reader:CloseDropdown", this);
|
||||
this._mm.removeMessageListener("Reader:AddButton", this);
|
||||
this._mm.removeMessageListener("Reader:RemoveButton", this);
|
||||
this._mm.removeMessageListener("Reader:GetStoredArticleData", this);
|
||||
this._mm.removeMessageListener("Reader:ZoomIn", this);
|
||||
this._mm.removeMessageListener("Reader:ZoomOut", this);
|
||||
this._mm.removeMessageListener("Reader:ResetZoom", this);
|
||||
this._windowUnloaded = true;
|
||||
this._actor.readerModeHidden();
|
||||
this.clearActor();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
observe(subject, topic, data) {
|
||||
if (
|
||||
subject.QueryInterface(Ci.nsISupportsPRUint64).data != this._innerWindowId
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
|
||||
this._mm.removeMessageListener("Reader:CloseDropdown", this);
|
||||
this._mm.removeMessageListener("Reader:AddButton", this);
|
||||
this._mm.removeMessageListener("Reader:RemoveButton", this);
|
||||
this._windowUnloaded = true;
|
||||
clearActor() {
|
||||
this._actor = null;
|
||||
},
|
||||
|
||||
_onReaderClose() {
|
||||
ReaderMode.leaveReaderMode(this._mm.docShell, this._win);
|
||||
ReaderMode.leaveReaderMode(this._actor.docShell, this._win);
|
||||
},
|
||||
|
||||
async _resetFontSize() {
|
||||
|
@ -858,10 +810,6 @@ AboutReader.prototype = {
|
|||
AsyncPrefs.set("reader.font_type", this._fontType);
|
||||
},
|
||||
|
||||
_setSystemUIVisibility(visible) {
|
||||
this._mm.sendAsyncMessage("Reader:SystemUIVisibility", { visible });
|
||||
},
|
||||
|
||||
_setToolbarVisibility(visible) {
|
||||
let tb = this._toolbarElement;
|
||||
|
||||
|
@ -893,7 +841,7 @@ AboutReader.prototype = {
|
|||
article = await this._articlePromise;
|
||||
} else {
|
||||
try {
|
||||
article = await this._getArticle(url);
|
||||
article = await ReaderMode.downloadAndParseDocument(url);
|
||||
} catch (e) {
|
||||
if (e && e.newURL) {
|
||||
let readerURL = "about:reader?url=" + encodeURIComponent(e.newURL);
|
||||
|
@ -903,7 +851,7 @@ AboutReader.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
if (this._windowUnloaded) {
|
||||
if (!this._actor) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -918,38 +866,15 @@ AboutReader.prototype = {
|
|||
this._showContent(article);
|
||||
},
|
||||
|
||||
_getArticle(url) {
|
||||
if (this.PLATFORM_HAS_CACHE) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let listener = message => {
|
||||
this._mm.removeMessageListener("Reader:ArticleData", listener);
|
||||
if (message.data.newURL) {
|
||||
reject({ newURL: message.data.newURL });
|
||||
return;
|
||||
}
|
||||
resolve(message.data.article);
|
||||
};
|
||||
this._mm.addMessageListener("Reader:ArticleData", listener);
|
||||
this._mm.sendAsyncMessage("Reader:ArticleGet", { url });
|
||||
});
|
||||
}
|
||||
return ReaderMode.downloadAndParseDocument(url);
|
||||
},
|
||||
|
||||
_requestFavicon() {
|
||||
let handleFaviconReturn = message => {
|
||||
this._mm.removeMessageListener(
|
||||
"Reader:FaviconReturn",
|
||||
handleFaviconReturn
|
||||
);
|
||||
this._loadFavicon(message.data.url, message.data.faviconUrl);
|
||||
};
|
||||
|
||||
this._mm.addMessageListener("Reader:FaviconReturn", handleFaviconReturn);
|
||||
this._mm.sendAsyncMessage("Reader:FaviconRequest", {
|
||||
async _requestFavicon() {
|
||||
let iconDetails = await this._actor.sendQuery("Reader:FaviconRequest", {
|
||||
url: this._article.url,
|
||||
preferredWidth: 16 * this._win.devicePixelRatio,
|
||||
});
|
||||
|
||||
if (iconDetails) {
|
||||
this._loadFavicon(iconDetails.url, iconDetails.faviconUrl);
|
||||
}
|
||||
},
|
||||
|
||||
_loadFavicon(url, faviconUrl) {
|
||||
|
@ -1134,7 +1059,7 @@ AboutReader.prototype = {
|
|||
// No need to show progress if the article has been loaded,
|
||||
// if the window has been unloaded, or if there was an error
|
||||
// trying to load the article.
|
||||
if (this._article || this._windowUnloaded || this._error) {
|
||||
if (this._article || !this._actor || this._error) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1300,7 +1225,6 @@ AboutReader.prototype = {
|
|||
|
||||
// Trigger BackPressListener initialization in Android.
|
||||
dropdown.classList.add("open");
|
||||
this._mm.sendAsyncMessage("Reader:DropdownOpened", this.viewId);
|
||||
},
|
||||
|
||||
/*
|
||||
|
@ -1318,11 +1242,6 @@ AboutReader.prototype = {
|
|||
for (let dropdown of openDropdowns) {
|
||||
dropdown.classList.remove("open");
|
||||
}
|
||||
|
||||
// Trigger BackPressListener cleanup in Android.
|
||||
if (openDropdowns.length) {
|
||||
this._mm.sendAsyncMessage("Reader:DropdownClosed", this.viewId);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
<meta content="text/html; charset=UTF-8" http-equiv="content-type" />
|
||||
<meta name="viewport" content="width=device-width; user-scalable=0" />
|
||||
<link rel="stylesheet" href="chrome://global/skin/aboutReader.css" type="text/css"/>
|
||||
<script src="chrome://global/content/reader/aboutReader.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
/* 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";
|
||||
|
||||
window.addEventListener("DOMContentLoaded", function() {
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("AboutReaderContentLoaded", { bubbles: true })
|
||||
);
|
||||
});
|
|
@ -4,4 +4,3 @@
|
|||
|
||||
toolkit.jar:
|
||||
content/global/reader/aboutReader.html (content/aboutReader.html)
|
||||
content/global/reader/aboutReader.js (content/aboutReader.js)
|
||||
|
|
|
@ -8,6 +8,10 @@ support-files =
|
|||
[browser_readerMode_hidden_nodes.js]
|
||||
support-files =
|
||||
readerModeArticleHiddenNodes.html
|
||||
[browser_readerMode_pocket.js]
|
||||
support-files =
|
||||
readerModeArticleShort.html
|
||||
readerModeArticleMedium.html
|
||||
[browser_readerMode_with_anchor.js]
|
||||
skip-if = fission # Bug 1616805
|
||||
support-files =
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// This test verifies that the Save To Pocket button appears in reader mode,
|
||||
// and is toggled hidden and visible when pocket is disabled and enabled.
|
||||
|
||||
const TEST_PATH = getRootDirectory(gTestPath).replace(
|
||||
"chrome://mochitests/content",
|
||||
"http://example.com"
|
||||
);
|
||||
|
||||
async function getPocketButtonsCount(browser) {
|
||||
return SpecialPowers.spawn(browser, [], () => {
|
||||
return content.document.getElementsByClassName("pocket-button").length;
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
// set the pocket preference before beginning.
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.pocket.enabled", true]],
|
||||
});
|
||||
|
||||
var readerButton = document.getElementById("reader-mode-button");
|
||||
|
||||
let tab1 = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
TEST_PATH + "readerModeArticleShort.html"
|
||||
);
|
||||
|
||||
let promiseTabLoad = promiseTabLoadEvent(tab1);
|
||||
readerButton.click();
|
||||
await promiseTabLoad;
|
||||
|
||||
let tab2 = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
TEST_PATH + "readerModeArticleMedium.html"
|
||||
);
|
||||
|
||||
promiseTabLoad = promiseTabLoadEvent(tab2);
|
||||
readerButton.click();
|
||||
await promiseTabLoad;
|
||||
|
||||
is(
|
||||
await getPocketButtonsCount(tab1.linkedBrowser),
|
||||
1,
|
||||
"tab 1 has a pocket button"
|
||||
);
|
||||
is(
|
||||
await getPocketButtonsCount(tab1.linkedBrowser),
|
||||
1,
|
||||
"tab 2 has a pocket button"
|
||||
);
|
||||
|
||||
// Turn off the pocket preference. The Save To Pocket buttons should disappear.
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.pocket.enabled", false]],
|
||||
});
|
||||
|
||||
is(
|
||||
await getPocketButtonsCount(tab1.linkedBrowser),
|
||||
0,
|
||||
"tab 1 has no pocket button"
|
||||
);
|
||||
is(
|
||||
await getPocketButtonsCount(tab1.linkedBrowser),
|
||||
0,
|
||||
"tab 2 has no pocket button"
|
||||
);
|
||||
|
||||
// Turn on the pocket preference. The Save To Pocket buttons should reappear again.
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.pocket.enabled", true]],
|
||||
});
|
||||
|
||||
is(
|
||||
await getPocketButtonsCount(tab1.linkedBrowser),
|
||||
1,
|
||||
"tab 1 has a pocket button again"
|
||||
);
|
||||
is(
|
||||
await getPocketButtonsCount(tab1.linkedBrowser),
|
||||
1,
|
||||
"tab 2 has a pocket button again"
|
||||
);
|
||||
|
||||
BrowserTestUtils.removeTab(tab1);
|
||||
BrowserTestUtils.removeTab(tab2);
|
||||
});
|
Загрузка…
Ссылка в новой задаче