commit 7719a132533d0e245602b9aee496875a8cb03cd5 Author: Kathy Brade brade@pearlcrescent.com Date: Wed Jan 17 14:01:51 2018 -0500
fixup! Bug 16940: After update, load local change notes.
Always load about:tbupdate in a content process. To improve compatiblity with future sandboxing efforts, relocate the code that accesses the file system (changelog) to the chrome process. Avoid using a query string to pass the "more info" link to the about:tbupdate page. Remove obsolete flag nsIAboutModule::MAKE_UNLINKABLE (about: pages are unlinkable by default). --- browser/base/content/browser.js | 22 +++-- browser/base/content/tab-content.js | 104 ++++++++---------------- browser/base/jar.mn | 2 +- browser/base/moz.build | 3 + browser/components/about/AboutRedirector.cpp | 2 +- browser/components/nsBrowserContentHandler.js | 5 +- browser/components/nsBrowserGlue.js | 9 +++ browser/modules/AboutTBUpdate.jsm | 111 ++++++++++++++++++++++++++ browser/modules/moz.build | 5 ++ toolkit/modules/AppConstants.jsm | 7 ++ toolkit/modules/moz.build | 3 + 11 files changed, 186 insertions(+), 87 deletions(-)
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 5c0d9a4d7161..5eabd3373b71 100755 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -215,9 +215,6 @@ this.__defineSetter__("AddonManager", function (val) {
var gInitialPages = [ "about:tor", -#ifdef TOR_BROWSER_UPDATE - "about:tbupdate", -#endif "about:blank", "about:newtab", "about:home", @@ -225,6 +222,9 @@ var gInitialPages = [ "about:welcomeback", "about:sessionrestore" ]; +if (AppConstants.TOR_BROWSER_UPDATE) { + gInitialPages.push("about:tbupdate"); +}
function* browserWindows() { let windows = Services.wm.getEnumerator("navigator:browser"); @@ -2420,13 +2420,8 @@ function URLBarSetURI(aURI) { // 2. if remote newtab is enabled and it's the default remote newtab page let defaultRemoteURL = gAboutNewTabService.remoteEnabled && uri.spec === gAboutNewTabService.newTabURL; -#ifdef TOR_BROWSER_UPDATE - if ((gInitialPages.includes(uri.spec.split('?')[0]) || defaultRemoteURL) && - checkEmptyPageOrigin(gBrowser.selectedBrowser, uri)) -#else if ((gInitialPages.includes(uri.spec) || defaultRemoteURL) && checkEmptyPageOrigin(gBrowser.selectedBrowser, uri)) -#endif { value = ""; } else { @@ -7453,11 +7448,12 @@ var gIdentityHandler = { this._uriHasHost = false; }
-#ifdef TOR_BROWSER_UPDATE - let whitelist = /^(?:accounts|addons|cache|config|crashes|customizing|downloads|healthreport|home|license|newaddon|permissions|preferences|privatebrowsing|rights|searchreset|sessionrestore|support|welcomeback|tor|tbupdate)(?:[?#]|$)/i; -#else - let whitelist = /^(?:accounts|addons|cache|config|crashes|customizing|downloads|healthreport|home|license|newaddon|permissions|preferences|privatebrowsing|rights|searchreset|sessionrestore|support|welcomeback|tor)(?:[?#]|$)/i; -#endif + let whitelist; + if (AppConstants.TOR_BROWSER_UPDATE) { + whitelist = /^(?:accounts|addons|cache|config|crashes|customizing|downloads|healthreport|home|license|newaddon|permissions|preferences|privatebrowsing|rights|searchreset|sessionrestore|support|welcomeback|tor|tbupdate)(?:[?#]|$)/i; + } else { + whitelist = /^(?:accounts|addons|cache|config|crashes|customizing|downloads|healthreport|home|license|newaddon|permissions|preferences|privatebrowsing|rights|searchreset|sessionrestore|support|welcomeback|tor)(?:[?#]|$)/i; + } this._isSecureInternalUI = uri.schemeIs("about") && whitelist.test(uri.path);
// Create a channel for the sole purpose of getting the resolved URI diff --git a/browser/base/content/tab-content.js b/browser/base/content/tab-content.js index d7d565ec50de..9aefa567fbae 100644 --- a/browser/base/content/tab-content.js +++ b/browser/base/content/tab-content.js @@ -5,19 +5,11 @@
/* This content script contains code that requires a tab browser. */
-#ifdef TOR_BROWSER_VERSION -# Add double-quotes back on (stripped by JarMaker.py). -#expand const TOR_BROWSER_VERSION = "__TOR_BROWSER_VERSION__"; -#endif - var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/ExtensionContent.jsm"); -#ifdef TOR_BROWSER_UPDATE -Cu.import("resource://gre/modules/NetUtil.jsm"); -#endif
XPCOMUtils.defineLazyModuleGetter(this, "E10SUtils", "resource:///modules/E10SUtils.jsm"); @@ -408,80 +400,50 @@ let AboutTBUpdateListener = { },
get isAboutTBUpdate() { - return content.document.documentURI.split('?')[0].toLowerCase() - == "about:tbupdate"; + return content.document.documentURI.toLowerCase() == "about:tbupdate"; },
handleEvent: function(aEvent) { - if (this.isAboutTBUpdate && (aEvent.type == "AboutTBUpdateLoad")) - this.onPageLoad(); - }, + if (!this.isAboutTBUpdate) + return;
- onPageLoad: function() { - let doc = content.document; - doc.getElementById("infolink").setAttribute("href", this.getPostUpdateURL()); - doc.getElementById("changelog").textContent = this.getChangeLogText(); - - const kBrandBundle = "chrome://branding/locale/brand.properties"; - let brandBundle = Cc["@mozilla.org/intl/stringbundle;1"] - .getService(Ci.nsIStringBundleService) - .createBundle(kBrandBundle); - let productName = brandBundle.GetStringFromName("brandFullName"); - doc.getElementById("torbrowser-version").textContent = productName + "\n" - + TOR_BROWSER_VERSION; + switch (aEvent.type) { + case "AboutTBUpdateLoad": + this.onPageLoad(); + break; + case "pagehide": + this.onPageHide(aEvent); + break; + } },
- // Extract the post update URL from this page's query string. - getPostUpdateURL: function() { - let idx = content.document.documentURI.indexOf('?'); - if (idx > 0) - return decodeURIComponent(content.document.documentURI.substring(idx+1)); - - // No query string: use the default URL. - return Services.urlFormatter.formatURLPref("startup.homepage_override_url"); + receiveMessage: function(aMessage) { + if (this.isAboutTBUpdate && (aMessage.name == "AboutTBUpdate:Update")) + this.onUpdate(aMessage.data); },
- // Read and return the text from the beginning of the changelog file that is - // located at TorBrowser/Docs/ChangeLog.txt. - // On Mac OS, when building with --enable-tor-browser-data-outside-app-dir - // to support Gatekeeper signing, the file is located in - // TorBrowser.app/Contents/Resources/TorBrowser/Docs/. - // - // When electrolysis is enabled we will need to adopt an architecture that is - // more similar to the one that is used for about:home (see AboutHomeListener - // in this file and browser/modules/AboutHome.jsm). - getChangeLogText: function() { - try { -#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR - // "XREExeF".parent is the directory that contains firefox, i.e., - // Browser/ or, on Mac OS, TorBrowser.app/Contents/MacOS/. - let f = Services.dirsvc.get("XREExeF", Ci.nsIFile).parent; -#ifdef XP_MACOSX - f = f.parent; - f.append("Resources"); -#endif - f.append("TorBrowser"); -#else - // "DefProfRt" is .../TorBrowser/Data/Browser - let f = Cc["@mozilla.org/file/directory_service;1"] - .getService(Ci.nsIProperties).get("DefProfRt", Ci.nsIFile); - f = f.parent.parent; // Remove "Data/Browser" -#endif - f.append("Docs"); - f.append("ChangeLog.txt"); - - let fs = Cc["@mozilla.org/network/file-input-stream;1"] - .createInstance(Ci.nsIFileInputStream); - fs.init(f, -1, 0, 0); - let s = NetUtil.readInputStreamToString(fs, fs.available()); - fs.close(); + onUpdate: function(aData) { + let doc = content.document; + doc.getElementById("torbrowser-version").textContent = aData.productInfo; + if (aData.moreInfoURL) + doc.getElementById("infolink").setAttribute("href", aData.moreInfoURL); + doc.getElementById("changelog").textContent = aData.changeLog; + },
- // Truncate at the first empty line. - return s.replace(/[\r\n][\r\n][\s\S]*$/m, ""); - } catch (e) {} + onPageLoad: function() { + addMessageListener("AboutTBUpdate:Update", this); + addEventListener("pagehide", this, true); + sendAsyncMessage("AboutTBUpdate:RequestUpdate"); + },
- return ""; + onPageHide: function(aEvent) { + if (aEvent.target.defaultView.frameElement) { + return; + } + removeMessageListener("AboutTBUpdate:Update", this); + removeEventListener("pagehide", this, true); }, + }; AboutTBUpdateListener.init(this); #endif diff --git a/browser/base/jar.mn b/browser/base/jar.mn index 2b0f744b42cb..9d2f100a9717 100644 --- a/browser/base/jar.mn +++ b/browser/base/jar.mn @@ -75,7 +75,7 @@ browser.jar: content/browser/abouttbupdate/aboutTBUpdateLogo.png (content/abouttbupdate/aboutTBUpdateLogo.png) #endif * content/browser/browser.css (content/browser.css) -* content/browser/browser.js (content/browser.js) + content/browser/browser.js (content/browser.js) * content/browser/browser.xul (content/browser.xul) content/browser/browser-addons.js (content/browser-addons.js) content/browser/browser-captivePortal.js (content/browser-captivePortal.js) diff --git a/browser/base/moz.build b/browser/base/moz.build index 46634999261c..dc15e2902bb8 100644 --- a/browser/base/moz.build +++ b/browser/base/moz.build @@ -47,4 +47,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'): if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'): DEFINES['MENUBAR_CAN_AUTOHIDE'] = 1
+if CONFIG['TOR_BROWSER_UPDATE']: + DEFINES['TOR_BROWSER_UPDATE'] = 1 + JAR_MANIFESTS += ['jar.mn'] diff --git a/browser/components/about/AboutRedirector.cpp b/browser/components/about/AboutRedirector.cpp index 016d75cb68c7..364f78d46957 100644 --- a/browser/components/about/AboutRedirector.cpp +++ b/browser/components/about/AboutRedirector.cpp @@ -107,8 +107,8 @@ static RedirEntry kRedirMap[] = { #ifdef TOR_BROWSER_UPDATE { "tbupdate", "chrome://browser/content/abouttbupdate/aboutTBUpdate.xhtml", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | + nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | - nsIAboutModule::MAKE_UNLINKABLE | nsIAboutModule::HIDE_FROM_ABOUTABOUT }, #endif }; diff --git a/browser/components/nsBrowserContentHandler.js b/browser/components/nsBrowserContentHandler.js index ee0c6a5a4a7a..583010e937ed 100644 --- a/browser/components/nsBrowserContentHandler.js +++ b/browser/components/nsBrowserContentHandler.js @@ -576,7 +576,10 @@ nsBrowserContentHandler.prototype = {
#ifdef TOR_BROWSER_UPDATE if (overridePage) - overridePage = "about:tbupdate?" + encodeURIComponent(overridePage); + { + prefb.setCharPref("torbrowser.post_update.url", overridePage); + overridePage = "about:tbupdate" + } #endif break; } diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index bb2351d41014..562ca20e19a4 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -78,6 +78,11 @@ if (AppConstants.MOZ_CRASHREPORTER) { "resource://gre/modules/CrashSubmit.jsm"); }
+if (AppConstants.TOR_BROWSER_UPDATE) { + XPCOMUtils.defineLazyModuleGetter(this, "AboutTBUpdate", + "resource:///modules/AboutTBUpdate.jsm"); +} + XPCOMUtils.defineLazyGetter(this, "gBrandBundle", function() { return Services.strings.createBundle('chrome://branding/locale/brand.properties'); }); @@ -714,6 +719,10 @@ BrowserGlue.prototype = { UnsubmittedCrashHandler.init(); }
+ if (AppConstants.TOR_BROWSER_UPDATE) { + AboutTBUpdate.init(); + } + Services.obs.notifyObservers(null, "browser-ui-startup-complete", ""); },
diff --git a/browser/modules/AboutTBUpdate.jsm b/browser/modules/AboutTBUpdate.jsm new file mode 100644 index 000000000000..49d9d9b0e18d --- /dev/null +++ b/browser/modules/AboutTBUpdate.jsm @@ -0,0 +1,111 @@ +// Copyright (c) 2018, The Tor Project, Inc. +// See LICENSE for licensing information. +// +// vim: set sw=2 sts=2 ts=8 et syntax=javascript: + +"use strict"; + +var Cc = Components.classes; +var Ci = Components.interfaces; +var Cu = Components.utils; + +this.EXPORTED_SYMBOLS = [ "AboutTBUpdate" ]; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); + +const kRequestUpdateMessageName = "AboutTBUpdate:RequestUpdate"; +const kSendUpdateMessageName = "AboutTBUpdate:Update"; + +#ifdef TOR_BROWSER_VERSION +#expand const TOR_BROWSER_VERSION = __TOR_BROWSER_VERSION__; +#endif + +/** + * This code provides services to the about:tbupdate page. Whenever + * about:tbupdate needs to do something chrome-privileged, it sends a + * message that's handled here. It is modeled after Mozilla's about:home + * implementation. + */ +var AboutTBUpdate = { + init: function() { + let mm = Cc["@mozilla.org/globalmessagemanager;1"] + .getService(Ci.nsIMessageListenerManager); + mm.addMessageListener(kRequestUpdateMessageName, this); + }, + + receiveMessage: function(aMessage) { + if (aMessage.name == kRequestUpdateMessageName) + this.sendAboutTBUpdateData(aMessage.target); + }, + + sendAboutTBUpdateData: function(aTarget) { + let data = { productInfo: this.productInfo, + moreInfoURL: this.moreInfoURL, + changeLog: this.changeLog }; + + if (aTarget && aTarget.messageManager) { + aTarget.messageManager.sendAsyncMessage(kSendUpdateMessageName, data); + } else { + let mm = Cc["@mozilla.org/globalmessagemanager;1"] + .getService(Ci.nsIMessageListenerManager); + mm.broadcastAsyncMessage(kSendUpdateMessageName, data); + } + }, + + get productInfo() { + const kBrandBundle = "chrome://branding/locale/brand.properties"; + let brandBundle = Cc["@mozilla.org/intl/stringbundle;1"] + .getService(Ci.nsIStringBundleService) + .createBundle(kBrandBundle); + return brandBundle.GetStringFromName("brandFullName") + + "\n" + TOR_BROWSER_VERSION; + }, + + get moreInfoURL() { + try { + return Services.prefs.getCharPref("torbrowser.post_update.url"); + } catch (e) {} + + // Use the default URL as a fallback. + return Services.urlFormatter.formatURLPref("startup.homepage_override_url"); + }, + + // Read and return the text from the beginning of the changelog file that is + // located at TorBrowser/Docs/ChangeLog.txt. + // On Mac OS, when building with --enable-tor-browser-data-outside-app-dir + // to support Gatekeeper signing, the file is located in + // TorBrowser.app/Contents/Resources/TorBrowser/Docs/. + get changeLog() { + try { +#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR + // "XREExeF".parent is the directory that contains firefox, i.e., + // Browser/ or, on Mac OS, TorBrowser.app/Contents/MacOS/. + let f = Services.dirsvc.get("XREExeF", Ci.nsIFile).parent; +#ifdef XP_MACOSX + f = f.parent; + f.append("Resources"); +#endif + f.append("TorBrowser"); +#else + // "DefProfRt" is .../TorBrowser/Data/Browser + let f = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties).get("DefProfRt", Ci.nsIFile); + f = f.parent.parent; // Remove "Data/Browser" +#endif + f.append("Docs"); + f.append("ChangeLog.txt"); + + let fs = Cc["@mozilla.org/network/file-input-stream;1"] + .createInstance(Ci.nsIFileInputStream); + fs.init(f, -1, 0, 0); + let s = NetUtil.readInputStreamToString(fs, fs.available()); + fs.close(); + + // Truncate at the first empty line. + return s.replace(/[\r\n][\r\n][\s\S]*$/m, ""); + } catch (e) {} + + return ""; + }, +}; diff --git a/browser/modules/moz.build b/browser/modules/moz.build index 2526272249e8..4fe8adeb6c49 100644 --- a/browser/modules/moz.build +++ b/browser/modules/moz.build @@ -52,6 +52,11 @@ if not CONFIG['TOR_BROWSER_VERSION']: 'CastingApps.jsm', ]
+if CONFIG['TOR_BROWSER_UPDATE']: + EXTRA_PP_JS_MODULES += [ + 'AboutTBUpdate.jsm', + ] + if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': EXTRA_JS_MODULES += [ 'Windows8WindowFrameColor.jsm', diff --git a/toolkit/modules/AppConstants.jsm b/toolkit/modules/AppConstants.jsm index 7ce8e1f09af4..82e5753be12a 100644 --- a/toolkit/modules/AppConstants.jsm +++ b/toolkit/modules/AppConstants.jsm @@ -340,4 +340,11 @@ this.AppConstants = Object.freeze({ #else false, #endif + + TOR_BROWSER_UPDATE: +#ifdef TOR_BROWSER_UPDATE + true, +#else + false, +#endif }); diff --git a/toolkit/modules/moz.build b/toolkit/modules/moz.build index 7d4b0f3fa713..6c3d273804fc 100644 --- a/toolkit/modules/moz.build +++ b/toolkit/modules/moz.build @@ -159,4 +159,7 @@ for var in ('MOZ_TOOLKIT_SEARCH', if CONFIG[var]: DEFINES[var] = True
+if CONFIG['TOR_BROWSER_UPDATE']: + DEFINES['TOR_BROWSER_UPDATE'] = 1 + DEFINES['TOPOBJDIR'] = TOPOBJDIR
tbb-commits@lists.torproject.org