diff --git a/browser/actors/AboutReaderParent.jsm b/browser/actors/AboutReaderParent.jsm index 9e1050737d1d..4f66b07904ed 100644 --- a/browser/actors/AboutReaderParent.jsm +++ b/browser/actors/AboutReaderParent.jsm @@ -201,6 +201,13 @@ class AboutReaderParent extends JSWindowActorParent { break; } + case "RedirectTo": { + gCachedArticles.set(message.data.newURL, message.data.article); + // This is setup as a query so we can navigate the page after we've + // cached the relevant info in the parent. + return true; + } + default: this.callListeners(message); break; diff --git a/toolkit/components/reader/AboutReader.jsm b/toolkit/components/reader/AboutReader.jsm index 026f70fa98ff..a5e9e942d089 100644 --- a/toolkit/components/reader/AboutReader.jsm +++ b/toolkit/components/reader/AboutReader.jsm @@ -837,7 +837,12 @@ AboutReader.prototype = { docContentType ); } catch (e) { - if (e && e.newURL) { + if (e?.newURL && this._actor) { + await this._actor.sendQuery("RedirectTo", { + newURL: e.newURL, + article: e.article, + }); + let readerURL = "about:reader?url=" + encodeURIComponent(e.newURL); this._win.location.replace(readerURL); return; diff --git a/toolkit/components/reader/ReaderMode.jsm b/toolkit/components/reader/ReaderMode.jsm index 2d8f4316131b..a07ea64247ba 100644 --- a/toolkit/components/reader/ReaderMode.jsm +++ b/toolkit/components/reader/ReaderMode.jsm @@ -135,7 +135,7 @@ var ReaderMode = { }); let url = win.document.location.href; - let originalURL = ReaderMode.getOriginalUrl(url); + let originalURL = this.getOriginalUrl(url); let webNav = docShell.QueryInterface(Ci.nsIWebNavigation); if (!Services.appinfo.sessionHistoryInParent) { @@ -219,7 +219,7 @@ var ReaderMode = { }, getOriginalUrlObjectForDisplay(url) { - let originalUrl = ReaderMode.getOriginalUrl(url); + let originalUrl = this.getOriginalUrl(url); if (originalUrl) { let uriObj; try { @@ -264,10 +264,12 @@ var ReaderMode = { * @resolves JS object representing the article, or null if no article is found. */ async downloadAndParseDocument(url, docContentType = "document") { - let doc = await this._downloadDocument(url, docContentType); - if (!doc) { + let result = await this._downloadDocument(url, docContentType); + if (!result?.doc) { return null; - } else if ( + } + let { doc, newURL } = result; + if ( !Readerable.shouldCheckUri(doc.documentURIObject) || !Readerable.shouldCheckUri(doc.baseURIObject, true) ) { @@ -275,7 +277,14 @@ var ReaderMode = { return null; } - return this._readerParse(doc); + let article = await this._readerParse(doc); + // If we have to redirect, reject to the caller with the parsed article, + // so we can update the URL before displaying it. + if (newURL) { + return Promise.reject({ newURL, article }); + } + // Otherwise, we can just continue with the article. + return article; }, _downloadDocument(url, docContentType = "document") { @@ -312,78 +321,37 @@ var ReaderMode = { return; } - if (xhr.responseType === "document") { - // Manually follow a meta refresh tag if one exists. - let meta = doc.querySelector("meta[http-equiv=refresh]"); - if (meta) { - let content = meta.getAttribute("content"); - if (content) { - let urlIndex = content.toUpperCase().indexOf("URL="); - if (urlIndex > -1) { - let baseURI = Services.io.newURI(url); - let newURI = Services.io.newURI( - content.substring(urlIndex + 4), - null, - baseURI - ); - let newURL = newURI.spec; - let ssm = Services.scriptSecurityManager; - let flags = - ssm.LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT | - ssm.DISALLOW_INHERIT_PRINCIPAL; - try { - ssm.checkLoadURIStrWithPrincipal( - doc.nodePrincipal, - newURL, - flags - ); - } catch (ex) { - let errorMsg = - "Reader mode disallowed meta refresh (reason: " + ex + ")."; - - if (Services.prefs.getBoolPref("reader.errors.includeURLs")) { - errorMsg += " Refresh target URI: '" + newURL + "'."; - } - reject(errorMsg); - return; - } - // Otherwise, pass an object indicating our new URL: - if (!baseURI.equalsExceptRef(newURI)) { - reject({ newURL }); - return; - } - } - } - } - let responseURL = xhr.responseURL; - let givenURL = url; - // Convert these to real URIs to make sure the escaping (or lack - // thereof) is identical: - try { - responseURL = Services.io.newURI(responseURL).specIgnoringRef; - } catch (ex) { - /* Ignore errors - we'll use what we had before */ - } - try { - givenURL = Services.io.newURI(givenURL).specIgnoringRef; - } catch (ex) { - /* Ignore errors - we'll use what we had before */ - } - - if (responseURL != givenURL) { - // We were redirected without a meta refresh tag. - // Force redirect to the correct place: - reject({ newURL: xhr.responseURL }); - return; - } - } else { - let parser = new DOMParser(); - let htmlString = `
${doc}
`; - doc = parser.parseFromString(htmlString, "text/html"); + let responseURL = xhr.responseURL; + let givenURL = url; + // Convert these to real URIs to make sure the escaping (or lack + // thereof) is identical: + try { + responseURL = Services.io.newURI(responseURL).specIgnoringRef; + } catch (ex) { + /* Ignore errors - we'll use what we had before */ + } + try { + givenURL = Services.io.newURI(givenURL).specIgnoringRef; + } catch (ex) { + /* Ignore errors - we'll use what we had before */ } - resolve(doc); + if (xhr.responseType != "document") { + let initialText = doc; + let parser = new DOMParser(); + doc = parser.parseFromString(`
`, "text/html");
+          doc.querySelector("pre").textContent = initialText;
+        }
+
+        // We treat redirects as download successes here:
         histogram.add(DOWNLOAD_SUCCESS);
+
+        let result = { doc };
+        if (responseURL != givenURL) {
+          result.newURL = xhr.responseURL;
+        }
+
+        resolve(result);
       };
       xhr.send();
     });