Bug 782453 - Add site-specific User Agent infrastructure and use it to fix AOL Mail. r=bz,ehsan sr=gerv
☠☠ backed out by c72b90b1c8d2 ☠ ☠
authorDão Gottwald <dao@mozilla.com>
Wed, 29 Aug 2012 08:03:24 +0200
changeset 105730 418955e7c3a95f72f9f2ca994de188d65a80e7b0
parent 105729 0eebcc79ee058a6f01e76487df88b524f56d179e
child 105731 c72b90b1c8d2b5e7662e93eeca04842aaab92249
child 111046 3818219abd6bbc4a65026b900e0c18ca9f575017
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewersbz, ehsan, gerv
bugs782453
milestone18.0a1
Bug 782453 - Add site-specific User Agent infrastructure and use it to fix AOL Mail. r=bz,ehsan sr=gerv
browser/app/profile/firefox.js
browser/components/nsBrowserGlue.js
modules/libpref/src/init/all.js
netwerk/protocol/http/Makefile.in
netwerk/protocol/http/UserAgentOverrides.jsm
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -217,16 +217,21 @@ pref("general.skins.selectedSkin", "clas
 
 pref("general.smoothScroll", true);
 #ifdef UNIX_BUT_NOT_MAC
 pref("general.autoScroll", false);
 #else
 pref("general.autoScroll", true);
 #endif
 
+// Send aol.com the legacy build date instead of the version number in the UA's
+// Gecko token as a temporary measure against bug 778408 (mail.aol.com defaults
+// to basic web UI when accessed with a user agent without Gecko/20100101).
+pref("general.useragent.override.aol.com", "Gecko/[^ ]*#Gecko/20100101");
+
 // At startup, check if we're the default browser and prompt user if not.
 pref("browser.shell.checkDefaultBrowser", true);
 
 // 0 = blank, 1 = home (browser.startup.homepage), 2 = last visited page, 3 = resume previous browser session
 // The behavior of option 3 is detailed at: http://wiki.mozilla.org/Session_Restore
 pref("browser.startup.page",                1);
 pref("browser.startup.homepage",            "chrome://branding/locale/browserconfig.properties");
 
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -15,16 +15,19 @@ Cu.import("resource://gre/modules/Servic
 Cu.import("resource:///modules/SignInToWebsite.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
                                   "resource://gre/modules/AddonManager.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
                                   "resource://gre/modules/NetUtil.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "UserAgentOverrides",
+                                  "resource://gre/modules/UserAgentOverrides.jsm");
+
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "BookmarkHTMLUtils",
                                   "resource://gre/modules/BookmarkHTMLUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "webappsUI",
                                   "resource:///modules/webappsUI.jsm");
@@ -306,16 +309,17 @@ BrowserGlue.prototype = {
     if (this._isIdleObserver)
       this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
     if (this._isPlacesInitObserver)
       os.removeObserver(this, "places-init-complete");
     if (this._isPlacesLockedObserver)
       os.removeObserver(this, "places-database-locked");
     if (this._isPlacesShutdownObserver)
       os.removeObserver(this, "places-shutdown");
+    UserAgentOverrides.uninit();
     webappsUI.uninit();
     SignInToWebsiteUX.uninit();
   },
 
   _onAppDefaults: function BG__onAppDefaults() {
     // apply distribution customizations (prefs)
     // other customizations are applied in _onProfileStartup()
     this._distributionCustomizer.applyPrefDefaults();
@@ -332,24 +336,21 @@ BrowserGlue.prototype = {
 
     // apply distribution customizations
     // prefs are applied in _onAppDefaults()
     this._distributionCustomizer.applyCustomizations();
 
     // handle any UI migration
     this._migrateUI();
 
-    // Initialize webapps UI
+    UserAgentOverrides.init();
     webappsUI.init();
-
     PageThumbs.init();
     NewTabUtils.init();
-
     SignInToWebsiteUX.init();
-
     PdfJs.init();
 
     Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
   },
 
   // the first browser window has finished initializing
   _onFirstWindowLoaded: function BG__onFirstWindowLoaded() {
 #ifdef XP_WIN
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -19,16 +19,20 @@
  *  - Computed values (e.g. 50 * 1024) don't work.
  */
 
 pref("keyword.URL", "https://www.google.com/search?ie=UTF-8&oe=utf-8&q=");
 pref("keyword.enabled", false);
 pref("general.useragent.locale", "chrome://global/locale/intl.properties");
 pref("general.useragent.compatMode.firefox", false);
 
+// This pref exists only for testing purposes. In order to disable all
+// overrides by default, don't initialize UserAgentOverrides.jsm.
+pref("general.useragent.site_specific_overrides", true);
+
 pref("general.config.obscure_value", 13); // for MCD .cfg files
 
 pref("general.warnOnAboutConfig", true);
 
 // maximum number of dated backups to keep at any time
 pref("browser.bookmarks.max_backups",       5);
 
 pref("browser.cache.disk.enable",           true);
--- a/netwerk/protocol/http/Makefile.in
+++ b/netwerk/protocol/http/Makefile.in
@@ -89,15 +89,19 @@ CPPSRCS = \
 
 LOCAL_INCLUDES = \
   -I$(srcdir)/../../base/src \
   -I$(topsrcdir)/xpcom/ds \
   -I$(topsrcdir)/content/base/src \
   -I$(topsrcdir)/content/events/src \
   $(NULL)
 
+EXTRA_JS_MODULES = \
+  UserAgentOverrides.jsm \
+  $(NULL)
+
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
 DEFINES += -DIMPL_NS_NET
 
 XPIDL_FLAGS += -I$(topsrcdir)/netwerk/base/public
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/http/UserAgentOverrides.jsm
@@ -0,0 +1,74 @@
+/* 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 = [ "UserAgentOverrides" ];
+
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+const PREF_OVERRIDES_ENABLED = "general.useragent.site_specific_overrides";
+
+var gPrefBranch;
+var gOverrides;
+
+var UserAgentOverrides = {
+  init: function uao_init() {
+    gPrefBranch = Services.prefs.getBranch("general.useragent.override.");
+    gPrefBranch.addObserver("", buildOverrides, false);
+
+    Services.prefs.addObserver(PREF_OVERRIDES_ENABLED, buildOverrides, false);
+
+    Services.obs.addObserver(HTTP_on_modify_request, "http-on-modify-request", false);
+
+    buildOverrides();
+  },
+
+  uninit: function uao_uninit() {
+    gPrefBranch.removeObserver("", buildOverrides);
+
+    Services.prefs.removeObserver(PREF_OVERRIDES_ENABLED, buildOverrides);
+
+    Services.obs.removeObserver(HTTP_on_modify_request, "http-on-modify-request");
+  }
+};
+
+function buildOverrides() {
+  gOverrides = {};
+
+  if (!Services.prefs.getBoolPref(PREF_OVERRIDES_ENABLED))
+    return;
+
+  const defaultUA = Cc["@mozilla.org/network/protocol;1?name=http"]
+                      .getService(Ci.nsIHttpProtocolHandler)
+                      .userAgent;
+  let domains = gPrefBranch.getChildList("");
+
+  for (let domain of domains) {
+    let override = gPrefBranch.getCharPref(domain);
+
+    let [search, replace] = override.split("#", 2);
+    if (search && replace) {
+      gOverrides[domain] = defaultUA.replace(new RegExp(search, "g"), replace);
+    } else {
+      gOverrides[domain] = override;
+    }
+  }
+}
+
+function HTTP_on_modify_request(aSubject, aTopic, aData) {
+  let channel = aSubject.QueryInterface(Ci.nsIHttpChannel);
+  let host = channel.URI.asciiHost;
+
+  for (let domain in gOverrides) {
+    if (host == domain ||
+        host.endsWith("." + domain)) {
+      channel.setRequestHeader("User-Agent", gOverrides[domain], false);
+      break;
+    }
+  }
+}