Bug 897221 - Initialize UserAgentUpdates.jsm inside UserAgentOverrides; r=fabrice
authorJim Chen <nchen@mozilla.com>
Mon, 09 Sep 2013 15:47:47 -0400
changeset 146274 a8711da4abee6109bd8d7aa1c8981b7bd0c2f51b
parent 146273 d0938d3591a94c7bb3e222cf34c03246d2fc7a7a
child 146275 88fd66b4944c215a02e1974e0f59259d2ccc138a
push id25251
push userMs2ger@gmail.com
push dateTue, 10 Sep 2013 08:13:39 +0000
treeherdermozilla-central@25bfaa953892 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfabrice
bugs897221
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 897221 - Initialize UserAgentUpdates.jsm inside UserAgentOverrides; r=fabrice
netwerk/protocol/http/UserAgentOverrides.jsm
netwerk/test/mochitests/test_user_agent_overrides.html
--- a/netwerk/protocol/http/UserAgentOverrides.jsm
+++ b/netwerk/protocol/http/UserAgentOverrides.jsm
@@ -5,25 +5,27 @@
 "use strict";
 
 this.EXPORTED_SYMBOLS = [ "UserAgentOverrides" ];
 
 const Ci = Components.interfaces;
 const Cc = Components.classes;
 
 Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource://gre/modules/UserAgentUpdates.jsm");
 
 const PREF_OVERRIDES_ENABLED = "general.useragent.site_specific_overrides";
 const DEFAULT_UA = Cc["@mozilla.org/network/protocol;1?name=http"]
                      .getService(Ci.nsIHttpProtocolHandler)
                      .userAgent;
 const MAX_OVERRIDE_FOR_HOST_CACHE_SIZE = 250;
 
 var gPrefBranch;
 var gOverrides = new Map;
+var gUpdatedOverrides;
 var gOverrideForHostCache = new Map;
 var gInitialized = false;
 var gOverrideFunctions = [
   function (aHttpChannel) UserAgentOverrides.getOverrideForURI(aHttpChannel.URI)
 ];
 
 this.UserAgentOverrides = {
   init: function uao_init() {
@@ -36,46 +38,62 @@ this.UserAgentOverrides = {
     Services.prefs.addObserver(PREF_OVERRIDES_ENABLED, buildOverrides, false);
 
     try {
       Services.obs.addObserver(HTTP_on_modify_request, "http-on-modify-request", false);
     } catch (x) {
       // The http-on-modify-request notification is disallowed in content processes.
     }
 
+    UserAgentUpdates.init(function(overrides) {
+      gOverrideForHostCache.clear();
+      if (overrides) {
+        overrides.get = function(key) this[key];
+      }
+      gUpdatedOverrides = overrides;
+    });
+
     buildOverrides();
     gInitialized = true;
   },
 
   addComplexOverride: function uao_addComplexOverride(callback) {
     gOverrideFunctions.push(callback);
   },
 
   getOverrideForURI: function uao_getOverrideForURI(aURI) {
     if (!gInitialized ||
-        !gOverrides.size ||
+        (!gOverrides.size && !gUpdatedOverrides) ||
         !(aURI instanceof Ci.nsIStandardURL))
       return null;
 
     let host = aURI.asciiHost;
 
     let override = gOverrideForHostCache.get(host);
     if (override !== undefined)
       return override;
 
-    override = null;
+    function findOverride(overrides) {
+      let searchHost = host;
+      let userAgent = overrides.get(searchHost);
 
-    for (let [domain, userAgent] of gOverrides) {
-      if (host == domain ||
-          host.endsWith("." + domain)) {
-        override = userAgent;
-        break;
+      while (!userAgent) {
+        let dot = searchHost.indexOf('.');
+        if (dot === -1) {
+          return null;
+        }
+        searchHost = searchHost.slice(dot + 1);
+        userAgent = overrides.get(searchHost);
       }
+      return userAgent;
     }
 
+    override = (gOverrides.size && findOverride(gOverrides))
+            || (gUpdatedOverrides && findOverride(gUpdatedOverrides));
+
     if (gOverrideForHostCache.size >= MAX_OVERRIDE_FOR_HOST_CACHE_SIZE) {
       gOverrideForHostCache.clear();
     }
     gOverrideForHostCache.set(host, override);
 
     return override;
   },
 
--- a/netwerk/test/mochitests/test_user_agent_overrides.html
+++ b/netwerk/test/mochitests/test_user_agent_overrides.html
@@ -176,30 +176,71 @@ function testInactive(callback) {
       clear: [
         [PREF_OVERRIDES_ENABLED],
         [PREF_OVERRIDES_BRANCH + location.hostname]
       ]
     }, callback);
   });
 }
 
+function testPriority(callback) {
+  // foo.bar.com override should have priority over bar.com override
+  var tests = [
+    ['example.org', 'test1.example.org', 'sub1.test1.example.org'],
+    ['example.org', 'test1.example.org', 'sub2.test1.example.org'],
+    ['example.org', 'test2.example.org', 'sub1.test2.example.org'],
+    ['example.org', 'test2.example.org', 'sub2.test2.example.org'],
+  ];
+  (function nextTest() {
+    var [level0, level1, level2] = tests.shift();
+    var host = 'http://' + level2;
+    SpecialPowers.pushPrefEnv({
+      set: [
+        [PREF_OVERRIDES_ENABLED, true],
+        [PREF_OVERRIDES_BRANCH + level1, UA_WHOLE_OVERRIDE]
+      ]
+    }, function () {
+      // should use first override at this point
+      is(getUA(host),
+        UA_WHOLE_EXPECTED, 'UA not overridden');
+      // add a second override that should be used
+      testUA({
+        domain: level2,
+        override: UA_PARTIAL_OVERRIDE,
+        test_hosts: [host],
+        expected: UA_PARTIAL_EXPECTED
+      }, function () {
+        // add a third override that should not be used
+        testUA({
+          domain: level0,
+          override: UA_PARTIAL_OVERRIDE,
+          test_hosts: [host],
+          expected: UA_WHOLE_EXPECTED
+        }, tests.length ? nextTest : callback);
+      });
+    });
+  })();
+}
+
 function testOverrides(callback) {
   SpecialPowers.pushPrefEnv({
     set: [[PREF_OVERRIDES_ENABLED, true]]
   }, function nextTest() {
     testUA(tests.shift(), function () tests.length ? nextTest() : callback());
   });
 }
 
 SpecialPowers.Cu.import('resource://gre/modules/UserAgentOverrides.jsm', window);
 SpecialPowers.wrap(UserAgentOverrides).init();
 
 SimpleTest.waitForExplicitFinish();
 
 testOverrides(function ()
-  testInactive(SimpleTest.finish)
+  testInactive(function ()
+    testPriority(SimpleTest.finish)
+  )
 );
 
 </script>
 </pre>
 </body>
 </html>