Bug 848420 - Distribution support for additional default search engines. r=mfinkle
authorMargaret Leibovic <margaret.leibovic@gmail.com>
Mon, 18 Mar 2013 15:39:08 -0700
changeset 125315 f49cd7c9b7664296c92d05098d8287a7cfda2240
parent 125314 d0c34cd5d1226e44cc154dcdb9ce4ff1c9d483eb
child 125316 7dafe64aa7f71198ceb5fe5c143b8709fdbd82a1
push idunknown
push userunknown
push dateunknown
reviewersmfinkle
bugs848420
milestone22.0a1
Bug 848420 - Distribution support for additional default search engines. r=mfinkle
mobile/android/chrome/content/browser.js
mobile/android/components/DirectoryProvider.js
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -8352,16 +8352,18 @@ var Distribution = {
     defaults.setCharPref("distribution.version", aData.version);
   },
 
   getPrefs: function dc_getPrefs() {
     let file;
     if (this._path) {
       file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
       file.initWithPath(this._path);
+      // Store the path in a pref for DirectoryProvider to read.
+      Services.prefs.setCharPref("distribution.path", this._path);
     } else {
       // If a path isn't specified, look in the data directory:
       // /data/data/org.mozilla.xxx/distribution
       file = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
       file.append("distribution");
     }
     file.append("preferences.json");
 
--- a/mobile/android/components/DirectoryProvider.js
+++ b/mobile/android/components/DirectoryProvider.js
@@ -1,32 +1,40 @@
 /* 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/. */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
+const Cu = Components.utils;
 
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 // -----------------------------------------------------------------------
 // Directory Provider for special browser folders and files
 // -----------------------------------------------------------------------
 
 const NS_APP_CACHE_PARENT_DIR = "cachePDir";
+const NS_APP_SEARCH_DIR       = "SrchPlugns";
+const NS_APP_SEARCH_DIR_LIST  = "SrchPluginsDL";
+const NS_APP_USER_SEARCH_DIR  = "UsrSrchPlugns";
+const NS_XPCOM_CURRENT_PROCESS_DIR = "XCurProcD";
 const XRE_UPDATE_ROOT_DIR     = "UpdRootD";
 const ENVVAR_UPDATE_DIR       = "UPDATES_DIRECTORY";
 const WEBAPPS_DIR             = "webappsDir";
 
 function DirectoryProvider() {}
 
 DirectoryProvider.prototype = {
   classID: Components.ID("{ef0f7a87-c1ee-45a8-8d67-26f586e46a4b}"),
   
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider]),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider,
+                                         Ci.nsIDirectoryServiceProvider2]),
 
   getFile: function(prop, persistent) {
     if (prop == NS_APP_CACHE_PARENT_DIR) {
       let dirsvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
       let profile = dirsvc.get("ProfD", Ci.nsIFile);
       return profile;
     } else if (prop == WEBAPPS_DIR) {
       // returns the folder that should hold the webapps database file
@@ -48,13 +56,109 @@ DirectoryProvider.prototype = {
       let dm = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager);
       return dm.defaultDownloadsDirectory;
     }
     
     // We are retuning null to show failure instead for throwing an error. The
     // interface is called quite a bit and throwing an error is noisy. Returning
     // null works with the way the interface is called [see bug 529077]
     return null;
+  },
+
+  /**
+   * Appends the distribution-specific search engine directories to the array.
+   * The distribution directory structure is as follows:
+   *
+   * \- distribution/
+   *    \- searchplugins/
+   *       |- common/
+   *       \- locale/
+   *          |- <locale 1>/
+   *          ...
+   *          \- <locale N>/
+   *
+   * Common engines are loaded for all locales. If there is no locale directory for
+   * the current locale, there is a pref: "distribution.searchplugins.defaultLocale",
+   * which specifies a default locale to use.
+   */
+  _appendDistroSearchDirs: function(array) {
+    let distro = FileUtils.getDir(NS_XPCOM_CURRENT_PROCESS_DIR, ["distribution"], false);
+    if (!distro.exists()) {
+      // If there's no distribution in the data directory, check for a system distribution.
+      let path;
+      try {
+        path = Services.prefs.getCharPref("distribution.path");
+      } catch (e) { }
+
+      if (!path)
+        return;
+
+      distro = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+      distro.initWithPath(path);
+    }
+
+    let searchPlugins = distro.clone();
+    searchPlugins.append("searchplugins");
+    if (!searchPlugins.exists())
+      return;
+
+    let commonPlugins = searchPlugins.clone();
+    commonPlugins.append("common");
+    if (commonPlugins.exists())
+      array.push(commonPlugins);
+
+    let localePlugins = searchPlugins.clone();
+    localePlugins.append("locale");
+    if (!localePlugins.exists())
+      return;
+
+    let curLocale = Services.prefs.getCharPref("general.useragent.locale");
+    let curLocalePlugins = localePlugins.clone();
+    curLocalePlugins.append(curLocale);
+    if (curLocalePlugins.exists()) {
+      array.push(curLocalePlugins);
+      return;
+    }
+
+    // We didn't append the locale dir - try the default one.
+    let defLocale = Services.prefs.getCharPref("distribution.searchplugins.defaultLocale");
+    let defLocalePlugins = localePlugins.clone();
+    if (defLocalePlugins.exists())
+      array.push(defLocalePlugins);
+  },
+
+  getFiles: function(prop) {
+    if (prop != NS_APP_SEARCH_DIR_LIST)
+      return;
+
+    let result = [];
+
+    /**
+     * We want to preserve the following order, since the search service loads
+     * engines in first-loaded-wins order.
+     *   - distro search plugin locations
+     *   - user search plugin locations (profile)
+     *   - app search plugin location (shipped engines)
+     */
+    this._appendDistroSearchDirs(result);
+
+    let appUserSearchDir = FileUtils.getDir(NS_APP_USER_SEARCH_DIR, [], false);
+    if (appUserSearchDir.exists())
+      result.push(appUserSearchDir);
+
+    let appSearchDir = FileUtils.getDir(NS_APP_SEARCH_DIR, [], false);
+    if (appSearchDir.exists())
+      result.push(appSearchDir);
+
+    return {
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]),
+      hasMoreElements: function() {
+        return result.length > 0;
+      },
+      getNext: function() {
+        return result.shift();
+      }
+    };
   }
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DirectoryProvider]);