Skip to content

Instantly share code, notes, and snippets.

@kmaglione
Created February 22, 2013 21:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kmaglione/c413c704c6a331d263f8 to your computer and use it in GitHub Desktop.
Save kmaglione/c413c704c6a331d263f8 to your computer and use it in GitHub Desktop.
diff -Nur bing-old/bing.xml bing-new/bing.xml
--- bing-old/bing.xml 1969-12-31 16:00:00.000000000 -0800
+++ bing-new/bing.xml 2013-02-22 12:59:18.723082667 -0800
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+ <!-- FIXME: Trailing space to avoid conflict with the builtin
+ - Bing plugin. That should ideally be updated to get tracking
+ - parameters from preferences instead. -->
+ <ShortName>Bing </ShortName>
+ <Description>Bing. Search by Microsoft.</Description>
+ <InputEncoding>UTF-8</InputEncoding>
+ <Image width="16" height="16" type="image/png">data:image/png;base64,
+ AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAABMLAAATCwAAAAAAAAAA
+ AAAVpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8V
+ pv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8ysf97zf+24//F
+ 6f/F6f/F6f+K0/9QvP8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8krP+Z2P/////////w+f/F6f/F6f/i9P//////
+ ///T7v9Bt/8Vpv8Vpv8Vpv8Vpv/T7v/////w+f97zf8Vpv8Vpv8Vpv8Vpv9QvP/T7v/////w+f9Bt/8V
+ pv8Vpv97zf////////9QvP8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8krP/i9P/////i9P8Vpv8Vpv+24//////i
+ 9P8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv+K0/////////8Vpv8Vpv/F6f////////8krP8Vpv8Vpv8V
+ pv8Vpv8Vpv8Vpv8Vpv+n3v/////w+f8Vpv8Vpv/F6f////////+n3v8krP8Vpv8Vpv8Vpv8Vpv8Vpv9t
+ x/////////+Z2P8Vpv8Vpv/F6f/////////////i9P+K0/9QvP9QvP9tx//F6f////////+n3v8Vpv8V
+ pv8Vpv/F6f/////T7v+Z2P/i9P////////////////////+24/9QvP8Vpv8Vpv8Vpv8Vpv/F6f/////F
+ 6f8Vpv8Vpv8krP9QvP9QvP9Bt/8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv/F6f/////F6f8Vpv8Vpv8Vpv8V
+ pv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv9Bt/9QvP9Bt/8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8V
+ pv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8V
+ pv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8AAHBsAABhdAAA
+ biAAAHJ0AABsaQAAdGkAACBDAABlbgAAUEEAAEVYAAAuQwAAOy4AAEU7AABBVAAAQ00AAC5W
+ <!-- Image from the original add-ons. Improperly sized and
+ - distorts badly when used as a search icon.
+ iVBORw0KGgoAAAANSUhEUgAAAEYAAAAZCAYAAACM9limAAAC7mlDQ1BJQ0MgUHJvZmlsZQAAeAGFVM9r
+ E0EU%2FjZuqdAiCFprDrJ4kCJJWatoRdQ2%2FRFiawzbH7ZFkGQzSdZuNuvuJrWliOTi0SreRe2hB%2F
+ %2BAHnrwZC9KhVpFKN6rKGKhFy3xzW5MtqXqwM5%2B8943731vdt8ADXLSNPWABOQNx1KiEWlsfEJq%2
+ FIgAjqIJQTQlVdvsTiQGQYNz%2BXvn2HoPgVtWw3v7d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836
+ Epx3QI3%2BPY8uyPOU55eMG1Dys9xFkifEA1Lc5%2FTbhTzSXTQINIOJT1cVI%2BnNeLlNcdB2luZsbI
+ EL1PkKa7zO6rYqGcTvYOkL2d9H5Os94%2BwiHCCxmtP0a4jZ71jNU%2F4mHhpObEhj0cGDX0%2BGAVtx
+ qp%2BDXCFF8QTSeiVHHZLg3xmK79VvJKgnCQOMpkYYBzWkhP10xu%2BLqHBX0m1xOv4ndWUeF5jxNn3t
+ Td70XaAq8wDh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz%2B
+ KCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF5Zm5Gh7X08jjc01efJXUdpNXR5aseXq8muwa
+ P%2BxXlzHmgjWPxHOw%2B%2FEtX5XMlymMFMXjVfPqS4R1WjE3359sfzs94i7PLrXWc62JizdWm5dn%2
+ FWpI%2B%2B6qvJPmVflPXvXx%2FGfNxGPiKTEmdornIYmXxS7xkthLqwviYG3HCJ2VhinSbZH6JNVgYJ
+ q89S9dP1t4vUZ%2FDPVRlBnM0lSJ93%2FCKmQ0nbkOb%2FqP28f8F%2BT3iuefKAIvbODImbptU3HvEK
+ FlpW5zrgIXv9F98LZua6N%2BOPwEWDyrFq1SNZ8gvAEcdod6HugpmNOWls05Uocsn5O66cpiUsxQ20NS
+ Utcl12VLFrOZVWLpdtiZ0x1uHKE5QvfEp0plk%2Fqv8RGw%2FbBS%2BfmsUtl%2BThrWgZf6b8C8%2FU
+ XAeIuJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAMIklEQVRYCdVZe3BcVRn%2Fzrn37iOPJmm7SZAiUl6S
+ UFseMkxngCCCgm1e7cYqIPyh5TlYFUUE2cQ%2FENEZQYpa7ExnqpYhS%2FMqpOKoRGCmZcqzTuIASnFs
+ Kc2mTdrNY3fvvef4%2B87NJpsm0OA4I5zpzb177jnf4%2Fc9z62INXf5JGwplHdE%2BWJlqrv%2BDdFG
+ UidI0YceQhBpvf%2FnK6PlkdGHhBBfAokjQtO9Rbe83kMUvP%2FQZP8PG%2BwP4gk1BLW2QdnjRmtCa0
+ 36uFmiZFxSnPyK6HhrcXlo%2Fdiw6xVHrZPHMv7W8Y3n1xTdrt%2BlNiEpoWeA%2FqH5zGI8PTEfWsEa
+ 6NafnNYtGZ%2BUCfq2JmgGMFq7wcL%2BpC3aBjytE1icmA1AAraHVxnCIDgF0kDSrIXar4yNeJniYicC
+ 9hhqd5EbGTbiJwJA4U2C4u2S57SO%2B%2B%2FPpw18agRAn%2BZjCM38IwTWxWvECWn1XSa1rvOYLcGK
+ s0eg7yQwML8m4Ug7ELQ9nuMN1V%2F4bbEfKSuzwiJMGUyEXOFrmhCWn9bt8dE8YdGStALBAQkULtH6Cd
+ omdlOWVmBXuviz9DxdoN18KPF6uBzAIL7olJZkdIKiC22VC1MOHEKWcD3LtUK5Yd2eAJ9gTPOZ9lZj%2
+ FXgSyiYMLV5Z1dBTJcKiKC%2Bz1ORnJ6LDujdxjJAiKluSJcqzL5JKXqwFfRq2CymhHhdKngn5NdC1Ra
+ wJOQaAIMcc9t3c8uoopQa98FdI6DpkmRXYWCOdkhAzZCOrXBoQiTcA%2BOsg%2BGfXznUfaY8fNe9Z4f
+ a4f8cdO8OP7CleSrtPT9Piw8W0PDWi%2F3TFIWNVeCB7mLjwMadySdUqZYkrSenzQXq5cEoiTIe9TOfS
+ 8Faxl%2Flokn9QGaf3cO%2FVx8zrtjbkwIQSk3eeq67fcZqy%2FHXYcxlkP1%2FYRTESFn4K0u4YyPh%
+ 2Fx7JdyA77cV9L0qmB3kTSAjtJfuZYvSX0uK%2FFaQj2lQwMrGxhtz8CebZAmqukU1yLi1R2BNO5vXi5
+ D8p4AAmUxBlSOrUyUkHKHQXTibfAdWPKzj3KoLCQZ16zc4EbzTxvS%2FszGlx837v2ne0N29i6DEqsuW
+ cdHr4jLOdCGSkn7WUB%2BLGDoPMa6I%2FBH8KQ9mxhR8%2BSoVLIcZTX7MP7hwc7Gx9mHuLyPls%2FW%
+ 2BdxSFY2dt8HyneQU7JQ2BFSE0Ps37txDeGCvnQ2OZEaAZ0gL8h4rBdCCQ9AyICn%2FMtTnY19xpuhBw
+ Nj8gIIAB84hhVma6URWw8robeVllXs27eljhmZcXL9U0VZ2z0VDvdlyLQBVi4DF7CY6FOudd3QjlUHKp
+ q6ysHtObLDy4yXubmvpjpXP84EKpt7HhJ2%2BJsEwLSXYaS64em%2FBuc9%2BzuaDgdcsA7uLn3rXKXl
+ NzB3I5TCBlZl%2FEkY4VoYIcfgxMpHfi9CpS1AlpUdh1wP2o7c8i5NHMgbysjs6Fqp1A9hjNVauZ6Qjo
+ 37Fu2Ln8BxFtuufONAzyoG0oxCYBSHlPa9AUvTuve6Gv6WX8T3vLUL5xbVb6%2BVtv0EmNSCIQAdf42c
+ 3CVOJgqM%2FN2YW8YbfS97%2FVBn4%2B8qm7puF6GSRwAiNFSDyKY3Yb6rkOZcfCobOi7VltwqhHUqQg
+ RWH71%2FsKPhHtC7X4RL79a5UfghARRac6ir4Zk8PaYFyWFj%2BOnkqFrTswlOsl4rOIv2U9D1ooOdje
+ %2Fwa%2Fa%2B%2FFqTbDGH1GtJUt57MEs9g8LW4MrDxHkwA%2FPAN8S2uOkx53DPmn7hi0bE1CC7qAwv
+ WEFe6G4gP44dEiuZHUkpkHh5iBuw1ngmW5ZBYdc1lyEfKDLFh98hFw12Nz%2BHBLqBKwTSKITV1y5as3
+ MJ6F%2Bv3XG0YRHspocYFF6fl5t5G65MG%2FrwMzzjW9rPvm3mQ6UxxP4G8xwUhCkA88Aojk2kxEcPdT
+ b%2BE4KGOH65yeOcMHPgNxKf3rTe5XWD3fX%2FAOHfIDyAKzwBie0TazpOBQdO0vgHqeCzsYaeUrz7lL
+ GUQk%2Bp9Qu8mFIxwS4f8CnkhWfOWasPmrzlSfUSBDzEIQjESy2duxK7EYGcHl2SivqYHJWeBfmOlxu0
+ OB9BeWM0Ervg5QAZxVfIk3hbPuz4mQcDwyhZ2ke8C%2F9FnqTUAHLwPEbtAPcDGOoFxDcoQQdNS1yPlk
+ KUrAEGb32yfeFli%2BE6i40iCmaWCqUCI5aaspL5ffwfNJM8BUEZICMXbBUC3NxS4Dc7u0O%2BFKfxuj
+ OiEyhFs4fp5ieLAwiebroFgIyQHufVHAWFu9i92N98IWwLtTxqXqZPCnywcOVcz32QF9ZBWBRryUwgsq
+ CMJaxx3HkCu5gUqkDEQoQEa7BIuxo2ntdoAwGA49kC5sMOAEEiJLV6C0L%2FEUn5a8g5zHvDKS3PbP93
+ 79VHjJLcFOYHeyU8hn8iL90IL7mYFPolIUFTJM2ywvWYsMHnVbLs8%2FglXP4G3Hro5fUeE%2BeQ4fm5
+ Brsl9bXCigkW9QYkRpgVsnjegAq5%2FeSFo3BybJ2Wj4ELBmCb9wg8hmwPqAfOwPBrDZiF%2Bi76qs8J
+ p2iJ8HM1GS%2BzEyF7m%2B5OIOxmDg77xa5zK6zzIHuYQNeqssc2ovz3mmg33ff0HlsLdR%2B47NCKPd
+ 9qrmrqukXrxl%2BxlYzyQJvq6gBQG3YliPr6YPa%2Fkn42wWkd5bf7NjRJqzmUmCH858eD6IqrmrvhjX
+ kgphn%2Bb54EvNQvOtjRPBhr7ryC3PHNUPQSK1x8EXqePZVN3b1Q5gUp%2FCFIwBY7K0ahzyMPLuMch%
+ 2BSbUn5uI%2FqWH72fPHaqo%2BkpgHEX2ZGfIN5IS%2FollFrqkHpAd8Sn%2BgoDClNJMEh1VL7q6YpQ
+ yLsLM3cJDiN2Pjd7z2BXQ%2B%2FClmSZTSEf5XOGw%2BAXhpnEH77%2FNyPYB1flnEOQ%2F014d13l6y
+ uu8%2F3sjXDFi1HCrxHSvoZzHsIOMiBdg5%2FKoEE34UyvDo2U3c%2F7uVppHYQZ%2F84PU8JQiR5E95
+ jSUv8MneZChMWduezIOnjDVrTju2Cd%2FcqxU9L1YnBilEnrEsfR62S47JOcxNBHDILg9wHKFiYsRks0
+ RbKccbj65Hnhzs%2B4eLJwumDFCR7zbcZUiHPboDcluB3YyhdXRJU7ukJp6xSErkTnjQD3R1BZqvH%2B
+ TgC2CHNXxSqO7q1cu71BP7vmLY6M46uSzfHFwmjdsAVE%2F%2BJm07diqgHt%2BNlA%2FgfcnfJZQ3po
+ IKQVttBWm7Y7l%2BZW%2FU1s7fRFaOPh7Vfvn8EACVk6RQDBIsvL2MpH8o3gNxBB71HiSPRN8xpB8tU5
+ 1B3HKmGaKjcWxQknSDjDFcrowAdJVJ13tzf%2FC2T5mjWq13a0Ky%2F7JFnWechL50COJ3FQXqmfuX4s
+ yDPT5oLtAtMVKsUtfUjY52jhXSgUnYs8twBcbCx20R6n0R%2FuFb7%2FWk7K%2FuHOxhGWwOSjZAv6Hq
+ RFWCDmctdrlyD7i2wo14%2FT32gMJ1p4IzKv8C1X7A0aweluc5YmBROgGVrkW8ulDoUFub6XifTzobJQ
+ IW4MjUcCpIKtwWPFUqk3XeAubu48R2q5B%2B4QNccMN%2F29Qx1NPy3U32xgYPIXtbbim0Y7fxKYmjvR
+ M6%2FnfSdaN9d7CGAMM9e7%2BcwZeVuRFfmah9z5NTgfdlSu7dV84flx5gVAZ8hickwAKV5Nluf8Rx8z
+ XzswOxvka35yADQTJgnmaeTvxoPyPyY%2FMs2cC7wrv2Q%2B95n7De%2BpXDP1begEbYbho%2FkrwQeP
+ qVD64GUfzbdVzT03o44uR8XhXuM9HCwfYEnNuYg76tq4nvp8%2Bfaw1C%2Btdysbes5Do7gLy2yEkoX8
+ eTv2PXp8KJ0QuY8iJHkl4C4jVnjBzYAClTmHrranKtVV%2F%2B2Z5Xfq86Vf3di9DF3NNpTsMEBB8Ui%
+ 2FWJ4NbTY6Tn3zDTT%2B2HoMhzvCWE1%2B9NosnCjKJQByx19Gct%2BstdqNjn4M51ckZPskKNqIjPZ1
+ AFISVMaxXcp140M74gfMOQpHm0In%2BNgCw0rkjy2LGrtrUDLvRdf0RRkpqyB8cMPHNv4QxvnPQr%2BF
+ 4o7Tf2YYPaz7JtZtGhpe8Atz4sanlbn%2Bq%2BhjDYwBp6A5q1779FLlu5fiFH8ByuoZ6LxtRBluGt9G
+ 5auYewXNxPP4v7N0AOzcoPC7%2FwBfh%2BUgcZXzvgAAAABJRU5ErkJggg==
+ -->
+ </Image>
+ <Url type="application/x-suggestions+json" template="http://api.bing.com/osjson.aspx">
+ <Param name="query" value="{searchTerms}"/>
+ <Param name="form" value="OSDJAS"/>
+ </Url>
+ <Url type="text/html" method="GET" template="http://www.bing.com/search">
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="form" value="MOZHPB"/>
+ <MozParam name="pc" condition="pref" pref="ms-pc"/>
+ </Url>
+ <Url type="application/x-moz-keywordsearch" method="GET" template="http://www.bing.com/search">
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="form" value="MOZPLB"/>
+ <MozParam name="pc" condition="pref" pref="ms-pc"/>
+ </Url>
+ <SearchForm>http://www.bing.com/search</SearchForm>
+</SearchPlugin>
diff -Nur bing-old/bootstrap.js bing-new/bootstrap.js
--- bing-old/bootstrap.js 2011-10-18 15:21:50.000000000 -0700
+++ bing-new/bootstrap.js 2013-02-22 12:57:46.540384119 -0800
@@ -19,6 +19,7 @@
*
* Contributor(s):
* Edward Lee <edilee@mozilla.com>
+ * Kris Maglione <kmaglione@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -42,49 +43,27 @@
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+const REASONS = {};
+["APP_STARTUP", "APP_SHUTDOWN",
+ "ADDON_ENABLE", "ADDON_DISABLE",
+ "ADDON_INSTALL", "ADDON_UNINSTALL",
+ "ADDON_UPGRADE", "ADDON_DOWNGRADE"].forEach(function (reason) {
+ REASONS[this[reason]] = reason.replace(/.*_/, "").toLowerCase();
+}, this);
+
// Remember if we were just installed
let justInstalled = false;
// Remember if we're on Firefox or Fennec
let platform = Services.appinfo.name == "Firefox" ? "desktop" : "mobile";
-// Add a default search engine and move it to the right place
-function addSearchEngine() {
+function hideOriginalSearchEngine() {
// Hide any existing custom searches
let origEngine = Services.search.getEngineByName(SEARCH_NAME);
if (origEngine != null) {
origEngine.hidden = true;
unload(function() origEngine.hidden = false);
}
-
- // Add the special search engine if necessary
- let engineName = SEARCH_NAME + " ";
- try {
- Services.search.addEngineWithDetails(engineName, SEARCH_ICON, "", "",
- "GET", SEARCH_URL);
- }
- catch(ex) {}
-
- // Get the just-added or existing engine
- let engine = Services.search.getEngineByName(engineName);
- if (engine == null)
- return;
-
- // Move it to the desired position
- Services.search.moveEngine(engine, SEARCH_POSITION);
-
- // Switch to the engine by default if it's first
- if (SEARCH_POSITION == 0 && justInstalled)
- Services.search.currentEngine = engine;
-
- // Clean up when disabling
- unload(function() Services.search.removeEngine(engine));
-}
-
-// Customize the default prefs
-function setPref(pref, value) {
- let branch = Services.prefs.getBranch("");
- branch.setCharPref(pref, value);
}
// Open a new tab for the landing page and select it
@@ -95,8 +74,10 @@
// Do the appropriate thing on each platform
if (platform == "desktop") {
- // Try again after a short delay if session store is initializing
let {__SSi, __SS_restoreID, gBrowser, setTimeout} = window;
+
+ // Try again after a short delay if session store is initializing
+ // FIXME: Why not use sessionstore-windows-restored?
if (__SSi == null || __SS_restoreID != null) {
setTimeout(function() showLandingPage(window), 1000);
return;
@@ -107,22 +88,37 @@
return URI.spec == LANDING_PAGE;
});
- // Always remove the landing page when uninstalling
- unload(function() gBrowser.removeTab(landingTab));
-
// Add the landing page if not open yet
- if (landingTab == null)
+ if (landingTab == null) {
landingTab = gBrowser.loadOneTab(LANDING_PAGE);
+ // Prefer not to leak.
+ let landingTabMap = WeakMap();
+ landingTabMap.set(window, landingTab);
+
+ // Remove the landing page when uninstalling only if the user
+ // hasn't navigated away from it yet.
+ unload(function(reason) {
+ let tab = landingTabMap.get(window);
+
+ if (tab && tab.linkedBrowser.currentURI.spec == LANDING_PAGE)
+ gBrowser.removeTab(tab);
+ }, window);
+ }
+
// Make sure it's focused
gBrowser.selectedTab = landingTab;
+ landingTab = null;
}
else {
let {BrowserUI} = window;
let tab = BrowserUI.newTab(LANDING_PAGE);
- unload(function() BrowserUI.closeTab(tab));
+ unload(function() BrowserUI.closeTab(tab), window);
}
+ // We're no longer just installed after we get some windows loaded
+ justInstalled = false;
+
// Only show the landing page once
showLandingPage.shown = true;
}
@@ -130,32 +126,33 @@
/**
* Handle the add-on being activated on install/enable
*/
-function startup({id}, reason) AddonManager.getAddonByID(id, function(addon) {
+function startup(data, reason) {
// Load various javascript includes for helper functions
["helper", "utils"].forEach(function(fileName) {
- let fileURI = addon.getResourceURI("scripts/" + fileName + ".js");
- Services.scriptloader.loadSubScript(fileURI.spec, global);
+ let fileURI = data.resourceURI.spec + "/scripts/" + fileName + ".js";
+ Services.scriptloader.loadSubScript(fileURI, global);
+ });
+
+ Cu.import(SEARCH_MODULE_URL);
+ SearchSettings.init(REASONS[reason]);
+
+ unload(function(reason) {
+ SearchSettings.cleanup(reason);
+ Cu.unload(SEARCH_MODULE_URL);
});
- // Add custom search support to the browser
- addSearchEngine();
+ hideOriginalSearchEngine();
+
+ // Add custom search support to the browser and set it as default
+ SearchSettings.addSearchEngine(ENGINE_URL, true);
// Change some prefs to custom search on install
- if (justInstalled) {
- setPref(PREF_KEYWORD, SEARCH_KEYWORD_URL);
- setPref(PREF_HOME, SEARCH_HOME_URL);
- setPref(PREF_HOME_RESET, SEARCH_HOME_URL);
- }
+ for (let [pref, value] in Iterator(PREF_VALUES))
+ SearchSettings.setPref(pref, value);
// Open the landing page
watchWindows(showLandingPage);
-
- // We're no longer just installed after we get some windows loaded
- watchWindows(function(window) {
- if (justInstalled)
- window.setTimeout(function() justInstalled = false, 5000);
- });
-})
+}
/**
* Handle the add-on being deactivated on uninstall/disable
@@ -163,7 +160,7 @@
function shutdown(data, reason) {
// Clean up with unloaders when we're deactivating
if (reason != APP_SHUTDOWN)
- unload();
+ unload(REASONS[reason]);
}
/**
diff -Nur bing-old/chrome.manifest bing-new/chrome.manifest
--- bing-old/chrome.manifest 1969-12-31 16:00:00.000000000 -0800
+++ bing-new/chrome.manifest 2013-02-22 11:53:17.730659827 -0800
@@ -0,0 +1 @@
+content bing-search ./
diff -Nur bing-old/scripts/helper.js bing-new/scripts/helper.js
--- bing-old/scripts/helper.js 2011-10-18 15:18:59.000000000 -0700
+++ bing-new/scripts/helper.js 2013-02-22 12:53:41.115409289 -0800
@@ -36,22 +36,20 @@
"use strict";
-const HOME_SEARCH = JSON.stringify({
- name: "Bing",
- searchUrl: "http://www.bing.com/search?form=MOZHPB&pc=MOZO&q=_searchTerms_",
- image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEYAAAAZCAYAAACM9limAAAC7mlDQ1BJQ0MgUHJvZmlsZQAAeAGFVM9rE0EU%2FjZuqdAiCFprDrJ4kCJJWatoRdQ2%2FRFiawzbH7ZFkGQzSdZuNuvuJrWliOTi0SreRe2hB%2F%2BAHnrwZC9KhVpFKN6rKGKhFy3xzW5MtqXqwM5%2B8943731vdt8ADXLSNPWABOQNx1KiEWlsfEJq%2FIgAjqIJQTQlVdvsTiQGQYNz%2BXvn2HoPgVtWw3v7d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836Epx3QI3%2BPY8uyPOU55eMG1Dys9xFkifEA1Lc5%2FTbhTzSXTQINIOJT1cVI%2BnNeLlNcdB2luZsbIEL1PkKa7zO6rYqGcTvYOkL2d9H5Os94%2BwiHCCxmtP0a4jZ71jNU%2F4mHhpObEhj0cGDX0%2BGAVtxqp%2BDXCFF8QTSeiVHHZLg3xmK79VvJKgnCQOMpkYYBzWkhP10xu%2BLqHBX0m1xOv4ndWUeF5jxNn3tTd70XaAq8wDh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz%2BKCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF5Zm5Gh7X08jjc01efJXUdpNXR5aseXq8muwaP%2BxXlzHmgjWPxHOw%2B%2FEtX5XMlymMFMXjVfPqS4R1WjE3359sfzs94i7PLrXWc62JizdWm5dn%2FWpI%2B%2B6qvJPmVflPXvXx%2FGfNxGPiKTEmdornIYmXxS7xkthLqwviYG3HCJ2VhinSbZH6JNVgYJq89S9dP1t4vUZ%2FDPVRlBnM0lSJ93%2FCKmQ0nbkOb%2FqP28f8F%2BT3iuefKAIvbODImbptU3HvEKFlpW5zrgIXv9F98LZua6N%2BOPwEWDyrFq1SNZ8gvAEcdod6HugpmNOWls05Uocsn5O66cpiUsxQ20NSUtcl12VLFrOZVWLpdtiZ0x1uHKE5QvfEp0plk%2Fqv8RGw%2FbBS%2BfmsUtl%2BThrWgZf6b8C8%2FUXAeIuJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAMIklEQVRYCdVZe3BcVRn%2Fzrn37iOPJmm7SZAiUl6SUFseMkxngCCCgm1e7cYqIPyh5TlYFUUE2cQ%2FENEZQYpa7ExnqpYhS%2FMqpOKoRGCmZcqzTuIASnFsKc2mTdrNY3fvvef4%2B87NJpsm0OA4I5zpzb177jnf4%2Fc9z62INXf5JGwplHdE%2BWJlqrv%2BDdFGUidI0YceQhBpvf%2FnK6PlkdGHhBBfAokjQtO9Rbe83kMUvP%2FQZP8PG%2BwP4gk1BLW2QdnjRmtCa036uFmiZFxSnPyK6HhrcXlo%2Fdiw6xVHrZPHMv7W8Y3n1xTdrt%2BlNiEpoWeA%2FqH5zGI8PTEfWsEa6NafnNYtGZ%2BUCfq2JmgGMFq7wcL%2BpC3aBjytE1icmA1AAraHVxnCIDgF0kDSrIXar4yNeJniYicC9hhqd5EbGTbiJwJA4U2C4u2S57SO%2B%2B%2FPpw18agRAn%2BZjCM38IwTWxWvECWn1XSa1rvOYLcGKs0eg7yQwML8m4Ug7ELQ9nuMN1V%2F4bbEfKSuzwiJMGUyEXOFrmhCWn9bt8dE8YdGStALBAQkULtH6CdomdlOWVmBXuviz9DxdoN18KPF6uBzAIL7olJZkdIKiC22VC1MOHEKWcD3LtUK5Yd2eAJ9gTPOZ9lZj%2FXgSyiYMLV5Z1dBTJcKiKC%2Bz1ORnJ6LDujdxjJAiKluSJcqzL5JKXqwFfRq2CymhHhdKngn5NdC1RawJOQaAIMcc9t3c8uoopQa98FdI6DpkmRXYWCOdkhAzZCOrXBoQiTcA%2BOsg%2BGfXznUfaY8fNe9Z4fa4f8cdO8OP7CleSrtPT9Piw8W0PDWi%2F3TFIWNVeCB7mLjwMadySdUqZYkrSenzQXq5cEoiTIe9TOfS8Faxl%2Flokn9QGaf3cO%2FVx8zrtjbkwIQSk3eeq67fcZqy%2FHXYcxlkP1%2FYRTESFn4K0u4YyPh%2Fx7JdyA77cV9L0qmB3kTSAjtJfuZYvSX0uK%2FFaQj2lQwMrGxhtz8CebZAmqukU1yLi1R2BNO5vXi5D8p4AAmUxBlSOrUyUkHKHQXTibfAdWPKzj3KoLCQZ16zc4EbzTxvS%2FszGlx837v2ne0N29i6DEqsuWcdHr4jLOdCGSkn7WUB%2BLGDoPMa6I%2FBH8KQ9mxhR8%2BSoVLIcZTX7MP7hwc7Gx9mHuLyPls%2FW%2BdxSFY2dt8HyneQU7JQ2BFSE0Ps37txDeGCvnQ2OZEaAZ0gL8h4rBdCCQ9AyICn%2FMtTnY19xpuhBwNj8gIIAB84hhVma6URWw8robeVllXs27eljhmZcXL9U0VZ2z0VDvdlyLQBVi4DF7CY6FOudd3QjlUHKpq6ysHtObLDy4yXubmvpjpXP84EKpt7HhJ2%2BJsEwLSXYaS64em%2FBuc9%2BzuaDgdcsA7uLn3rXKXlNzB3I5TCBlZl%2FEkY4VoYIcfgxMpHfi9CpS1AlpUdh1wP2o7c8i5NHMgbysjs6Fqp1A9hjNVauZ6Qjo37Fu2Ln8BxFtuufONAzyoG0oxCYBSHlPa9AUvTuve6Gv6WX8T3vLUL5xbVb6%2BVtv0EmNSCIQAdf42c3CVOJgqM%2FN2YW8YbfS97%2FVBn4%2B8qm7puF6GSRwAiNFSDyKY3Yb6rkOZcfCobOi7VltwqhHUqQgRWH71%2FsKPhHtC7X4RL79a5UfghARRac6ir4Zk8PaYFyWFj%2BOnkqFrTswlOsl4rOIv2U9D1ooOdje%2Fwa%2Fa%2B%2FFqTbDGH1GtJUt57MEs9g8LW4MrDxHkwA%2FPAN8S2uOkx53DPmn7hi0bE1CC7qAwvWEFe6G4gP44dEiuZHUkpkHh5iBuw1ngmW5ZBYdc1lyEfKDLFh98hFw12Nz%2BHBLqBKwTSKITV1y5as3MJ6F%2Bv3XG0YRHspocYFF6fl5t5G65MG%2FrwMzzjW9rPvm3mQ6UxxP4G8xwUhCkA88Aojk2kxEcPdTb%2BE4KGOH65yeOcMHPgNxKf3rTe5XWD3fX%2FAOHfIDyAKzwBie0TazpOBQdO0vgHqeCzsYaeUrz7lLGUQk%2Bp9Qu8mFIxwS4f8CnkhWfOWasPmrzlSfUSBDzEIQjESy2duxK7EYGcHl2SivqYHJWeBfmOlxu0OB9BeWM0Ervg5QAZxVfIk3hbPuz4mQcDwyhZ2ke8C%2F9FnqTUAHLwPEbtAPcDGOoFxDcoQQdNS1yPlkKUrAEGb32yfeFli%2BE6i40iCmaWCqUCI5aaspL5ffwfNJM8BUEZICMXbBUC3NxS4Dc7u0O%2BFKfxujOiEyhFs4fp5ieLAwiebroFgIyQHufVHAWFu9i92N98IWwLtTxqXqZPCnywcOVcz32QF9ZBWBRryUwgsqCMJaxx3HkCu5gUqkDEQoQEa7BIuxo2ntdoAwGA49kC5sMOAEEiJLV6C0L%2FEUn5a8g5zHvDKS3PbP9379VHjJLcFOYHeyU8hn8iL90IL7mYFPolIUFTJM2ywvWYsMHnVbLs8%2FglXP4G3Hro5fUeE%2BeQ4fm5Brsl9bXCigkW9QYkRpgVsnjegAq5%2FeSFo3BybJ2Wj4ELBmCb9wg8hmwPqAfOwPBrDZiF%2Bi76qs8Jp2iJ8HM1GS%2BzEyF7m%2B5OIOxmDg77xa5zK6zzIHuYQNeqssc2ovz3mmg33ff0HlsLdR%2B47NCKPd9qrmrqukXrxl%2BxlYzyQJvq6gBQG3YliPr6YPa%2Fkn42wWkd5bf7NjRJqzmUmCH858eD6IqrmrvhjXkgphn%2Bb54EvNQvOtjRPBhr7ryC3PHNUPQSK1x8EXqePZVN3b1Q5gUp%2FCFIwBY7K0ahzyMPLuMch%2BSbUn5uI%2FqWH72fPHaqo%2BkpgHEX2ZGfIN5IS%2FollFrqkHpAd8Sn%2BgoDClNJMEh1VL7q6YpQyLsLM3cJDiN2Pjd7z2BXQ%2B%2FClmSZTSEf5XOGw%2BAXhpnEH77%2FNyPYB1flnEOQ%2F014d13l6yuu8%2F3sjXDFi1HCrxHSvoZzHsIOMiBdg5%2FKoEE34UyvDo2U3c%2F7uVppHYQZ%2F84PU8JQiR5E95jSUv8MneZChMWduezIOnjDVrTju2Cd%2FcqxU9L1YnBilEnrEsfR62S47JOcxNBHDILg9wHKFiYsRks0RbKccbj65Hnhzs%2B4eLJwumDFCR7zbcZUiHPboDcluB3YyhdXRJU7ukJp6xSErkTnjQD3R1BZqvH%2BTgC2CHNXxSqO7q1cu71BP7vmLY6M46uSzfHFwmjdsAVE%2F%2BJm07diqgHt%2BNlA%2FgfcnfJZQ3poIKQVttBWm7Y7l%2BZW%2FU1s7fRFaOPh7Vfvn8EACVk6RQDBIsvL2MpH8o3gNxBB71HiSPRN8xpB8tU51B3HKmGaKjcWxQknSDjDFcrowAdJVJ13tzf%2FC2T5mjWq13a0Ky%2F7JFnWechL50COJ3FQXqmfuX4syDPT5oLtAtMVKsUtfUjY52jhXSgUnYs8twBcbCx20R6n0R%2FuFb7%2FWk7K%2FuHOxhGWwOSjZAv6HqRFWCDmctdrlyD7i2wo14%2FT32gMJ1p4IzKv8C1X7A0aweluc5YmBROgGVrkW8ulDoUFub6XifTzobJQIW4MjUcCpIKtwWPFUqk3XeAubu48R2q5B%2B4QNccMN%2F29Qx1NPy3U32xgYPIXtbbim0Y7fxKYmjvRM6%2FnfSdaN9d7CGAMM9e7%2BcwZeVuRFfmah9z5NTgfdlSu7dV84flx5gVAZ8hickwAKV5Nluf8Rx8zXzswOxvka35yADQTJgnmaeTvxoPyPyY%2FMs2cC7wrv2Q%2B95n7De%2BpXDP1begEbYbho%2FkrwQePqVD64GUfzbdVzT03o44uR8XhXuM9HCwfYEnNuYg76tq4nvp8%2Bfaw1C%2Btdysbes5Do7gLy2yEkoX8eTv2PXp8KJ0QuY8iJHkl4C4jVnjBzYAClTmHrranKtVV%2F%2B2Z5Xfq86Vf3di9DF3NNpTsMEBB8Ui%2FWJ4NbTY6Tn3zDTT%2B2HoMhzvCWE1%2B9NosnCjKJQByx19Gct%2BstdqNjn4M51ckZPskKNqIjPZ1AFISVMaxXcp140M74gfMOQpHm0In%2BNgCw0rkjy2LGrtrUDLvRdf0RRkpqyB8cMPHNv4QxvnPQr%2BF4o7Tf2YYPaz7JtZtGhpe8Atz4sanlbn%2Bq%2BhjDYwBp6A5q1779FLlu5fiFH8ByuoZ6LxtRBluGt9G5auYewXNxPP4v7N0AOzcoPC7%2FwBfh%2BUgcZXzvgAAAABJRU5ErkJggg%3D%3D",
-});
-const LANDING_PAGE = "http://bing.com/?pc=MOZO";
-const PREF_HOME = "browser.startup.homepage";
-const PREF_HOME_RESET = "browser.startup.homepage_reset";
-const PREF_KEYWORD = "keyword.URL";
-const SEARCH_DOMAIN = "www.bing.com";
-const SEARCH_ICON = "data:image/x-icon;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAABMLAAATCwAAAAAAAAAAAAAVpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8ysf97zf%2B24%2F%2FF6f%2FF6f%2FF6f%2BK0%2F9QvP8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8krP%2BZ2P%2F%2F%2F%2F%2F%2F%2F%2F%2Fw%2Bf%2FF6f%2FF6f%2Fi9P%2F%2F%2F%2F%2F%2F%2F%2F%2FT7v9Bt%2F8Vpv8Vpv8Vpv8Vpv%2FT7v%2F%2F%2F%2F%2Fw%2Bf97zf8Vpv8Vpv8Vpv8Vpv9QvP%2FT7v%2F%2F%2F%2F%2Fw%2Bf9Bt%2F8Vpv8Vpv97zf%2F%2F%2F%2F%2F%2F%2F%2F9QvP8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8krP%2Fi9P%2F%2F%2F%2F%2Fi9P8Vpv8Vpv%2B24%2F%2F%2F%2F%2F%2Fi9P8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv%2BK0%2F%2F%2F%2F%2F%2F%2F%2F%2F8Vpv8Vpv%2FF6f%2F%2F%2F%2F%2F%2F%2F%2F8krP8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv%2Bn3v%2F%2F%2F%2F%2Fw%2Bf8Vpv8Vpv%2FF6f%2F%2F%2F%2F%2F%2F%2F%2F%2Bn3v8krP8Vpv8Vpv8Vpv8Vpv8Vpv9tx%2F%2F%2F%2F%2F%2F%2F%2F%2F%2BZ2P8Vpv8Vpv%2FF6f%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2Fi9P%2BK0%2F9QvP9QvP9tx%2F%2FF6f%2F%2F%2F%2F%2F%2F%2F%2F%2Bn3v8Vpv8Vpv8Vpv%2FF6f%2F%2F%2F%2F%2FT7v%2BZ2P%2Fi9P%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2B24%2F9QvP8Vpv8Vpv8Vpv8Vpv%2FF6f%2F%2F%2F%2F%2FF6f8Vpv8Vpv8krP9QvP9QvP9Bt%2F8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv%2FF6f%2F%2F%2F%2F%2FF6f8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv9Bt%2F9QvP9Bt%2F8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8Vpv8AAHBsAABhdAAAbiAAAHJ0AABsaQAAdGkAACBDAABlbgAAUEEAAEVYAAAuQwAAOy4AAEU7AABBVAAAQ00AAC5W";
+const BASE_URL = "chrome://bing-search/content/";
+const ENGINE_URL = BASE_URL + "bing.xml";
+const SEARCH_MODULE_URL = BASE_URL + "search-settings.jsm";
+
+const LANDING_PAGE = "http://www.bing.com/?pc=MOZO";
const SEARCH_HOME_URL = "http://www.bing.com/?pc=MOZO";
-const SEARCH_KEYWORD_URL = "http://www.bing.com/search?form=MOZPLB&pc=MOZO&q=";
const SEARCH_NAME = "Bing";
-const SEARCH_POSITION = 0;
-const SEARCH_URL = "http://www.bing.com/search?form=MOZPSB&pc=MOZO&q={searchTerms}";
+const SEARCH_PC = "MOZO";
+
+const PREF_VALUES = {
+ "browser.search.param.ms-pc": SEARCH_PC,
+ "browser.startup.homepage": SEARCH_HOME_URL,
+ "browser.startup.homepage_reset": SEARCH_HOME_URL
+};
// Look through tabs in the browser to see if any match
function findOpenTab(browser, checkTabAndURI) {
diff -Nur bing-old/scripts/utils.js bing-new/scripts/utils.js
--- bing-old/scripts/utils.js 2011-05-26 18:22:31.000000000 -0700
+++ bing-new/scripts/utils.js 2013-02-22 12:55:37.751271595 -0800
@@ -186,8 +186,8 @@
unloaders = unload.unloaders = [];
// Calling with no arguments runs all the unloader callbacks
- if (callback == null) {
- unloaders.slice().forEach(function(unloader) unloader());
+ if (typeof callback != "function") {
+ unloaders.slice().forEach(function(unloader) unloader(callback));
unloaders.length = 0;
return;
}
@@ -206,9 +206,9 @@
}
// Wrap the callback in a function that ignores failures
- function unloader() {
+ function unloader(reason) {
try {
- callback();
+ callback(reason);
}
catch(ex) {}
}
diff -Nur bing-old/search-settings.jsm bing-new/search-settings.jsm
--- bing-old/search-settings.jsm 1969-12-31 16:00:00.000000000 -0800
+++ bing-new/search-settings.jsm 2013-02-22 13:05:03.904066794 -0800
@@ -0,0 +1,369 @@
+var EXPORTED_SYMBOLS = ["SearchSettings"];
+
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
+// Import the Services module.
+Cu.import("resource://gre/modules/Services.jsm");
+
+const XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1");
+
+const SupportsString = Components.Constructor("@mozilla.org/supports-string;1", "nsISupportsString");
+function Prefs(branch, defaults) {
+ this.constructor = Prefs; // Ends up Object otherwise... Why?
+
+ this.branch = Services.prefs[defaults ? "getDefaultBranch" : "getBranch"](branch || "");
+ if (this.branch instanceof Ci.nsIPrefBranch2)
+ this.branch.QueryInterface(Ci.nsIPrefBranch2);
+
+ this.defaults = defaults ? this : new this.constructor(branch, true);
+}
+Prefs.prototype = {
+ /**
+ * Returns a new Prefs object for the sub-branch *branch* of this
+ * object.
+ *
+ * @param {string} branch The sub-branch to return.
+ */
+ Branch: function Branch(branch) new this.constructor(this.root + branch),
+
+ /**
+ * Returns the full name of this object's preference branch.
+ */
+ get root() this.branch.root,
+
+ /**
+ * Returns the value of the preference *name*, or *defaultValue* if
+ * the preference does not exist.
+ *
+ * @param {string} name The name of the preference to return.
+ * @param {*} defaultValue The value to return if the preference has no value.
+ * @optional
+ */
+ get: function get(name, defaultValue) {
+ let type = this.branch.getPrefType(name);
+
+ try {
+ if (type === Ci.nsIPrefBranch.PREF_STRING)
+ return this.branch.getComplexValue(name, Ci.nsISupportsString).data;
+
+ if (type === Ci.nsIPrefBranch.PREF_INT)
+ return this.branch.getIntPref(name);
+
+ if (type === Ci.nsIPrefBranch.PREF_BOOL)
+ return this.branch.getBoolPref(name);
+ }
+ catch (e if e.result == Cr.NS_ERROR_UNEXPECTED) {}
+
+ return defaultValue;
+ },
+
+ /**
+ * Returns true if the given preference exists in this branch.
+ *
+ * @param {string} name The name of the preference to check.
+ */
+ has: function has(name) this.branch.getPrefType(name) !== 0,
+
+ /**
+ * Returns an array of all preference names in this branch or the
+ * given sub-branch.
+ *
+ * @param {string} branch The sub-branch for which to return preferences.
+ * @optional
+ */
+ getNames: function getNames(branch) this.branch.getChildList(branch || "", { value: 0 }),
+
+ /**
+ * Returns true if the given preference is set to its default value.
+ *
+ * @param {string} name The name of the preference to check.
+ */
+ isDefault: function isDefault(name) !this.branch.prefHasUserValue(name),
+
+ /**
+ * Sets the preference *name* to *value*. If the preference already
+ * exists, it must have the same type as the given value.
+ *
+ * @param {name} name The name of the preference to change.
+ * @param {string|number|boolean} value The value to set.
+ */
+ set: function set(name, value) {
+ let type = typeof value;
+ if (type === "string") {
+ let string = SupportsString();
+ string.data = value;
+ this.branch.setComplexValue(name, Ci.nsISupportsString, string);
+ }
+ else if (type === "number")
+ this.branch.setIntPref(name, value);
+ else if (type === "boolean")
+ this.branch.setBoolPref(name, value);
+ else if (value == null)
+ this.reset(name);
+ else
+ throw TypeError("Unknown preference type: " + type);
+ },
+
+ /**
+ * Sets the preference *name* to *value* only if it doesn't
+ * already have that value. Avoids triggering preference observers
+ * when unnecessary.
+ */
+ maybeSet: function maybeSet(name, value) {
+ if (this.get(name) != value)
+ this.set(name, value);
+ },
+
+ /**
+ * Resets the preference *name* to its default value.
+ *
+ * @param {string} name The name of the preference to reset.
+ */
+ reset: function reset(name) {
+ if (this != this.defaults && this.branch.prefHasUserValue(name))
+ this.branch.clearUserPref(name);
+ }
+};
+
+const hasOwnProperty = Function.call.bind({}.hasOwnProperty);
+
+function isString(value) Object.prototype.toString.call(value) == "[object String]";
+
+const SearchSettings = {
+ ENGINE_ADDED: "browser-search-engine-modified",
+
+ _observers: [],
+
+ // Observer called after our engine has been successfully added
+ observe: function SS_observe(subject, topic, data) {
+ switch (topic) {
+ case this.ENGINE_ADDED:
+ if (data != "engine-added")
+ break;
+
+ let engine = subject.QueryInterface(Ci.nsISearchEngine);
+ if (!hasOwnProperty(this.engines, engine.name))
+ break;
+
+ if (this.engines[engine.name].unprocessed)
+ this._processEngine(engine);
+ break;
+ }
+ },
+
+ engines: {},
+
+ _processEngine: function SS__processEngine(engine) {
+ let self = this;
+
+ let engineDetails = this.engines[engine.name];
+ engineDetails.unprocessed = false;
+
+ // If the engine is not hidden and this is the first run, move
+ // it to the first position in the engine list and select it
+ if (engineDetails.setDefault && !engine.hidden) {
+ Services.search.moveEngine(engine, 0);
+ if (self.firstRun)
+ Services.search.currentEngine = engine;
+
+ this.setPref("browser.search.defaultenginename", engine.name, true);
+ this.setPref("keyword.URL", "");
+ }
+
+ for (let [, engine] in Iterator(this.engines))
+ if (engine.unprocessed)
+ return;
+ this._removeObserver();
+ },
+
+ _addObserver: function SS__addObserver() {
+ if (!~this._observers.indexOf(this.ENGINE_ADDED)) {
+ Services.obs.addObserver(this, this.ENGINE_ADDED, false);
+ this._observers.push(this.ENGINE_ADDED);
+ }
+ },
+
+ _removeObserver: function SS__removeObserver() {
+ if (~this._observers.indexOf(this.ENGINE_ADDED)) {
+ Services.obs.removeObserver(this, this.ENGINE_ADDED);
+ this._observers.splice(this._observers.indexOf(this.ENGINE_ADDED), 1);
+ }
+ },
+
+ /**
+ * Adds a new search engine and optionally sets it as the default
+ * engine by which about:home and location bar searches will be
+ * performed.
+ *
+ * @param {string|object} details The URL (within the add-on) of an
+ * OpenSearch XML search description file, or an object of the
+ * form:
+ *
+ * {
+ * name: "Example Engine",
+ * iconURL: "data:image/png;base64,...",
+ * alias: "example-engine", // Used as a keyword for location bar searches
+ * description: "An example search engine",
+ * method: "GET", // The HTTP request method
+ * url: "https://www.example.com/?q=_searchTerms_"
+ * }
+ * @param {boolean} default If true, this engine is set as the
+ * default search engine.
+ */
+ addSearchEngine: function SS_addSearchEngine(details, setDefault) {
+ const ENGINE_PROPERTIES = ["name", "iconURL", "alias", "description", "method", "url"];
+ let self = this;
+
+ setDefault = Boolean(setDefault);
+
+ if (isString(details)) {
+ // Search description file URL
+
+ let url = details;
+ let xhr = XMLHttpRequest();
+
+ xhr.open("GET", url);
+ xhr.onload = function () {
+ details = {
+ name: this.responseXML.querySelector(":root > ShortName").textContent,
+ unprocessed: setDefault,
+ setDefault: setDefault
+ };
+ self.engines[details.name] = details;
+
+ // Only add the engine if it doesn't already exist.
+ let engine = Services.search.getEngineByName(details.name);
+ if (engine)
+ self._processEngine(engine);
+ else {
+ // Register an observer to detect when the engine has been added, if
+ // necessary.
+ if (setDefault)
+ self._addObserver();
+
+ Services.search.addEngine(url, Ci.nsISearchEngine.DATA_XML,
+ null, false);
+ }
+ };
+ xhr.send();
+ }
+ else {
+ // Search engine details object
+
+ let newDetails = { setDefault: setDefault };
+ ENGINE_PROPERTIES.forEach(function (prop) {
+ newDetails[prop] = details[prop];
+ });
+ this.engines[newDetails.name] = newDetails;
+
+ if (!Services.search.getEngineByName(details.name)) {
+ Services.search.addEngineWithDetails.apply(Services.search,
+ ENGINE_PROPERTIES.map(function (k) details[k]))
+ }
+
+ this._processEngine(Services.search.getEngineByName(details.name));
+ }
+ },
+
+ prefs: new Prefs(""),
+
+ // Stores the original values of changed preferences.
+ savedPrefs: {},
+
+ /**
+ * Change the default value of the preference *name* to *value*.
+ * A default for this preference must exist, and it must be a
+ * character preference.
+ *
+ * The user preference will be reset only on first run, as
+ * determined by the value passed to init().
+ *
+ * @param {string} name The name of the preference to change.
+ * @param {string|boolean|number} value The new value to set. Must
+ * be the same type as the original default, if it exists.
+ * @param {boolean} localized If true, set the preference as a
+ * URL pointing to a property file, as required by the
+ * localized preference retrieval process.
+ */
+ setPref: function SS_setPref(name, value, localized) {
+ // If this is a localized preference, transform the value into an
+ // appropriate data: URL.
+ if (localized)
+ value = "data:text/plain," + encodeURIComponent(name + "=" + value.replace(/ /g, "\\u0020"));
+
+ // Save the original and new values.
+ this.savedPrefs[name] = [this.prefs.defaults.get(name), value];
+
+ // Change the default
+ this.prefs.defaults.set(name, value);
+
+ // Clear the user value if this is the first run, or the
+ // new default is the same as the user value.
+ if (this.firstRun || this.prefs.get(name) == value)
+ this.prefs.reset(name);
+ },
+
+ /**
+ * Must be called at startup.
+ *
+ * @param {string} reason The reason that initialization is required. Must
+ * be one of:
+ *
+ * startup - The app is starting up.
+ * enable - The add-on is being enabled.
+ * install - The add-on is being installed.
+ * upgrade - The add-on is being upgraded.
+ * downgrade - The add-on is being downgraded.
+ */
+ init: function SS_cleanup(reason) {
+ if (reason == "install")
+ this.firstRun = true;
+ },
+
+ firstRun: false,
+
+ /**
+ * Must be called at shutdown or when the add-on is disabled or
+ * uninstalled.
+ *
+ * @param {string} reason The reason that cleanup is required. Must
+ * be one of:
+ *
+ * shutdown - The app is being shutdown.
+ * disable - The add-on is being disabled.
+ * uninstall - The add-on is being uninstalled.
+ * upgrade - The add-on is being upgraded.
+ * downgrade - The add-on is being downgraded.
+ */
+ cleanup: function SS_cleanup(reason) {
+ if (reason == "shutdown")
+ return;
+
+ this._observers.forEach(function (observer) {
+ Services.obs.removeObserver(this, observer);
+ }, this);
+
+ // Reset our changes if the values have not been changed
+ // in the mean time.
+ for (let [name, [origValue, value]] in Iterator(this.savedPrefs)) {
+ if (this.prefs.defaults.get(name) == value) {
+ this.prefs.defaults.set(name, origValue);
+ // Clear the user value if it's the same as the default.
+ if (this.prefs.get(name) == origValue)
+ this.prefs.reset(name);
+ }
+ }
+
+ // Remove our search engines on disable or uninstall
+ if (~["disable", "uninstall"].indexOf(reason)) {
+ for (let [name, details] in Iterator(this.engines)) {
+ let engine = Services.search.getEngineByName(name);
+ // Only remove the engine if it appears to be the same one we
+ // added.
+ if (engine && (!details.url || engine.getSubmission("_searchTerms_")
+ .uri.spec == details.url))
+ Services.search.removeEngine(engine);
+ }
+ }
+ }
+};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment