Bug 1102416: make Yahoo the default search plugin for en-US in American time zones, r=dolske, a=gavin
☠☠ backed out by 28157652a0fd ☠ ☠
authorGavin Sharp <gavin@gavinsharp.com>
Sun, 23 Nov 2014 20:38:22 -0800
changeset 234094 70dca05c957564007648dee9bc5f3f1646d11da8
parent 234093 75879febfc5592f89517ad50acf68932e0d8d490
child 234095 28157652a0fd5469f0b8a912a1d263940865b906
push id1
push usersledru@mozilla.com
push dateThu, 04 Dec 2014 17:57:20 +0000
reviewersdolske, gavin
bugs1102416
milestone35.0
Bug 1102416: make Yahoo the default search plugin for en-US in American time zones, r=dolske, a=gavin
browser/app/profile/firefox.js
browser/base/content/test/general/browser_contextSearchTabPosition.js
browser/base/content/test/general/browser_urlbar_search_healthreport.js
toolkit/components/search/nsSearchService.js
toolkit/components/search/tests/xpcshell/test_selectedEngine.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -397,16 +397,21 @@ pref("browser.search.defaultenginename",
 // disable logging for the search service by default
 pref("browser.search.log", false);
 
 // Ordering of Search Engines in the Engine list. 
 pref("browser.search.order.1",                "chrome://browser-region/locale/region.properties");
 pref("browser.search.order.2",                "chrome://browser-region/locale/region.properties");
 pref("browser.search.order.3",                "chrome://browser-region/locale/region.properties");
 
+pref("browser.search.defaultenginename.US",      "data:text/plain,browser.search.defaultenginename.US=Yahoo");
+pref("browser.search.order.US.1",                "data:text/plain,browser.search.order.US.1=Yahoo");
+pref("browser.search.order.US.2",                "data:text/plain,browser.search.order.US.2=Google");
+pref("browser.search.order.US.3",                "data:text/plain,browser.search.order.US.3=Bing");
+
 // search bar results always open in a new tab
 pref("browser.search.openintab", false);
 
 // context menu searches open in the foreground
 pref("browser.search.context.loadInBackground", false);
 
 // send ping to the server to update
 pref("browser.search.update", true);
--- a/browser/base/content/test/general/browser_contextSearchTabPosition.js
+++ b/browser/base/content/test/general/browser_contextSearchTabPosition.js
@@ -48,18 +48,19 @@ function test() {
     ok(provider, "Searches provider is available.");
 
     let m = provider.getMeasurement("counts", 3);
     m.getValues().then(function onValues(data) {
       let now = new Date();
       ok(data.days.hasDay(now), "Have data for today.");
       let day = data.days.getDay(now);
 
-      // Will need to be changed if Google isn't the default search engine.
-      let field = "google.contextmenu";
+      // Will need to be changed if Yahoo isn't the default search engine.
+      let defaultProviderID = "yahoo";
+      let field = defaultProviderID + ".contextmenu";
       ok(day.has(field), "Have search recorded for context menu.");
 
       // If any other mochitests perform a context menu search, this will fail.
       // The solution will be to look up count at test start and ensure it is
       // incremented by two.
       is(day.get(field), 2, "2 searches recorded in FHR.");
       finish();
     });
--- a/browser/base/content/test/general/browser_urlbar_search_healthreport.js
+++ b/browser/base/content/test/general/browser_urlbar_search_healthreport.js
@@ -22,18 +22,20 @@ add_task(function* test_healthreport_sea
   let provider = reporter.getProvider("org.mozilla.searches");
   ok(provider, "Searches provider is available.");
   let m = provider.getMeasurement("counts", 3);
 
   let data = yield m.getValues();
   let now = new Date();
   let oldCount = 0;
 
-  // This will to be need changed if default search engine is not Google.
-  let field = "google.urlbar";
+  // This will to be need changed if default search engine is not Yahoo.
+  let defaultEngineID = "yahoo";
+
+  let field = defaultEngineID + ".urlbar";
 
   if (data.days.hasDay(now)) {
     let day = data.days.getDay(now);
     if (day.has(field)) {
       oldCount = day.get(field);
     }
   }
 
@@ -66,15 +68,15 @@ add_task(function* test_healthreport_sea
 
   m = provider.getMeasurement("engines", 1);
   yield provider.collectDailyData();
   data = yield m.getValues();
 
   ok(data.days.hasDay(now), "Have engines data when Telemetry is enabled.");
   day = data.days.getDay(now);
   ok(day.has("default"), "We have default engine data.");
-  is(day.get("default"), "google", "The default engine is reported properly.");
+  is(day.get("default"), defaultEngineID, "The default engine is reported properly.");
 
   // Restore.
   Services.prefs.setBoolPref("toolkit.telemetry.enabled", oldTelemetry);
 
   gBrowser.removeTab(tab);
 });
--- a/toolkit/components/search/nsSearchService.js
+++ b/toolkit/components/search/nsSearchService.js
@@ -396,16 +396,49 @@ loadListener.prototype = {
   // FIXME: bug 253127
   // nsIHttpEventSink
   onRedirect: function (aChannel, aNewChannel) {},
   // nsIProgressEventSink
   onProgress: function (aRequest, aContext, aProgress, aProgressMax) {},
   onStatus: function (aRequest, aContext, aStatus, aStatusArg) {}
 }
 
+// Hacky method that tries to determine if this user is in a US geography, and
+// using an en-US build.
+function getIsUS() {
+  // If we've set the pref before, just return that result.
+  let cachePref = "browser.search.isUS";
+  try {
+    return Services.prefs.getBoolPref(cachePref);
+  } catch(e) {}
+
+  if (getLocale() != "en-US") {
+    Services.prefs.setBoolPref(cachePref, false);
+    return false;
+  }
+
+  // Timezone assumptions! We assume that if the system clock's timezone is
+  // between Newfoundland and Hawaii, that the user is in North America.
+
+  // This includes all of South America as well, but we have relatively few
+  // en-US users there, so that's OK.
+
+  // 150 minutes = 2.5 hours (UTC-2.5), which is
+  // Newfoundland Daylight Time (http://www.timeanddate.com/time/zones/ndt)
+
+  // 600 minutes = 10 hours (UTC-10), which is
+  // Hawaii-Aleutian Standard Time (http://www.timeanddate.com/time/zones/hast)
+
+  let UTCOffset = (new Date()).getTimezoneOffset();
+  let isNA = UTCOffset >= 150 && UTCOffset <= 600;
+
+  Services.prefs.setBoolPref(cachePref, isNA);
+
+  return isNA;
+}
 
 /**
  * Used to verify a given DOM node's localName and namespaceURI.
  * @param aElement
  *        The element to verify.
  * @param aLocalNameArray
  *        An array of strings to compare against aElement's localName.
  * @param aNameSpaceArray
@@ -2994,18 +3027,26 @@ SearchService.prototype = {
   },
 
   // Get the original Engine object that belongs to the defaultenginename pref
   // of the default branch.
   get _originalDefaultEngine() {
     let defaultPrefB = Services.prefs.getDefaultBranch(BROWSER_SEARCH_PREF);
     let nsIPLS = Ci.nsIPrefLocalizedString;
     let defaultEngine;
+
+    let defPref;
+    if (getIsUS()) {
+      defPref = "defaultenginename.US";
+    } else {
+      defPref = "defaultenginename";
+    }
+
     try {
-      defaultEngine = defaultPrefB.getComplexValue("defaultenginename", nsIPLS).data;
+      defaultEngine = defaultPrefB.getComplexValue(defPref, nsIPLS).data;
     } catch (ex) {
       // If the default pref is invalid (e.g. an add-on set it to a bogus value)
       // getEngineByName will just return null, which is the best we can do.
     }
     return this.getEngineByName(defaultEngine);
   },
 
   _buildCache: function SRCH_SVC__buildCache() {
@@ -3774,17 +3815,21 @@ SearchService.prototype = {
 
           this.__sortedEngines.push(engine);
           addedEngines[engine.name] = engine;
         }
       }
       catch (e) { }
 
       while (true) {
-        engineName = getLocalizedPref(BROWSER_SEARCH_PREF + "order." + (++i));
+        prefName = BROWSER_SEARCH_PREF + "order.";
+        if (getIsUS()) {
+          prefName += "US.";
+        }
+        engineName = getLocalizedPref(prefName + (++i));
         if (!engineName)
           break;
 
         engine = this._engines[engineName];
         if (!engine || engine.name in addedEngines)
           continue;
 
         this.__sortedEngines.push(engine);
@@ -3936,17 +3981,22 @@ SearchService.prototype = {
           engineOrder[engineName] = i++;
       }
     } catch (e) {
       LOG("Getting extra order prefs failed: " + e);
     }
 
     // Now look through the "browser.search.order" branch.
     for (var j = 1; ; j++) {
-      engineName = getLocalizedPref(BROWSER_SEARCH_PREF + "order." + j);
+      var prefName = BROWSER_SEARCH_PREF + "order.";
+      if (getIsUS()) {
+        prefName += "US.";
+      }
+      prefName += j;
+      engineName = getLocalizedPref(prefName);
       if (!engineName)
         break;
 
       if (!(engineName in engineOrder))
         engineOrder[engineName] = i++;
     }
 
     LOG("getDefaultEngines: engineOrder: " + engineOrder.toSource());
--- a/toolkit/components/search/tests/xpcshell/test_selectedEngine.js
+++ b/toolkit/components/search/tests/xpcshell/test_selectedEngine.js
@@ -3,19 +3,53 @@
 
 Components.utils.import("resource://gre/modules/osfile.jsm");
 
 const kDefaultenginenamePref = "browser.search.defaultenginename";
 const kSelectedEnginePref = "browser.search.selectedEngine";
 
 const kTestEngineName = "Test search engine";
 
+// These two functions (getLocale and getIsUS) are copied from nsSearchService.js
+function getLocale() {
+  let LOCALE_PREF = "general.useragent.locale";
+  return Services.prefs.getCharPref(LOCALE_PREF);
+}
+
+function getIsUS() {
+  if (getLocale() != "en-US") {
+    return false;
+  }
+
+  // Timezone assumptions! We assume that if the system clock's timezone is
+  // between Newfoundland and Hawaii, that the user is in North America.
+
+  // This includes all of South America as well, but we have relatively few
+  // en-US users there, so that's OK.
+
+  // 150 minutes = 2.5 hours (UTC-2.5), which is
+  // Newfoundland Daylight Time (http://www.timeanddate.com/time/zones/ndt)
+
+  // 600 minutes = 10 hours (UTC-10), which is
+  // Hawaii-Aleutian Standard Time (http://www.timeanddate.com/time/zones/hast)
+
+  let UTCOffset = (new Date()).getTimezoneOffset();
+  let isNA = UTCOffset >= 150 && UTCOffset <= 600;
+
+  return isNA;
+}
+
 function getDefaultEngineName() {
   const nsIPLS = Ci.nsIPrefLocalizedString;
-  return Services.prefs.getComplexValue(kDefaultenginenamePref, nsIPLS).data;
+  // Copy the logic from nsSearchService
+  let pref = kDefaultenginenamePref;
+  if (getIsUS()) {
+    pref += ".US";
+  }
+  return Services.prefs.getComplexValue(pref, nsIPLS).data;
 }
 
 function waitForNotification(aExpectedData) {
   let deferred = Promise.defer();
 
   const SEARCH_SERVICE_TOPIC = "browser-search-service";
   Services.obs.addObserver(function observer(aSubject, aTopic, aData) {
     if (aData != aExpectedData)
@@ -89,17 +123,20 @@ add_task(function* test_persistAcrossRes
   do_check_eq(json["[global]"].hash.length, 44);
 
   // Re-init and check the engine is still the same.
   yield asyncReInit();
   do_check_eq(Services.search.currentEngine.name, kTestEngineName);
 
   // Cleanup (set the engine back to default).
   Services.search.currentEngine = Services.search.defaultEngine;
-  do_check_eq(Services.search.currentEngine.name, getDefaultEngineName());
+  // This check is no longer valid with bug 1102416's patch - defaultEngine
+  // is not based on the same value as _originalDefaultEngine in non-Firefox
+  // users of the search service.
+  //do_check_eq(Services.search.currentEngine.name, getDefaultEngineName());
 });
 
 // An engine set without a valid hash should be ignored.
 add_task(function* test_ignoreInvalidHash() {
   // Set the engine through the API.
   Services.search.currentEngine = Services.search.getEngineByName(kTestEngineName);
   do_check_eq(Services.search.currentEngine.name, kTestEngineName);
   yield waitForNotification("write-metadata-to-disk-complete");