merge fx-team to mozilla-central
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 17 Apr 2014 12:49:25 +0200
changeset 179406 08222fb498f827aba292d262971141d214507b17
parent 179389 a64bdaed44e31b22a2a14c92d7211511fa5fc57b (current diff)
parent 179405 6608fb641776a00c681181ba148c8bda46d9f4cf (diff)
child 179433 c55dfb01a02757b15d5c5d1f2bfec4310d0232fc
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
milestone31.0a1
merge fx-team to mozilla-central
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1420,16 +1420,18 @@ pref("ui.key.menuAccessKeyFocuses", true
 
 // Delete HTTP cache v2 data of users that didn't opt-in manually
 pref("browser.cache.auto_delete_cache_version", 1);
 // Play with different values of the decay time and get telemetry,
 // 0 means to randomize (and persist) the experiment value in users' profiles,
 // -1 means no experiment is run and we use the preferred value for frecency (6h)
 pref("browser.cache.frecency_experiment", 0);
 
+pref("browser.translation.detectLanguage", false);
+
 // Telemetry experiments settings.
 pref("experiments.enabled", false);
 pref("experiments.manifest.fetchIntervalSeconds", 86400);
 pref("experiments.manifest.uri", "https://telemetry-experiment.cdn.mozilla.net/manifest/v1/firefox/%VERSION%/%CHANNEL%");
 pref("experiments.manifest.certs.1.commonName", "*.cdn.mozilla.net");
 pref("experiments.manifest.certs.1.issuerName", "CN=Cybertrust Public SureServer SV CA,O=Cybertrust Inc");
 // Whether experiments are supported by the current application profile.
 pref("experiments.supported", true);
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -142,16 +142,19 @@ XPCOMUtils.defineLazyModuleGetter(this, 
   "resource:///modules/BrowserNewTabPreloader.jsm", "BrowserNewTabPreloader");
 
 XPCOMUtils.defineLazyModuleGetter(this, "gCustomizationTabPreloader",
   "resource:///modules/CustomizationTabPreloader.jsm", "CustomizationTabPreloader");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "Translation",
+  "resource:///modules/translation/Translation.jsm");
+
 XPCOMUtils.defineLazyModuleGetter(this, "SitePermissions",
   "resource:///modules/SitePermissions.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
   "resource:///modules/sessionstore/SessionStore.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
   "resource://gre/modules/FxAccounts.jsm");
@@ -1028,16 +1031,17 @@ var gBrowserInit = {
     Services.obs.addObserver(gFormSubmitObserver, "invalidformsubmit", false);
 
     BrowserOffline.init();
     OfflineApps.init();
     IndexedDBPromptHelper.init();
     gFormSubmitObserver.init();
     gRemoteTabsUI.init();
     gPageStyleMenu.init();
+    LanguageDetectionListener.init();
 
     // Initialize the full zoom setting.
     // We do this before the session restore service gets initialized so we can
     // apply full zoom settings to tabs restored by the session restore service.
     FullZoom.init();
     PanelUI.init();
     LightweightThemeListener.init();
     WebrtcIndicator.init();
@@ -4459,19 +4463,16 @@ var TabsInTitlebar = {
     for (let something in this._disallowed) {
       allowed = false;
       break;
     }
 
     let titlebar = $("titlebar");
     let titlebarContent = $("titlebar-content");
     let menubar = $("toolbar-menubar");
-#ifdef XP_MACOSX
-    let secondaryButtonsWidth = rect($("titlebar-secondary-buttonbox")).width;
-#endif
 
     if (allowed) {
       // We set the tabsintitlebar attribute first so that our CSS for
       // tabsintitlebar manifests before we do our measurements.
       document.documentElement.setAttribute("tabsintitlebar", "true");
       updateTitlebarDisplay();
 
       // Try to avoid reflows in this code by calculating dimensions first and
@@ -4479,16 +4480,17 @@ var TabsInTitlebar = {
 
       // Get the full height of the tabs toolbar:
       let tabsToolbar = $("TabsToolbar");
       let fullTabsHeight = rect(tabsToolbar).height;
       // Buttons first:
       let captionButtonsBoxWidth = rect($("titlebar-buttonbox-container")).width;
 
 #ifdef XP_MACOSX
+      let secondaryButtonsWidth = rect($("titlebar-secondary-buttonbox")).width;
       // No need to look up the menubar stuff on OS X:
       let menuHeight = 0;
       let fullMenuHeight = 0;
       // Instead, look up the titlebar padding:
       let titlebarPadding = parseInt(window.getComputedStyle(titlebar).paddingTop, 10);
 #else
       // Otherwise, get the height and margins separately for the menubar
       let menuHeight = rect(menubar).height;
@@ -4553,16 +4555,19 @@ var TabsInTitlebar = {
         titlebarContentHeight += extraMargin;
       }
 
       // Then we bring up the titlebar by the same amount, but we add any negative margin:
       titlebar.style.marginBottom = "-" + titlebarContentHeight + "px";
 
 
       // Finally, size the placeholders:
+#ifdef XP_MACOSX
+      this._sizePlaceholder("fullscreen-button", secondaryButtonsWidth);
+#endif
       this._sizePlaceholder("caption-buttons", captionButtonsBoxWidth);
 
       if (!this._draghandles) {
         this._draghandles = {};
         let tmp = {};
         Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
 
         let mouseDownCheck = function () {
@@ -4574,26 +4579,26 @@ var TabsInTitlebar = {
 
         this._draghandles.navToolbox = new tmp.WindowDraggingElement(gNavToolbox);
         this._draghandles.navToolbox.mouseDownCheck = mouseDownCheck;
       }
     } else {
       document.documentElement.removeAttribute("tabsintitlebar");
       updateTitlebarDisplay();
 
+#ifdef XP_MACOSX
+      let secondaryButtonsWidth = rect($("titlebar-secondary-buttonbox")).width;
+      this._sizePlaceholder("fullscreen-button", secondaryButtonsWidth);
+#endif
       // Reset the margins and padding that might have been modified:
       titlebarContent.style.marginTop = "";
       titlebarContent.style.marginBottom = "";
       titlebar.style.marginBottom = "";
       menubar.style.paddingBottom = "";
     }
-
-#ifdef XP_MACOSX
-    this._sizePlaceholder("fullscreen-button", secondaryButtonsWidth);
-#endif
   },
 
   _sizePlaceholder: function (type, width) {
     Array.forEach(document.querySelectorAll(".titlebar-placeholder[type='"+ type +"']"),
                   function (node) { node.width = width; });
   },
 #endif
 
@@ -5337,16 +5342,25 @@ function stylesheetSwitchAll(contentWind
   gPageStyleMenu.switchStyleSheet(title);
 }
 function setStyleDisabled(disabled) {
   if (disabled)
     gPageStyleMenu.disableStyle();
 }
 
 
+var LanguageDetectionListener = {
+  init: function() {
+    window.messageManager.addMessageListener("LanguageDetection:Result", msg => {
+      Translation.languageDetected(msg.target, msg.data);
+    });
+  }
+};
+
+
 var BrowserOffline = {
   _inited: false,
 
   /////////////////////////////////////////////////////////////////////////////
   // BrowserOffline Public Methods
   init: function ()
   {
     if (!this._uiElement)
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -7,16 +7,18 @@ let Cc = Components.classes;
 let Ci = Components.interfaces;
 let Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ContentLinkHandler",
   "resource:///modules/ContentLinkHandler.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "LanguageDetector",
+  "resource:///modules/translation/LanguageDetector.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerContent",
   "resource://gre/modules/LoginManagerContent.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "InsecurePasswordUtils",
   "resource://gre/modules/InsecurePasswordUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "UITour",
   "resource:///modules/UITour.jsm");
@@ -382,8 +384,54 @@ let PageStyleHandler = {
       result.push({title: currentStyleSheet.title,
                    disabled: currentStyleSheet.disabled});
     }
 
     return result;
   },
 };
 PageStyleHandler.init();
+
+let TranslationHandler = {
+  init: function() {
+    let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
+                              .getInterface(Ci.nsIWebProgress);
+    webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
+  },
+
+  /* nsIWebProgressListener implementation */
+  onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
+    if (!aWebProgress.isTopLevel ||
+        !(aStateFlags & Ci.nsIWebProgressListener.STATE_STOP))
+      return;
+
+    let url = aRequest.name;
+    if (!url.startsWith("http://") && !url.startsWith("https://"))
+      return;
+
+    // Grab a 60k sample of text from the page.
+    let encoder = Cc["@mozilla.org/layout/documentEncoder;1?type=text/plain"]
+                    .createInstance(Ci.nsIDocumentEncoder);
+    encoder.init(content.document, "text/plain", encoder.SkipInvisibleContent);
+    let string = encoder.encodeToStringWithMaxLength(60 * 1024);
+
+    // Language detection isn't reliable on very short strings.
+    if (string.length < 100)
+      return;
+
+    LanguageDetector.detectLanguage(string).then(result => {
+      if (result.confident)
+        sendAsyncMessage("LanguageDetection:Result", result.language);
+    });
+  },
+
+  // Unused methods.
+  onProgressChange: function() {},
+  onLocationChange: function() {},
+  onStatusChange:   function() {},
+  onSecurityChange: function() {},
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
+                                         Ci.nsISupportsWeakReference])
+};
+
+if (Services.prefs.getBoolPref("browser.translation.detectLanguage"))
+  TranslationHandler.init();
--- a/browser/components/translation/Translation.jsm
+++ b/browser/components/translation/Translation.jsm
@@ -6,63 +6,69 @@
 
 this.EXPORTED_SYMBOLS = ["Translation"];
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/Promise.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "LanguageDetector",
-  "resource:///modules/translation/LanguageDetector.jsm");
+
+this.Translation = {
+  supportedSourceLanguages: ["en", "zh", "ja", "es", "de", "fr", "ru", "ar", "ko", "pt"],
+  supportedTargetLanguages: ["en", "pl", "tr", "vi"],
 
-/* Create an object keeping the information related to translation for
+  _defaultTargetLanguage: "",
+  get defaultTargetLanguage() {
+    if (!this._defaultTargetLanguage) {
+      this._defaultTargetLanguage = Cc["@mozilla.org/chrome/chrome-registry;1"]
+                                      .getService(Ci.nsIXULChromeRegistry)
+                                      .getSelectedLocale("global")
+                                      .split("-")[0];
+    }
+    return this._defaultTargetLanguage;
+  },
+
+  languageDetected: function(aBrowser, aDetectedLanguage) {
+    if (this.supportedSourceLanguages.indexOf(aDetectedLanguage) != -1 &&
+        aDetectedLanguage != this.defaultTargetLanguage) {
+      if (!aBrowser.translationUI)
+        aBrowser.translationUI = new TranslationUI(aBrowser);
+
+      aBrowser.translationUI.showTranslationUI(aDetectedLanguage);
+    }
+  }
+};
+
+/* TranslationUI objects keep the information related to translation for
  * a specific browser.  This object is passed to the translation
  * infobar so that it can initialize itself.  The properties exposed to
  * the infobar are:
- * - supportedSourceLanguages, array of supported source language codes
- * - supportedTargetLanguages, array of supported target language codes
  * - detectedLanguage, code of the language detected on the web page.
- * - defaultTargetLanguage, code of the language to use by default for
- *   translation.
  * - state, the state in which the infobar should be displayed
  * - STATE_{OFFER,TRANSLATING,TRANSLATED,ERROR} constants.
  * - translatedFrom, if already translated, source language code.
  * - translatedTo, if already translated, target language code.
  * - translate, method starting the translation of the current page.
  * - showOriginalContent, method showing the original page content.
  * - showTranslatedContent, method showing the translation for an
  *   already translated page whose original content is shown.
  * - originalShown, boolean indicating if the original or translated
  *   version of the page is shown.
  */
-this.Translation = function(aBrowser) {
+function TranslationUI(aBrowser) {
   this.browser = aBrowser;
-};
+}
 
-this.Translation.prototype = {
-  supportedSourceLanguages: ["en", "zh", "ja", "es", "de", "fr", "ru", "ar", "ko", "pt"],
-  supportedTargetLanguages: ["en", "pl", "tr", "vi"],
-
+TranslationUI.prototype = {
   STATE_OFFER: 0,
   STATE_TRANSLATING: 1,
   STATE_TRANSLATED: 2,
   STATE_ERROR: 3,
 
-  _defaultTargetLanguage: "",
-  get defaultTargetLanguage() {
-    if (!this._defaultTargetLanguage) {
-      this._defaultTargetLanguage = Cc["@mozilla.org/chrome/chrome-registry;1"]
-                                      .getService(Ci.nsIXULChromeRegistry)
-                                      .getSelectedLocale("global")
-                                      .split("-")[0];
-    }
-    return this._defaultTargetLanguage;
-  },
-
   get doc() this.browser.contentDocument,
 
   translate: function(aFrom, aTo) {
     this.state = this.STATE_TRANSLATING;
     this.translatedFrom = aFrom;
     this.translatedTo = aTo;
   },
 
--- a/browser/components/translation/test/browser_translation_infobar.js
+++ b/browser/components/translation/test/browser_translation_infobar.js
@@ -24,18 +24,16 @@ function waitForCondition(condition, nex
       moveOn();
     }
     tries++;
   }, 100);
   var moveOn = function() { clearInterval(interval); nextTest(); };
 }
 
 var TranslationStub = {
-  __proto__: Translation.prototype,
-
   translate: function(aFrom, aTo) {
     this.state = this.STATE_TRANSLATING;
     this.translatedFrom = aFrom;
     this.translatedTo = aTo;
   },
 
   _reset: function() {
     this.translatedFrom = "";
@@ -49,16 +47,24 @@ var TranslationStub = {
 
   finishTranslation: function() {
     this.showTranslatedContent();
     this.state = this.STATE_TRANSLATED;
     this._reset();
   }
 };
 
+function showTranslationUI(aDetectedLanguage) {
+  let browser = gBrowser.selectedBrowser;
+  Translation.languageDetected(browser, aDetectedLanguage);
+  let ui = browser.translationUI;
+  for (let name of ["translate", "_reset", "failTranslation", "finishTranslation"])
+    ui[name] = TranslationStub[name];
+  return ui.notificationBox.getNotificationWithValue("translation");
+}
 
 function test() {
   waitForExplicitFinish();
 
   let tab = gBrowser.addTab();
   gBrowser.selectedTab = tab;
   tab.linkedBrowser.addEventListener("load", function onload() {
     tab.linkedBrowser.removeEventListener("load", onload, true);
@@ -78,45 +84,45 @@ function checkURLBarIcon(aExpectTranslat
   is(!PopupNotifications.getNotification("translate"), aExpectTranslated,
      "translate icon " + (aExpectTranslated ? "not " : "") + "shown");
   is(!!PopupNotifications.getNotification("translated"), aExpectTranslated,
      "translated icon " + (aExpectTranslated ? "" : "not ") + "shown");
 }
 
 function run_tests(aFinishCallback) {
   info("Show an info bar saying the current page is in French");
-  let notif = TranslationStub.showTranslationUI("fr");
-  is(notif.state, TranslationStub.STATE_OFFER, "the infobar is offering translation");
+  let notif = showTranslationUI("fr");
+  is(notif.state, notif.translation.STATE_OFFER, "the infobar is offering translation");
   is(notif._getAnonElt("detectedLanguage").value, "fr", "The detected language is displayed");
   checkURLBarIcon();
 
   info("Click the 'Translate' button");
   notif._getAnonElt("translate").click();
-  is(notif.state, TranslationStub.STATE_TRANSLATING, "the infobar is in the translating state");
-  ok(!!TranslationStub.translatedFrom, "Translation.translate has been called");
-  is(TranslationStub.translatedFrom, "fr", "from language correct");
-  is(TranslationStub.translatedTo, TranslationStub.defaultTargetLanguage, "from language correct");
+  is(notif.state, notif.translation.STATE_TRANSLATING, "the infobar is in the translating state");
+  ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
+  is(notif.translation.translatedFrom, "fr", "from language correct");
+  is(notif.translation.translatedTo, Translation.defaultTargetLanguage, "from language correct");
   checkURLBarIcon();
 
   info("Make the translation fail and check we are in the error state.");
-  TranslationStub.failTranslation();
-  is(notif.state, TranslationStub.STATE_ERROR, "infobar in the error state");
+  notif.translation.failTranslation();
+  is(notif.state, notif.translation.STATE_ERROR, "infobar in the error state");
   checkURLBarIcon();
 
   info("Click the try again button");
   notif._getAnonElt("tryAgain").click();
-  is(notif.state, TranslationStub.STATE_TRANSLATING, "infobar in the translating state");
-  ok(!!TranslationStub.translatedFrom, "Translation.translate has been called");
-  is(TranslationStub.translatedFrom, "fr", "from language correct");
-  is(TranslationStub.translatedTo, TranslationStub.defaultTargetLanguage, "from language correct");
+  is(notif.state, notif.translation.STATE_TRANSLATING, "infobar in the translating state");
+  ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
+  is(notif.translation.translatedFrom, "fr", "from language correct");
+  is(notif.translation.translatedTo, Translation.defaultTargetLanguage, "from language correct");
   checkURLBarIcon();
 
   info("Make the translation succeed and check we are in the 'translated' state.");
-  TranslationStub.finishTranslation();
-  is(notif.state, TranslationStub.STATE_TRANSLATED, "infobar in the translated state");
+  notif.translation.finishTranslation();
+  is(notif.state, notif.translation.STATE_TRANSLATED, "infobar in the translated state");
   checkURLBarIcon(true);
 
   info("Test 'Show original' / 'Show Translation' buttons.");
   // First check 'Show Original' is visible and 'Show Translation' is hidden.
   ok(!notif._getAnonElt("showOriginal").hidden, "'Show Original' button visible");
   ok(notif._getAnonElt("showTranslation").hidden, "'Show Translation' button hidden");
   // Click the button.
   notif._getAnonElt("showOriginal").click();
@@ -132,55 +138,55 @@ function run_tests(aFinishCallback) {
   // Check that the 'Show Original' button is visible again.
   ok(!notif._getAnonElt("showOriginal").hidden, "'Show Original' button visible");
   ok(notif._getAnonElt("showTranslation").hidden, "'Show Translation' button hidden");
 
   info("Check that changing the source language causes a re-translation");
   let from = notif._getAnonElt("fromLanguage");
   from.value = "es";
   from.doCommand();
-  is(notif.state, TranslationStub.STATE_TRANSLATING, "infobar in the translating state");
-  ok(!!TranslationStub.translatedFrom, "Translation.translate has been called");
-  is(TranslationStub.translatedFrom, "es", "from language correct");
-  is(TranslationStub.translatedTo, TranslationStub.defaultTargetLanguage, "to language correct");
+  is(notif.state, notif.translation.STATE_TRANSLATING, "infobar in the translating state");
+  ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
+  is(notif.translation.translatedFrom, "es", "from language correct");
+  is(notif.translation.translatedTo, Translation.defaultTargetLanguage, "to language correct");
   // We want to show the 'translated' icon while re-translating,
   // because we are still displaying the previous translation.
   checkURLBarIcon(true);
-  TranslationStub.finishTranslation();
+  notif.translation.finishTranslation();
   checkURLBarIcon(true);
 
   info("Check that changing the target language causes a re-translation");
   let to = notif._getAnonElt("toLanguage");
   to.value = "pl";
   to.doCommand();
-  is(notif.state, TranslationStub.STATE_TRANSLATING, "infobar in the translating state");
-  ok(!!TranslationStub.translatedFrom, "Translation.translate has been called");
-  is(TranslationStub.translatedFrom, "es", "from language correct");
-  is(TranslationStub.translatedTo, "pl", "to language correct");
+  is(notif.state, notif.translation.STATE_TRANSLATING, "infobar in the translating state");
+  ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
+  is(notif.translation.translatedFrom, "es", "from language correct");
+  is(notif.translation.translatedTo, "pl", "to language correct");
   checkURLBarIcon(true);
-  TranslationStub.finishTranslation();
+  notif.translation.finishTranslation();
   checkURLBarIcon(true);
 
   // Cleanup.
   notif.close();
 
   info("Reopen the info bar to check that it's possible to override the detected language.");
-  notif = TranslationStub.showTranslationUI("fr");
-  is(notif.state, TranslationStub.STATE_OFFER, "the infobar is offering translation");
+  notif = showTranslationUI("fr");
+  is(notif.state, notif.translation.STATE_OFFER, "the infobar is offering translation");
   is(notif._getAnonElt("detectedLanguage").value, "fr", "The detected language is displayed");
   // Change the language and click 'Translate'
   notif._getAnonElt("detectedLanguage").value = "ja";
   notif._getAnonElt("translate").click();
-  is(notif.state, TranslationStub.STATE_TRANSLATING, "the infobar is in the translating state");
-  ok(!!TranslationStub.translatedFrom, "Translation.translate has been called");
-  is(TranslationStub.translatedFrom, "ja", "from language correct");
+  is(notif.state, notif.translation.STATE_TRANSLATING, "the infobar is in the translating state");
+  ok(!!notif.translation.translatedFrom, "Translation.translate has been called");
+  is(notif.translation.translatedFrom, "ja", "from language correct");
   notif.close();
 
   info("Reopen to check the 'Not Now' button closes the notification.");
-  notif = TranslationStub.showTranslationUI("fr");
+  notif = showTranslationUI("fr");
   let notificationBox = gBrowser.getNotificationBox();
   ok(!!notificationBox.getNotificationWithValue("translation"), "there's a 'translate' notification");
   notif._getAnonElt("notNow").click();
   ok(!notificationBox.getNotificationWithValue("translation"), "no 'translate' notification after clicking 'not now'");
 
   info("Check that clicking the url bar icon reopens the info bar");
   checkURLBarIcon();
   // Clicking the anchor element causes a 'showing' event to be sent
--- a/browser/components/translation/translation-infobar.xml
+++ b/browser/components/translation/translation-infobar.xml
@@ -97,30 +97,30 @@
             this.translation = aTranslation;
             let bundle = Cc["@mozilla.org/intl/stringbundle;1"]
                            .getService(Ci.nsIStringBundleService)
                            .createBundle("chrome://global/locale/languageNames.properties");
 
             // Fill the lists of supported source languages.
             let detectedLanguage = this._getAnonElt("detectedLanguage");
             let fromLanguage = this._getAnonElt("fromLanguage");
-            for (let code of this.translation.supportedSourceLanguages) {
+            for (let code of Translation.supportedSourceLanguages) {
               let name = bundle.GetStringFromName(code);
               detectedLanguage.appendItem(name, code);
               fromLanguage.appendItem(name, code);
             }
             detectedLanguage.value = this.translation.detectedLanguage;
 
             // translatedFrom is only set if we have already translated this page.
             if (aTranslation.translatedFrom)
               fromLanguage.value = aTranslation.translatedFrom;
 
             // Fill the list of supporter target languages.
             let toLanguage = this._getAnonElt("toLanguage");
-            for (let code of this.translation.supportedTargetLanguages)
+            for (let code of Translation.supportedTargetLanguages)
               toLanguage.appendItem(bundle.GetStringFromName(code), code);
 
             if (aTranslation.translatedTo)
               toLanguage.value = aTranslation.translatedTo;
 
             if (aTranslation.state)
               this.state = aTranslation.state;
 
@@ -138,17 +138,17 @@
 
       <method name="translate">
         <body>
           <![CDATA[
             if (this.state == this.translation.STATE_OFFER) {
               this._getAnonElt("fromLanguage").value =
                 this._getAnonElt("detectedLanguage").value;
               this._getAnonElt("toLanguage").value =
-                this.translation.defaultTargetLanguage;
+                Translation.defaultTargetLanguage;
             }
 
             this._handleButtonHiding(false);
             this.translation.translate(this._getAnonElt("fromLanguage").value,
                                        this._getAnonElt("toLanguage").value);
           ]]>
         </body>
       </method>
--- a/browser/experiments/Experiments.jsm
+++ b/browser/experiments/Experiments.jsm
@@ -247,16 +247,20 @@ let Experiments = {
  * The policy object allows us to inject fake enviroment data from the
  * outside by monkey-patching.
  */
 
 Experiments.Policy = function () {
   this._log = Log.repository.getLoggerWithMessagePrefix(
     "Browser.Experiments.Policy",
     "Policy #" + gPolicyCounter++ + "::");
+
+  // Set to true to ignore hash verification on downloaded XPIs. This should
+  // not be used outside of testing.
+  this.ignoreHashes = false;
 };
 
 Experiments.Policy.prototype = {
   now: function () {
     return new Date();
   },
 
   random: function () {
@@ -367,29 +371,34 @@ Experiments.Experiments.prototype = {
     gPrefs.observe(PREF_MANIFEST_URI, this.updateManifest, this);
     gPrefs.observe(PREF_ENABLED, this._toggleExperimentsEnabled, this);
 
     gPrefsTelemetry.observe(PREF_TELEMETRY_ENABLED, this._telemetryStatusChanged, this);
 
     AsyncShutdown.profileBeforeChange.addBlocker("Experiments.jsm shutdown",
       this.uninit.bind(this));
 
-    this._startWatchingAddons();
+    this._registerWithAddonManager();
 
-    this._loadTask = Task.spawn(this._loadFromCache.bind(this));
+    let deferred = Promise.defer();
+
+    this._loadTask = this._loadFromCache();
     this._loadTask.then(
       () => {
         this._log.trace("_loadTask finished ok");
         this._loadTask = null;
-        this._run();
+        this._run().then(deferred.resolve, deferred.reject);
       },
       (e) => {
         this._log.error("_loadFromCache caught error: " + e);
+        deferred.reject(e);
       }
     );
+
+    return deferred.promise;
   },
 
   /**
    * Uninitialize this instance.
    *
    * This function is susceptible to race conditions. If it is called multiple
    * times before the previous uninit() has completed or if it is called while
    * an init() operation is being performed, the object may get in bad state
@@ -397,17 +406,17 @@ Experiments.Experiments.prototype = {
    *
    * @return Promise<>
    *         The promise is fulfilled when all pending tasks are finished.
    */
   uninit: Task.async(function* () {
     yield this._loadTask;
 
     if (!this._shutdown) {
-      this._stopWatchingAddons();
+      this._unregisterWithAddonManager();
 
       gPrefs.ignore(PREF_LOGGING, configureLogging);
       gPrefs.ignore(PREF_MANIFEST_URI, this.updateManifest, this);
       gPrefs.ignore(PREF_ENABLED, this._toggleExperimentsEnabled, this);
 
       gPrefsTelemetry.ignore(PREF_TELEMETRY_ENABLED, this._telemetryStatusChanged, this);
 
       if (this._timer) {
@@ -418,22 +427,24 @@ Experiments.Experiments.prototype = {
     this._shutdown = true;
     if (this._mainTask) {
       yield this._mainTask;
     }
 
     this._log.info("Completed uninitialization.");
   }),
 
-  _startWatchingAddons: function () {
+  _registerWithAddonManager: function () {
+    this._log.trace("Registering instance with Addon Manager.");
+
     AddonManager.addAddonListener(this);
     AddonManager.addInstallListener(this);
   },
 
-  _stopWatchingAddons: function () {
+  _unregisterWithAddonManager: function () {
     AddonManager.removeInstallListener(this);
     AddonManager.removeAddonListener(this);
   },
 
   /**
    * Throws an exception if we've already shut down.
    */
   _checkForShutdown: function() {
@@ -807,27 +818,27 @@ Experiments.Experiments.prototype = {
     yield OS.File.writeAtomic(path, data, options);
     this._dirty = false;
     this._log.debug("_saveToCache saved to " + path);
   },
 
   /*
    * Task function, load the cached experiments manifest file from disk.
    */
-  _loadFromCache: function*() {
+  _loadFromCache: Task.async(function* () {
     this._log.trace("_loadFromCache");
     let path = this._cacheFilePath;
     try {
       let result = yield loadJSONAsync(path, { compression: "lz4" });
       this._populateFromCache(result);
     } catch (e if e instanceof OS.File.Error && e.becauseNoSuchFile) {
       // No cached manifest yet.
       this._experiments = new Map();
     }
-  },
+  }),
 
   _populateFromCache: function (data) {
     this._log.trace("populateFromCache() - data: " + JSON.stringify(data));
 
     // If the user has a newer cache version than we can understand, we fail
     // hard; no experiments should be active in this older client.
     if (CACHE_VERSION !== data.version) {
       throw new Error("Experiments::_populateFromCache() - invalid cache version");
@@ -1493,18 +1504,19 @@ Experiments.ExperimentEntry.prototype = 
       gPrefs.set(PREF_ACTIVE_EXPERIMENT, true);
     }.bind(this));
   },
 
   // Async install of the addon for this experiment, part of the start task above.
   _installAddon: function* () {
     let deferred = Promise.defer();
 
-    let install = yield addonInstallForURL(this._manifestData.xpiURL,
-                                           this._manifestData.xpiHash);
+    let hash = this._policy.ignoreHashes ? null : this._manifestData.xpiHash;
+
+    let install = yield addonInstallForURL(this._manifestData.xpiURL, hash);
     gActiveInstallURLs.add(install.sourceURI.spec);
 
     let failureHandler = (install, handler) => {
       let message = "AddonInstall " + handler + " for " + this.id + ", state=" +
                    (install.state || "?") + ", error=" + install.error;
       this._log.error("_installAddon() - " + message);
       this._failedStart = true;
       gActiveInstallURLs.delete(install.sourceURI.spec);
--- a/browser/experiments/test/xpcshell/test_activate.js
+++ b/browser/experiments/test/xpcshell/test_activate.js
@@ -135,9 +135,28 @@ add_task(function* test_startStop() {
   defineNow(gPolicy, futureDate(endDate, MS_IN_ONE_DAY));
   result = yield experiment._shouldStop();
   Assert.equal(result.shouldStop, true, "shouldStop should now be true.");
   maybeStop = yield experiment.maybeStop();
   Assert.equal(maybeStop, true, "Experiment should have been stopped.");
   Assert.equal(experiment.enabled, false, "Experiment should be disabled.");
   addons = yield getExperimentAddons();
   Assert.equal(addons.length, 0, "Experiment add-on is uninstalled.");
+
+  // Ensure hash validation works.
+  // We set an incorrect hash and expect the install to fail.
+  experiment._manifestData.xpiHash = "sha1:41014dcc66b4dcedcd973491a1530a32f0517d8a";
+  let errored = false;
+  try {
+    yield experiment.start();
+  } catch (ex) {
+    errored = true;
+  }
+  Assert.ok(experiment._failedStart, "Experiment failed to start.");
+  Assert.ok(errored, "start() threw an exception.");
+
+  // Make sure "ignore hashes" mode works.
+  gPolicy.ignoreHashes = true;
+  let changes = yield experiment.start();
+  Assert.equal(changes, experiment.ADDON_CHANGE_INSTALL);
+  yield experiment.stop();
+  gPolicy.ignoreHashes = false;
 });
--- a/browser/experiments/test/xpcshell/test_api.js
+++ b/browser/experiments/test/xpcshell/test_api.js
@@ -1361,19 +1361,19 @@ add_task(function* test_unexpectedUninst
 // uninstalled.
 add_task(function* testUnknownExperimentsUninstalled() {
   let experiments = new Experiments.Experiments(gPolicy);
 
   let addons = yield getExperimentAddons();
   Assert.equal(addons.length, 0, "Precondition: No experiment add-ons are present.");
 
   // Simulate us not listening.
-  experiments._stopWatchingAddons();
+  experiments._unregisterWithAddonManager();
   yield AddonTestUtils.installXPIFromURL(gDataRoot + EXPERIMENT1_XPI_NAME, EXPERIMENT1_XPI_SHA1);
-  experiments._startWatchingAddons();
+  experiments._registerWithAddonManager();
 
   addons = yield getExperimentAddons();
   Assert.equal(addons.length, 1, "Experiment 1 installed via AddonManager");
 
   // Simulate no known experiments.
   gManifestObject = {
     "version": 1,
     experiments: [],
@@ -1447,19 +1447,19 @@ add_task(function* testEnabledAfterResta
   let fromManifest = yield experiments.getExperiments();
   Assert.equal(fromManifest.length, 1, "A single experiment is known.");
 
   addons = yield getExperimentAddons();
   Assert.equal(addons.length, 1, "A single experiment add-on is installed.");
   Assert.ok(addons[0].isActive, "That experiment is active.");
 
   dump("Restarting Addon Manager\n");
-  experiments._stopWatchingAddons();
+  experiments._unregisterWithAddonManager();
   restartManager();
-  experiments._startWatchingAddons();
+  experiments._registerWithAddonManager();
 
   addons = yield getExperimentAddons();
   Assert.equal(addons.length, 1, "The experiment is still there after restart.");
   Assert.ok(addons[0].userDisabled, "But it is disabled.");
   Assert.equal(addons[0].isActive, false, "And not active.");
 
   yield experiments.updateManifest();
   Assert.ok(addons[0].isActive, "It activates when the manifest is evaluated.");
--- a/browser/themes/shared/customizableui/panelUIOverlay.inc.css
+++ b/browser/themes/shared/customizableui/panelUIOverlay.inc.css
@@ -50,17 +50,17 @@
 }
 
 @keyframes moveX {
   /* These values are adjusted for the padding on the panel. */
   from { margin-left: -15px; } to { margin-left: calc(100% - 49px); }
 }
 @keyframes moveY {
   /* These values are adjusted for the padding and height of the panel. */
-  from { margin-top: -6px; } to { margin-top: 58px; }
+  from { margin-top: -.5em; } to { margin-top: calc(64px - .5em); }
 }
 
 #PanelUI-button {
   background-image: linear-gradient(to bottom, hsla(0,0%,100%,0), hsla(0,0%,100%,.3) 30%, hsla(0,0%,100%,.3) 70%, hsla(0,0%,100%,0)),
                     linear-gradient(to bottom, hsla(210,54%,20%,0), hsla(210,54%,20%,.3) 30%, hsla(210,54%,20%,.3) 70%, hsla(210,54%,20%,0)),
                     linear-gradient(to bottom, hsla(0,0%,100%,0), hsla(0,0%,100%,.3) 30%, hsla(0,0%,100%,.3) 70%, hsla(0,0%,100%,0));
   background-size: 1px calc(100% - 1px), 1px calc(100% - 1px), 1px  calc(100% - 1px) !important;
   background-position: 0px 0px, 1px 0px, 2px 0px;
--- a/content/base/public/nsIDocumentEncoder.idl
+++ b/content/base/public/nsIDocumentEncoder.idl
@@ -30,17 +30,17 @@ interface nsIDocumentEncoderNodeFixup : 
    * @param [OUT] aSerializeCloneKids True if the document encoder should
    * apply recursive serialization to the children of the fixed up node
    * instead of the children of the original node.
    * @return The resulting fixed up node.
    */
   nsIDOMNode fixupNode(in nsIDOMNode aNode, out boolean aSerializeCloneKids);
 };
 
-[scriptable, uuid(7222bdf1-c2b9-41f1-a40a-a3d65283a95b)]
+[scriptable, uuid(1158bd7e-a08b-4ff6-9417-6f99144cfccc)]
 interface nsIDocumentEncoder : nsISupports
 {
   // Output methods flag bits. There are a frightening number of these,
   // because everyone wants something a little bit different
    
 
   /** 
    * Output only the selection (as opposed to the whole document).
@@ -325,13 +325,28 @@ interface nsIDocumentEncoder : nsISuppor
    *              be stored.
    * @return The document encoded as a string.
    * 
    */
   AString encodeToStringWithContext( out AString aContextString,
                                      out AString aInfoString);
 
   /**
+   * Encode the document into a string of limited size.
+   * @param aMaxLength After aMaxLength characters, the encoder will stop
+   *                   encoding new data.
+   *                   Only values > 0 will be considered.
+   *                   The returned string may be slightly larger than
+   *                   aMaxLength because some serializers (eg. HTML)
+   *                   may need to close some tags after they stop
+   *                   encoding new data, or finish a line (72 columns
+   *                   by default for the plain text serializer).
+   *
+   * @return The document encoded into a string.
+   */
+  AString encodeToStringWithMaxLength(in unsigned long aMaxLength);
+
+  /**
    * Set the fixup object associated with node persistence.
    * @param aFixup The fixup object.
    */
   void setNodeFixup(in nsIDocumentEncoderNodeFixup aFixup);
 };
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -76,17 +76,18 @@ public:
 
 protected:
   void Initialize(bool aClearCachedSerializer = true);
   nsresult SerializeNodeStart(nsINode* aNode, int32_t aStartOffset,
                               int32_t aEndOffset, nsAString& aStr,
                               nsINode* aOriginalNode = nullptr);
   nsresult SerializeToStringRecursive(nsINode* aNode,
                                       nsAString& aStr,
-                                      bool aDontSerializeRoot);
+                                      bool aDontSerializeRoot,
+                                      uint32_t aMaxLength = 0);
   nsresult SerializeNodeEnd(nsINode* aNode, nsAString& aStr);
   // This serializes the content of aNode.
   nsresult SerializeToStringIterative(nsINode* aNode,
                                       nsAString& aStr);
   nsresult SerializeRangeToString(nsRange *aRange,
                                   nsAString& aOutputString);
   nsresult SerializeRangeNodes(nsRange* aRange, 
                                nsINode* aNode, 
@@ -445,18 +446,23 @@ nsDocumentEncoder::SerializeNodeEnd(nsIN
     mSerializer->AppendElementEnd(aNode->AsElement(), aStr);
   }
   return NS_OK;
 }
 
 nsresult
 nsDocumentEncoder::SerializeToStringRecursive(nsINode* aNode,
                                               nsAString& aStr,
-                                              bool aDontSerializeRoot)
+                                              bool aDontSerializeRoot,
+                                              uint32_t aMaxLength)
 {
+  if (aMaxLength > 0 && aStr.Length() >= aMaxLength) {
+    return NS_OK;
+  }
+
   if (!IsVisibleNode(aNode))
     return NS_OK;
 
   nsresult rv = NS_OK;
   bool serializeClonedChildren = false;
   nsINode* maybeFixedNode = nullptr;
 
   // Keep the node from FixupNode alive.
@@ -482,26 +488,31 @@ nsDocumentEncoder::SerializeToStringRecu
         if (!isSelectable){
           aDontSerializeRoot = true;
         }
       }
     }
   }
 
   if (!aDontSerializeRoot) {
-    rv = SerializeNodeStart(maybeFixedNode, 0, -1, aStr, aNode);
+    int32_t endOffset = -1;
+    if (aMaxLength > 0) {
+      MOZ_ASSERT(aMaxLength >= aStr.Length());
+      endOffset = aMaxLength - aStr.Length();
+    }
+    rv = SerializeNodeStart(maybeFixedNode, 0, endOffset, aStr, aNode);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsINode* node = serializeClonedChildren ? maybeFixedNode : aNode;
 
   for (nsINode* child = nsNodeUtils::GetFirstChildOfTemplateOrNode(node);
        child;
        child = child->GetNextSibling()) {
-    rv = SerializeToStringRecursive(child, aStr, false);
+    rv = SerializeToStringRecursive(child, aStr, false, aMaxLength);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (!aDontSerializeRoot) {
     rv = SerializeNodeEnd(node, aStr);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
@@ -1012,16 +1023,23 @@ nsDocumentEncoder::SerializeRangeToStrin
   NS_ENSURE_SUCCESS(rv, rv);
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsDocumentEncoder::EncodeToString(nsAString& aOutputString)
 {
+  return EncodeToStringWithMaxLength(0, aOutputString);
+}
+
+NS_IMETHODIMP
+nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
+                                               nsAString& aOutputString)
+{
   if (!mDocument)
     return NS_ERROR_NOT_INITIALIZED;
 
   aOutputString.Truncate();
 
   nsString output;
   static const size_t bufferSize = 2048;
   if (!mCachedBuffer) {
@@ -1141,17 +1159,17 @@ nsDocumentEncoder::EncodeToString(nsAStr
     } else {
       rv = SerializeToStringRecursive(mNode, output, mNodeIsContainer);
     }
     mNode = nullptr;
   } else {
     rv = mSerializer->AppendDocumentStart(mDocument, output);
 
     if (NS_SUCCEEDED(rv)) {
-      rv = SerializeToStringRecursive(mDocument, output, false);
+      rv = SerializeToStringRecursive(mDocument, output, false, aMaxLength);
     }
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
   rv = mSerializer->Flush(output);
  
   mCachedBuffer = nsStringBuffer::FromString(output);
   // We have to be careful how we set aOutputString, because we don't
--- a/content/base/src/nsPlainTextSerializer.cpp
+++ b/content/base/src/nsPlainTextSerializer.cpp
@@ -273,17 +273,18 @@ nsPlainTextSerializer::AppendText(nsICon
   nsresult rv = NS_OK;
 
   nsIContent* content = aText;
   const nsTextFragment* frag;
   if (!content || !(frag = content->GetText())) {
     return NS_ERROR_FAILURE;
   }
   
-  int32_t endoffset = (aEndOffset == -1) ? frag->GetLength() : aEndOffset;
+  int32_t fragLength = frag->GetLength();
+  int32_t endoffset = (aEndOffset == -1) ? fragLength : std::min(aEndOffset, fragLength);
   NS_ASSERTION(aStartOffset <= endoffset, "A start offset is beyond the end of the text fragment!");
 
   int32_t length = endoffset - aStartOffset;
   if (length <= 0) {
     return NS_OK;
   }
 
   nsAutoString textstr;
--- a/content/base/src/nsXMLContentSerializer.cpp
+++ b/content/base/src/nsXMLContentSerializer.cpp
@@ -133,17 +133,18 @@ nsXMLContentSerializer::AppendTextData(n
                                        bool aTranslateEntities)
 {
   nsIContent* content = aNode;
   const nsTextFragment* frag;
   if (!content || !(frag = content->GetText())) {
     return NS_ERROR_FAILURE;
   }
 
-  int32_t endoffset = (aEndOffset == -1) ? frag->GetLength() : aEndOffset;
+  int32_t fragLength = frag->GetLength();
+  int32_t endoffset = (aEndOffset == -1) ? fragLength : std::min(aEndOffset, fragLength);
   int32_t length = endoffset - aStartOffset;
 
   NS_ASSERTION(aStartOffset >= 0, "Negative start offset for text fragment!");
   NS_ASSERTION(aStartOffset <= endoffset, "A start offset is beyond the end of the text fragment!");
 
   if (length <= 0) {
     // XXX Zero is a legal value, maybe non-zero values should be an
     // error.
@@ -295,22 +296,26 @@ nsXMLContentSerializer::AppendComment(ns
   nsCOMPtr<nsIDOMComment> comment = do_QueryInterface(aComment);
   NS_ENSURE_ARG(comment);
   nsresult rv;
   nsAutoString data;
 
   rv = comment->GetData(data);
   if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
 
-  if (aStartOffset || (aEndOffset != -1)) {
-    int32_t length = (aEndOffset == -1) ? data.Length() : aEndOffset;
+  int32_t dataLength = data.Length();
+  if (aStartOffset || (aEndOffset != -1 && aEndOffset < dataLength)) {
+    int32_t length =
+      (aEndOffset == -1) ? dataLength : std::min(aEndOffset, dataLength);
     length -= aStartOffset;
 
     nsAutoString frag;
-    data.Mid(frag, aStartOffset, length);
+    if (length > 0) {
+      data.Mid(frag, aStartOffset, length);
+    }
     data.Assign(frag);
   }
 
   MaybeAddNewlineForRootNode(aStr);
 
   NS_NAMED_LITERAL_STRING(startComment, "<!--");
 
   if (mPreLevel > 0 || mDoRaw) {
--- a/content/base/test/mochitest.ini
+++ b/content/base/test/mochitest.ini
@@ -554,16 +554,17 @@ skip-if = (buildapp == 'b2g' && toolkit 
 skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 904183 # b2g(clipboard undefined) b2g-debug(clipboard undefined) b2g-desktop(clipboard undefined)
 [test_copypaste.xhtml]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 904183 # b2g(bug 904183) b2g-debug(bug 904183) b2g-desktop(bug 904183)
 [test_createHTMLDocument.html]
 [test_declare_stylesheet_obsolete.html]
 [test_domparser_null_char.html]
 [test_domparsing.html]
 [test_elementTraversal.html]
+[test_encodeToStringWithMaxLength.html]
 [test_fileapi.html]
 skip-if = e10s
 [test_fileapi_slice.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 775227
 [test_getElementById.html]
 [test_html_colors_quirks.html]
 [test_html_colors_standards.html]
 [test_html_in_xhr.html]
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_encodeToStringWithMaxLength.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=995321
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 995321 - encodeToStringWithMaxLength</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+  function getEncoder() {
+    const de = SpecialPowers.Ci.nsIDocumentEncoder;
+    const Cc = SpecialPowers.Cc;
+
+    // Create a plaintext encoder without flags.
+    var encoder = Cc["@mozilla.org/layout/documentEncoder;1?type=text/plain"]
+                  .createInstance(de);
+    encoder.init(document, "text/plain", 0);
+    return encoder;
+  }
+
+  function testPlaintextSerializerWithMaxLength() {
+    var string = getEncoder().encodeToString();
+
+    var shorterString = getEncoder().encodeToStringWithMaxLength(1);
+    ok(shorterString.length < 1 + 72,
+       "test length is in the expected range after limiting the length to 1");
+    ok(string.startsWith(shorterString.trimRight()),
+       "the shorter string has the expected content");
+
+    shorterString = getEncoder().encodeToStringWithMaxLength(300);
+    ok(shorterString.length < 300 + 72,
+       "test length is in the expected range after limiting the length to 300");
+    ok(string.startsWith(shorterString.trimRight()),
+       "the shorter string has the expected content");
+
+    is(getEncoder().encodeToStringWithMaxLength(0), string,
+       "limiting the length to 0 should be ignored");
+
+    is(getEncoder().encodeToStringWithMaxLength(10000), string,
+       "limiting the length to a huge value should return the whole page");
+
+    SimpleTest.finish();
+  }
+
+  addLoadEvent(testPlaintextSerializerWithMaxLength);
+  SimpleTest.waitForExplicitFinish();
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=995321">Mozilla Bug 995321</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+The <em>Mozilla</em> project is a global community of <strong>people</strong> who believe that openness, innovation, and opportunity are key to the continued health of the Internet. We have worked together since 1998 to ensure that the Internet is developed in a way that benefits everyone. We are best known for creating the Mozilla Firefox web browser.
+
+The Mozilla project uses a community-based approach to create world-class open source software and to develop new types of collaborative activities. We create communities of people involved in making the Internet experience better for all of us.
+
+As a result of these efforts, we have distilled a set of principles that we believe are critical for the Internet to continue to benefit the public good as well as commercial aspects of life. We set out these principles below.
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/mobile/android/base/tests/testPictureLinkContextMenu.java
+++ b/mobile/android/base/tests/testPictureLinkContextMenu.java
@@ -5,41 +5,39 @@ public class testPictureLinkContextMenu 
 
     // Test website strings
     private static String PICTURE_PAGE_URL;
     private static String BLANK_PAGE_URL;
     private static final String PICTURE_PAGE_TITLE = "Picture Link";
     private static final String tabs [] = { "Image", "Link" };
     private static final String photoMenuItems [] = { "Copy Image Location", "Share Image", "Set Image As", "Save Image" };
     private static final String linkMenuItems [] = { "Open Link in New Tab", "Open Link in Private Tab", "Copy Link", "Share Link", "Bookmark Link"};
-    private static final String linkTitle = "^Link$";
+    private static final String imageTitle = "^Image$";
 
     public void testPictureLinkContextMenu() {
         blockForGeckoReady();
 
         PICTURE_PAGE_URL=getAbsoluteUrl("/robocop/robocop_picture_link.html");
         BLANK_PAGE_URL=getAbsoluteUrl("/robocop/robocop_blank_02.html");
         loadAndPaint(PICTURE_PAGE_URL);
         verifyPageTitle(PICTURE_PAGE_TITLE);
 
+        switchTabs(imageTitle);
         verifyContextMenuItems(photoMenuItems);
         verifyTabs(tabs);
+        switchTabs(imageTitle);
         verifyCopyOption(photoMenuItems[0], "Firefox.jpg"); // Test the "Copy Image Location" option
+        switchTabs(imageTitle);
         verifyShareOption(photoMenuItems[1], PICTURE_PAGE_TITLE); // Test the "Share Image" option
 
-        switchTabs(linkTitle);
         verifyContextMenuItems(linkMenuItems);
         openTabFromContextMenu(linkMenuItems[0],2); // Test the "Open in New Tab" option - expecting 2 tabs: the original and the new one
-        switchTabs(linkTitle);
         openTabFromContextMenu(linkMenuItems[1],2); // Test the "Open in Private Tab" option - expecting only 2 tabs in normal mode
-        switchTabs(linkTitle);
         verifyCopyOption(linkMenuItems[2], BLANK_PAGE_URL); // Test the "Copy Link" option
-        switchTabs(linkTitle);
         verifyShareOption(linkMenuItems[3], PICTURE_PAGE_TITLE); // Test the "Share Link" option
-        switchTabs(linkTitle);
         verifyBookmarkLinkOption(linkMenuItems[4],BLANK_PAGE_URL); // Test the "Bookmark Link" option
     }
 
     @Override
     public void tearDown() throws Exception {
         mDatabaseHelper.deleteBookmark(BLANK_PAGE_URL);
         super.tearDown();
     }
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2097,16 +2097,21 @@ var NativeWindow = {
     },
 
     set _target(aTarget) {
       if (aTarget)
         this._targetRef = Cu.getWeakReference(aTarget);
       else this._targetRef = null;
     },
 
+    get defaultContext() {
+      delete this.defaultContext;
+      return this.defaultContext = Strings.browser.GetStringFromName("browser.menu.context.default");
+    },
+
     /* Gets menuitems for an arbitrary node
      * Parameters:
      *   element - The element to look at. If this element has a contextmenu attribute, the
      *             corresponding contextmenu will be used.
      */
     _getHTMLContextMenuItemsForElement: function(element) {
       let htmlMenu = element.contextMenu;
       if (!htmlMenu) {
@@ -2178,17 +2183,17 @@ var NativeWindow = {
       }
 
       // Otherwise we try the nodeName
       try {
         return Strings.browser.GetStringFromName("browser.menu.context." + element.nodeName.toLowerCase());
       } catch(ex) { }
 
       // Fallback to the default
-      return Strings.browser.GetStringFromName("browser.menu.context.default");
+      return this.defaultContext;
     },
 
     // Adds context menu items added through the add-on api
     _getNativeContextMenuItems: function(element, x, y) {
       let res = [];
       for (let itemId of Object.keys(this.items)) {
         let item = this.items[itemId];
 
@@ -2333,17 +2338,18 @@ var NativeWindow = {
      * menus, will return an array with appropriate tabs/items inside it. i.e. :
      * [
      *    { label: "link", items: [...] },
      *    { label: "image", items: [...] }
      * ]
      */
     _reformatList: function(target) {
       let contexts = Object.keys(this.menus);
-      if (contexts.length == 1) {
+
+      if (contexts.length === 1) {
         // If there's only one context, we'll only show a single flat single select list
         return this._reformatMenuItems(target, this.menus[contexts[0]]);
       }
 
       // If there are multiple contexts, we'll only show a tabbed ui with multiple lists
       return this._reformatListAsTabs(target, this.menus);
     },
 
@@ -2352,22 +2358,34 @@ var NativeWindow = {
      * { link: [...], image: [...] } becomes
      * [ { label: "link", items: [...] } ]
      *
      * Also reformats items and resolves any parmaeters that aren't known until display time
      * (for instance Helper app menu items adjust their title to reflect what Helper App can be used for this link).
      */
     _reformatListAsTabs: function(target, menus) {
       let itemArray = [];
-      for (let context in menus) {
+
+      // Sort the keys so that "link" is always first
+      let contexts = Object.keys(this.menus);
+      contexts.sort((context1, context2) => {
+        if (context1 === this.defaultContext) {
+          return -1;
+        } else if (context2 === this.defaultContext) {
+          return 1;
+        }
+        return 0;
+      });
+
+      contexts.forEach(context => {
         itemArray.push({
           label: context,
           items: this._reformatMenuItems(target, menus[context])
         });
-      }
+      });
 
       return itemArray;
     },
 
     /* Reformats an array of ContextMenuItems into an array that can be handled by Prompt.jsm. Also reformats items
      * and resolves any parmaeters that aren't known until display time
      * (for instance Helper app menu items adjust their title to reflect what Helper App can be used for this link).
      */
@@ -8381,18 +8399,20 @@ HTMLContextMenuItem.prototype = Object.c
 
           let elt = this.menuElementRef.get();
           let target = this.targetElementRef.get();
           if (!elt) {
             return;
           }
 
           var items = NativeWindow.contextmenus._getHTMLContextMenuItemsForMenu(elt, target);
+          // This menu will always only have one context, but we still make sure its the "right" one.
+          var context = NativeWindow.contextmenus._getContextType(target);
           if (items.length > 0) {
-            NativeWindow.contextmenus._addMenuItems(items, "link");
+            NativeWindow.contextmenus._addMenuItems(items, context);
           }
 
         } catch(ex) {
           Cu.reportError(ex);
         }
       } else {
         // otherwise just click the menu item
         elt.click();
index 75caa046e715eb63c24749cfaf688bf3efad0325..0243a84c873b939bcf190c0d02f47b869f5da899
GIT binary patch
literal 121856
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
W1fCmc>;t(>RP#Z`k@^2k_<sO@{$)7;
--- a/other-licenses/7zstub/src/7zip/Bundles/SFXSetup-moz/Main.cpp
+++ b/other-licenses/7zstub/src/7zip/Bundles/SFXSetup-moz/Main.cpp
@@ -237,20 +237,26 @@ int APIENTRY WinMain(
   {
     assumeYes = true;
     switches = switches.Mid(2);
     switches.Trim();
   }
 
   /* BEGIN Mozilla customizations */
   bool showProgress = true;
+  bool extractOnly = false;
   if (switches.Left(3).CompareNoCase(UString(L"-ms")) == 0 ||
-	  switches.Left(4).CompareNoCase(UString(L"/INI")) == 0 ||
-	  switches.Left(2).CompareNoCase(UString(L"/S")) == 0)
+      switches.Left(4).CompareNoCase(UString(L"/ini")) == 0 ||
+      switches.Left(2).CompareNoCase(UString(L"/s")) == 0) {
     showProgress = false;
+  } else if (switches.Left(12).CompareNoCase(UString(L"/extractdir=")) == 0) {
+    assumeYes = true;
+    showProgress = false;
+    extractOnly = true;
+  }
   /* END Mozilla customizations */
 
   AString config;
   if (!ReadDataString(fullPath, kStartID, kEndID, config))
   {
     if (!assumeYes)
       MyMessageBox(L"Can't load config info");
     return 1;
@@ -285,26 +291,30 @@ int APIENTRY WinMain(
     
     #ifdef _SHELL_EXECUTE
     executeFile = GetTextConfigValue(pairs, L"ExecuteFile");
     executeParameters = GetTextConfigValue(pairs, L"ExecuteParameters") + switches;
     #endif
   }
 
   NFile::NDirectory::CTempDirectory tempDir;
-  if (!tempDir.Create(kTempDirPrefix))
+  /* Mozilla customizations - Added !extractOnly */
+  if (!extractOnly && !tempDir.Create(kTempDirPrefix))
   {
     if (!assumeYes)
       MyMessageBox(L"Can not create temp folder archive");
     return 1;
   }
 
+  /* BEGIN Mozilla customizations */
+  UString tempDirPath = (extractOnly ? switches.Mid(12) : GetUnicodeString(tempDir.GetPath()));
+  /* END Mozilla customizations */
+
   COpenCallbackGUI openCallback;
 
-  UString tempDirPath = GetUnicodeString(tempDir.GetPath());
   bool isCorrupt = false;
   UString errorMessage;
   HRESULT result = ExtractArchive(fullPath, tempDirPath, &openCallback, showProgress, 
       isCorrupt, errorMessage);
 
   if (result != S_OK)
   {
     if (!assumeYes)
@@ -315,16 +325,23 @@ int APIENTRY WinMain(
         result = E_FAIL;
       }
       if (result != E_ABORT && !errorMessage.IsEmpty())
         ::MessageBoxW(0, errorMessage, NWindows::MyLoadStringW(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR);
     }
     return 1;
   }
 
+  /* BEGIN Mozilla customizations */
+  // The code immediately above handles the error case for extraction.
+  if (extractOnly) {
+    return 0;
+  }
+  /* END Mozilla customizations */
+
   CCurrentDirRestorer currentDirRestorer;
 
   if (!SetCurrentDirectory(tempDir.GetPath()))
     return 1;
   
   HANDLE hProcess = 0;
 #ifdef _SHELL_EXECUTE
   if (!executeFile.IsEmpty())
--- a/other-licenses/7zstub/src/7zip/FileManager/Resource/ProgressDialog/ProgressDialog.cpp
+++ b/other-licenses/7zstub/src/7zip/FileManager/Resource/ProgressDialog/ProgressDialog.cpp
@@ -159,17 +159,17 @@ bool CProgressDialog::OnButtonClicked(in
   switch(buttonID)
   {
     case IDCANCEL:
     {
       bool paused = ProgressSynch.GetPaused();;
       ProgressSynch.SetPaused(true);
       int res = ::MessageBoxW(HWND(*this), 
           L"Are you sure you want to cancel?", 
-          _title, MB_YESNOCANCEL);
+          _title, MB_YESNO);
       ProgressSynch.SetPaused(paused);
-      if (res == IDCANCEL || res == IDNO)
+      if (res == IDNO)
         return true;
       break;
     }
   }
   return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
 }
--- a/services/sync/modules/policies.js
+++ b/services/sync/modules/policies.js
@@ -497,16 +497,23 @@ this.ErrorHandler = function ErrorHandle
 ErrorHandler.prototype = {
   MINIMUM_ALERT_INTERVAL_MSEC: 604800000,   // One week.
 
   /**
    * Flag that turns on error reporting for all errors, incl. network errors.
    */
   dontIgnoreErrors: false,
 
+  /**
+   * Flag that indicates if we have already reported a prolonged failure.
+   * Once set, we don't report it again, meaning this error is only reported
+   * one per run.
+   */
+  didReportProlongedError: false,
+
   init: function init() {
     Svc.Obs.add("weave:engine:sync:applied", this);
     Svc.Obs.add("weave:engine:sync:error", this);
     Svc.Obs.add("weave:service:login:error", this);
     Svc.Obs.add("weave:service:sync:error", this);
     Svc.Obs.add("weave:service:sync:finish", this);
 
     this.initLogs();
@@ -767,17 +774,23 @@ ErrorHandler.prototype = {
     if (this.dontIgnoreErrors) {
       return true;
     }
 
     let lastSync = Svc.Prefs.get("lastSync");
     if (lastSync && ((Date.now() - Date.parse(lastSync)) >
         Svc.Prefs.get("errorhandler.networkFailureReportTimeout") * 1000)) {
       Status.sync = PROLONGED_SYNC_FAILURE;
-      this._log.trace("shouldReportError: true (prolonged sync failure).");
+      if (this.didReportProlongedError) {
+        this._log.trace("shouldReportError: false (prolonged sync failure, but" +
+                        " we've already reported it).");
+        return false;
+      }
+      this._log.trace("shouldReportError: true (first prolonged sync failure).");
+      this.didReportProlongedError = true;
       return true;
     }
 
     // We got a 401 mid-sync. Wait for the next sync before actually handling
     // an error. This assumes that we'll get a 401 again on a login fetch in
     // order to report the error.
     if (!this.service.clusterURL) {
       this._log.trace("shouldReportError: false (no cluster URL; " +
--- a/services/sync/tests/unit/test_errorhandler.js
+++ b/services/sync/tests/unit/test_errorhandler.js
@@ -145,16 +145,17 @@ function generateAndUploadKeys() {
   serverKeys.encrypt(Service.identity.syncKeyBundle);
   return serverKeys.upload(Service.resource(Service.cryptoKeysURL)).success;
 }
 
 function clean() {
   Service.startOver();
   Status.resetSync();
   Status.resetBackoff();
+  errorHandler.didReportProlongedError = false;
 }
 
 add_identity_test(this, function test_401_logout() {
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // By calling sync, we ensure we're logged in.
   Service.sync();
@@ -292,129 +293,161 @@ add_identity_test(this, function test_sh
   // Test dontIgnoreErrors, network, prolonged, sync error reported
   Status.resetSync();
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = true;
   Status.sync = LOGIN_FAILED_NETWORK_ERROR;
   do_check_true(errorHandler.shouldReportError());
 
   // Test non-network, prolonged, login error reported
+  do_check_false(errorHandler.didReportProlongedError);
   Status.resetSync();
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = false;
   Status.login = LOGIN_FAILED_NO_PASSWORD;
   do_check_true(errorHandler.shouldReportError());
+  do_check_true(errorHandler.didReportProlongedError);
+
+  // Second time with prolonged error and without resetting
+  // didReportProlongedError, sync error should not be reported.
+  Status.resetSync();
+  setLastSync(PROLONGED_ERROR_DURATION);
+  errorHandler.dontIgnoreErrors = false;
+  Status.login = LOGIN_FAILED_NO_PASSWORD;
+  do_check_false(errorHandler.shouldReportError());
+  do_check_true(errorHandler.didReportProlongedError);
 
   // Test non-network, prolonged, sync error reported
   Status.resetSync();
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = false;
+  errorHandler.didReportProlongedError = false;
   Status.sync = CREDENTIALS_CHANGED;
   do_check_true(errorHandler.shouldReportError());
+  do_check_true(errorHandler.didReportProlongedError);
+  errorHandler.didReportProlongedError = false;
 
   // Test network, prolonged, login error reported
   Status.resetSync();
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = false;
   Status.login = LOGIN_FAILED_NETWORK_ERROR;
   do_check_true(errorHandler.shouldReportError());
+  do_check_true(errorHandler.didReportProlongedError);
+  errorHandler.didReportProlongedError = false;
 
   // Test network, prolonged, sync error reported
   Status.resetSync();
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = false;
   Status.sync = LOGIN_FAILED_NETWORK_ERROR;
   do_check_true(errorHandler.shouldReportError());
+  do_check_true(errorHandler.didReportProlongedError);
+  errorHandler.didReportProlongedError = false;
 
   // Test non-network, non-prolonged, login error reported
   Status.resetSync();
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = false;
   Status.login = LOGIN_FAILED_NO_PASSWORD;
   do_check_true(errorHandler.shouldReportError());
+  do_check_false(errorHandler.didReportProlongedError);
 
   // Test non-network, non-prolonged, sync error reported
   Status.resetSync();
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = false;
   Status.sync = CREDENTIALS_CHANGED;
   do_check_true(errorHandler.shouldReportError());
+  do_check_false(errorHandler.didReportProlongedError);
 
   // Test network, non-prolonged, login error reported
   Status.resetSync();
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = false;
   Status.login = LOGIN_FAILED_NETWORK_ERROR;
   do_check_false(errorHandler.shouldReportError());
+  do_check_false(errorHandler.didReportProlongedError);
 
   // Test network, non-prolonged, sync error reported
   Status.resetSync();
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = false;
   Status.sync = LOGIN_FAILED_NETWORK_ERROR;
   do_check_false(errorHandler.shouldReportError());
+  do_check_false(errorHandler.didReportProlongedError);
 
   // Test server maintenance, sync errors are not reported
   Status.resetSync();
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = false;
   Status.sync = SERVER_MAINTENANCE;
   do_check_false(errorHandler.shouldReportError());
+  do_check_false(errorHandler.didReportProlongedError);
 
   // Test server maintenance, login errors are not reported
   Status.resetSync();
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = false;
   Status.login = SERVER_MAINTENANCE;
   do_check_false(errorHandler.shouldReportError());
+  do_check_false(errorHandler.didReportProlongedError);
 
   // Test prolonged, server maintenance, sync errors are reported
   Status.resetSync();
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = false;
   Status.sync = SERVER_MAINTENANCE;
   do_check_true(errorHandler.shouldReportError());
+  do_check_true(errorHandler.didReportProlongedError);
+  errorHandler.didReportProlongedError = false;
 
   // Test prolonged, server maintenance, login errors are reported
   Status.resetSync();
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = false;
   Status.login = SERVER_MAINTENANCE;
   do_check_true(errorHandler.shouldReportError());
+  do_check_true(errorHandler.didReportProlongedError);
+  errorHandler.didReportProlongedError = false;
 
   // Test dontIgnoreErrors, server maintenance, sync errors are reported
   Status.resetSync();
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = true;
   Status.sync = SERVER_MAINTENANCE;
   do_check_true(errorHandler.shouldReportError());
+  // dontIgnoreErrors means we don't set didReportProlongedError
+  do_check_false(errorHandler.didReportProlongedError);
 
   // Test dontIgnoreErrors, server maintenance, login errors are reported
   Status.resetSync();
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = true;
   Status.login = SERVER_MAINTENANCE;
   do_check_true(errorHandler.shouldReportError());
+  do_check_false(errorHandler.didReportProlongedError);
 
   // Test dontIgnoreErrors, prolonged, server maintenance,
   // sync errors are reported
   Status.resetSync();
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = true;
   Status.sync = SERVER_MAINTENANCE;
   do_check_true(errorHandler.shouldReportError());
+  do_check_false(errorHandler.didReportProlongedError);
 
   // Test dontIgnoreErrors, prolonged, server maintenance,
   // login errors are reported
   Status.resetSync();
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = true;
   Status.login = SERVER_MAINTENANCE;
   do_check_true(errorHandler.shouldReportError());
-
+  do_check_false(errorHandler.didReportProlongedError);
 });
 
 add_identity_test(this, function test_shouldReportError_master_password() {
   _("Test error ignored due to locked master password");
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // Monkey patch Service.verifyLogin to imitate
@@ -620,16 +653,17 @@ add_task(function test_login_prolonged_n
   let server = sync_httpd_setup();
   yield setUp(server);
   Service.identity.basicPassword = null;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
     Svc.Obs.remove("weave:ui:login:error", onSyncError);
     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
+    do_check_true(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
@@ -646,16 +680,17 @@ add_task(function test_sync_prolonged_no
   do_check_true(Service.isLoggedIn);
 
   generateCredentialsChangedFailure();
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
     Svc.Obs.remove("weave:ui:sync:error", onSyncError);
     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
+    do_check_true(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
@@ -666,16 +701,17 @@ add_identity_test(this, function test_lo
   yield configureIdentity({username: "johndoe"});
   Service.serverURL  = FAKE_SERVER_URL;
   Service.clusterURL = FAKE_SERVER_URL;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
     Svc.Obs.remove("weave:ui:login:error", onSyncError);
     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
+    do_check_true(errorHandler.didReportProlongedError);
 
     clean();
     deferred.resolve();
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
@@ -683,16 +719,17 @@ add_identity_test(this, function test_lo
 
 add_test(function test_sync_prolonged_network_error() {
   // Test prolonged, network errors are reported
   Services.io.offline = true;
 
   Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
     Svc.Obs.remove("weave:ui:sync:error", onSyncError);
     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
+    do_check_true(errorHandler.didReportProlongedError);
 
     Services.io.offline = false;
     clean();
     run_next_test();
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
@@ -703,16 +740,17 @@ add_task(function test_login_non_network
   let server = sync_httpd_setup();
   yield setUp(server);
   Service.identity.basicPassword = null;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
     Svc.Obs.remove("weave:ui:login:error", onSyncError);
     do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
@@ -729,16 +767,17 @@ add_task(function test_sync_non_network_
   do_check_true(Service.isLoggedIn);
 
   generateCredentialsChangedFailure();
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
     Svc.Obs.remove("weave:ui:sync:error", onSyncError);
     do_check_eq(Status.sync, CREDENTIALS_CHANGED);
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
@@ -750,16 +789,17 @@ add_identity_test(this, function test_lo
   Service.clusterURL = FAKE_SERVER_URL;
 
   let deferred = Promise.defer();
   // Test network errors are not reported.
   Svc.Obs.add("weave:ui:clear-error", function onClearError() {
     Svc.Obs.remove("weave:ui:clear-error", onClearError);
 
     do_check_eq(Status.login, LOGIN_FAILED_NETWORK_ERROR);
+    do_check_false(errorHandler.didReportProlongedError);
 
     Services.io.offline = false;
     clean();
     deferred.resolve()
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
@@ -768,16 +808,17 @@ add_identity_test(this, function test_lo
 
 add_test(function test_sync_network_error() {
   // Test network errors are not reported.
   Services.io.offline = true;
 
   Svc.Obs.add("weave:ui:sync:finish", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:sync:finish", onUIUpdate);
     do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
+    do_check_false(errorHandler.didReportProlongedError);
 
     Services.io.offline = false;
     clean();
     run_next_test();
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
@@ -802,16 +843,17 @@ add_identity_test(this, function test_sy
   do_check_eq(Status.service, STATUS_OK);
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:sync:finish", function onSyncFinish() {
     Svc.Obs.remove("weave:ui:sync:finish", onSyncFinish);
 
     do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
     do_check_eq(Status.sync, SERVER_MAINTENANCE);
+    do_check_false(errorHandler.didReportProlongedError);
 
     Svc.Obs.remove("weave:ui:sync:error", onSyncError);
     clean();
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
@@ -845,16 +887,17 @@ add_identity_test(this, function test_in
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:clear-error", function onLoginFinish() {
     Svc.Obs.remove("weave:ui:clear-error", onLoginFinish);
 
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, LOGIN_FAILED);
     do_check_eq(Status.login, SERVER_MAINTENANCE);
+    do_check_false(errorHandler.didReportProlongedError);
 
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     clean();
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
@@ -887,16 +930,17 @@ add_identity_test(this, function test_me
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:clear-error", function onLoginFinish() {
     Svc.Obs.remove("weave:ui:clear-error", onLoginFinish);
 
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, LOGIN_FAILED);
     do_check_eq(Status.login, SERVER_MAINTENANCE);
+    do_check_false(errorHandler.didReportProlongedError);
 
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     clean();
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
@@ -932,16 +976,17 @@ add_identity_test(this, function test_cr
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:clear-error", function onLoginFinish() {
     Svc.Obs.remove("weave:ui:clear-error", onLoginFinish);
 
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, LOGIN_FAILED);
     do_check_eq(Status.login, SERVER_MAINTENANCE);
+    do_check_false(errorHandler.didReportProlongedError);
 
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     clean();
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
@@ -959,16 +1004,17 @@ add_task(function test_sync_prolonged_se
   engine.exception = {status: 503,
                       headers: {"retry-after": BACKOFF}};
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
     do_check_eq(Status.service, SYNC_FAILED);
     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
+    do_check_true(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
@@ -993,16 +1039,17 @@ add_identity_test(this, function test_in
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, SYNC_FAILED);
     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
+    do_check_true(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1028,16 +1075,17 @@ add_identity_test(this, function test_me
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, SYNC_FAILED);
     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
+    do_check_true(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1065,16 +1113,17 @@ add_identity_test(this, function test_do
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, SYNC_FAILED);
     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
+    do_check_true(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1100,16 +1149,17 @@ add_identity_test(this, function test_up
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, SYNC_FAILED);
     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
+    do_check_true(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1136,16 +1186,17 @@ add_identity_test(this, function test_wi
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, SYNC_FAILED);
     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
+    do_check_true(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1178,16 +1229,17 @@ add_identity_test(this, function test_wi
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, SYNC_FAILED);
     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
     do_check_eq(Svc.Prefs.get("firstSync"), "wipeRemote");
+    do_check_true(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1209,16 +1261,17 @@ add_task(function test_sync_syncAndRepor
   engine.exception = {status: 503,
                       headers: {"retry-after": BACKOFF}};
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
     do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
     do_check_eq(Status.sync, SERVER_MAINTENANCE);
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
@@ -1244,16 +1297,17 @@ add_identity_test(this, function test_in
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, LOGIN_FAILED);
     do_check_eq(Status.login, SERVER_MAINTENANCE);
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1280,16 +1334,17 @@ add_identity_test(this, function test_me
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, LOGIN_FAILED);
     do_check_eq(Status.login, SERVER_MAINTENANCE);
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1318,16 +1373,17 @@ add_identity_test(this, function test_do
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, LOGIN_FAILED);
     do_check_eq(Status.login, SERVER_MAINTENANCE);
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1354,16 +1410,17 @@ add_identity_test(this, function test_up
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, LOGIN_FAILED);
     do_check_eq(Status.login, SERVER_MAINTENANCE);
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1390,16 +1447,17 @@ add_identity_test(this, function test_wi
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, LOGIN_FAILED);
     do_check_eq(Status.login, SERVER_MAINTENANCE);
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1431,16 +1489,17 @@ add_identity_test(this, function test_wi
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, SYNC_FAILED);
     do_check_eq(Status.sync, SERVER_MAINTENANCE);
     do_check_eq(Svc.Prefs.get("firstSync"), "wipeRemote");
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1462,16 +1521,19 @@ add_task(function test_sync_syncAndRepor
   engine.exception = {status: 503,
                       headers: {"retry-after": BACKOFF}};
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
     do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
     do_check_eq(Status.sync, SERVER_MAINTENANCE);
+    // syncAndReportErrors means dontIgnoreErrors, which means
+    // didReportProlongedError not touched.
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
@@ -1497,16 +1559,19 @@ add_identity_test(this, function test_in
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, LOGIN_FAILED);
     do_check_eq(Status.login, SERVER_MAINTENANCE);
+    // syncAndReportErrors means dontIgnoreErrors, which means
+    // didReportProlongedError not touched.
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1533,16 +1598,19 @@ add_identity_test(this, function test_me
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, LOGIN_FAILED);
     do_check_eq(Status.login, SERVER_MAINTENANCE);
+    // syncAndReportErrors means dontIgnoreErrors, which means
+    // didReportProlongedError not touched.
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1571,16 +1639,19 @@ add_identity_test(this, function test_do
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, LOGIN_FAILED);
     do_check_eq(Status.login, SERVER_MAINTENANCE);
+    // syncAndReportErrors means dontIgnoreErrors, which means
+    // didReportProlongedError not touched.
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1607,16 +1678,19 @@ add_identity_test(this, function test_up
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, LOGIN_FAILED);
     do_check_eq(Status.login, SERVER_MAINTENANCE);
+    // syncAndReportErrors means dontIgnoreErrors, which means
+    // didReportProlongedError not touched.
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
@@ -1643,16 +1717,19 @@ add_identity_test(this, function test_wi
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
     do_check_true(Status.enforceBackoff);
     do_check_eq(backoffInterval, 42);
     do_check_eq(Status.service, LOGIN_FAILED);
     do_check_eq(Status.login, SERVER_MAINTENANCE);
+    // syncAndReportErrors means dontIgnoreErrors, which means
+    // didReportProlongedError not touched.
+    do_check_false(errorHandler.didReportProlongedError);
 
     clean();
     server.stop(deferred.resolve);
   });
 
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
--- a/toolkit/mozapps/extensions/test/browser/browser_experiments.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_experiments.js
@@ -2,174 +2,155 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 let gManagerWindow;
 let gCategoryUtilities;
 let gInstalledAddons = [];
 let gContext = this;
 
-function test() {
-  waitForExplicitFinish();
-
-  open_manager(null, (win) => {
-    gManagerWindow = win;
-    gCategoryUtilities = new CategoryUtilities(win);
-
-    // The Experiments Manager will interfere with us by preventing installs
-    // of experiments it doesn't know about. We remove it from the equation
-    // because here we are only concerned with core Addon Manager operation,
-    // not the superset Experiments Manager has imposed.
-    if ("@mozilla.org/browser/experiments-service;1" in Components.classes) {
-      Components.utils.import("resource:///modules/experiments/Experiments.jsm", gContext);
+add_task(function* initializeState() {
+  gManagerWindow = yield open_manager();
+  gCategoryUtilities = new CategoryUtilities(gManagerWindow);
 
-      // There is a race condition between XPCOM service initialization and
-      // this test running. We have to initialize the instance first, then
-      // uninitialize it to prevent this.
-      let instance = gContext.Experiments.instance();
-      instance.uninit().then(run_next_test);
-    } else {
-      run_next_test();
-    }
-  });
-}
+  // The Experiments Manager will interfere with us by preventing installs
+  // of experiments it doesn't know about. We remove it from the equation
+  // because here we are only concerned with core Addon Manager operation,
+  // not the superset Experiments Manager has imposed.
+  if ("@mozilla.org/browser/experiments-service;1" in Components.classes) {
+    Components.utils.import("resource:///modules/experiments/Experiments.jsm", gContext);
 
-function end_test() {
-  for (let addon of gInstalledAddons) {
-    addon.uninstall();
+    // There is a race condition between XPCOM service initialization and
+    // this test running. We have to initialize the instance first, then
+    // uninitialize it to prevent this.
+    let instance = gContext.Experiments.instance();
+    yield instance.uninit();
   }
-
-  close_manager(gManagerWindow, () => {
-    if ("@mozilla.org/browser/experiments-service;1" in Components.classes) {
-      gContext.Experiments.instance().init();
-      finish();
-    } else {
-      finish();
-    }
-  });
-}
+});
 
 // On an empty profile with no experiments, the experiment category
 // should be hidden.
-add_test(function testInitialState() {
+add_task(function* testInitialState() {
   Assert.ok(gCategoryUtilities.get("experiment", false), "Experiment tab is defined.");
 
   Assert.ok(!gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab hidden by default.");
-
-  run_next_test();
 });
 
-add_test(function testExperimentInfoNotVisible() {
-  gCategoryUtilities.openType("extension", () => {
-    let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0];
-    is_element_hidden(el, "Experiment info not visible on other types.");
-
-    run_next_test();
-  });
+add_task(function* testExperimentInfoNotVisible() {
+  yield gCategoryUtilities.openType("extension");
+  let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0];
+  is_element_hidden(el, "Experiment info not visible on other types.");
 });
 
 // If we have an active experiment, we should see the experiments tab
 // and that tab should have some messages.
-add_test(function testActiveExperiment() {
-  install_addon("addons/browser_experiment1.xpi", (addon) => {
-    gInstalledAddons.push(addon);
-
-    Assert.ok(addon.userDisabled, "Add-on is disabled upon initial install.");
-    Assert.equal(addon.isActive, false, "Add-on is not active.");
+add_task(function* testActiveExperiment() {
+  let addon = yield install_addon("addons/browser_experiment1.xpi");
+  gInstalledAddons.push(addon);
 
-    Assert.ok(gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab visible.");
+  Assert.ok(addon.userDisabled, "Add-on is disabled upon initial install.");
+  Assert.equal(addon.isActive, false, "Add-on is not active.");
 
-    gCategoryUtilities.openType("experiment", (win) => {
-      let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0];
-      is_element_visible(el, "Experiment info is visible on experiment tab.");
+  Assert.ok(gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab visible.");
 
-      run_next_test();
-    });
-  });
+  yield gCategoryUtilities.openType("experiment");
+  let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0];
+  is_element_visible(el, "Experiment info is visible on experiment tab.");
 });
 
-add_test(function testExperimentLearnMore() {
+add_task(function* testExperimentLearnMore() {
   // Actual URL is irrelevant.
   Services.prefs.setCharPref("toolkit.telemetry.infoURL",
                              "http://mochi.test:8888/server.js");
 
-  gCategoryUtilities.openType("experiment", (win) => {
-    let btn = gManagerWindow.document.getElementById("experiments-learn-more");
+  yield gCategoryUtilities.openType("experiment");
+  let btn = gManagerWindow.document.getElementById("experiments-learn-more");
 
-    if (!gUseInContentUI) {
-      is_element_hidden(btn, "Learn more button hidden if not using in-content UI.");
-      Services.prefs.clearUserPref("toolkit.telemetry.infoURL");
+  if (!gUseInContentUI) {
+    is_element_hidden(btn, "Learn more button hidden if not using in-content UI.");
+    Services.prefs.clearUserPref("toolkit.telemetry.infoURL");
 
-      run_next_test();
-      return;
-    } else {
-      is_element_visible(btn, "Learn more button visible.");
-    }
+    return;
+  }
+
+  is_element_visible(btn, "Learn more button visible.");
 
-    window.addEventListener("DOMContentLoaded", function onLoad(event) {
-      info("Telemetry privacy policy window opened.");
-      window.removeEventListener("DOMContentLoaded", onLoad, false);
+  let deferred = Promise.defer();
+  window.addEventListener("DOMContentLoaded", function onLoad(event) {
+    info("Telemetry privacy policy window opened.");
+    window.removeEventListener("DOMContentLoaded", onLoad, false);
 
-      let browser = gBrowser.selectedTab.linkedBrowser;
-      let expected = Services.prefs.getCharPref("toolkit.telemetry.infoURL");
-      Assert.equal(browser.currentURI.spec, expected, "New tab should have loaded privacy policy.");
-      browser.contentWindow.close();
+    let browser = gBrowser.selectedTab.linkedBrowser;
+    let expected = Services.prefs.getCharPref("toolkit.telemetry.infoURL");
+    Assert.equal(browser.currentURI.spec, expected, "New tab should have loaded privacy policy.");
+    browser.contentWindow.close();
 
-      Services.prefs.clearUserPref("toolkit.telemetry.infoURL");
+    Services.prefs.clearUserPref("toolkit.telemetry.infoURL");
+
+    deferred.resolve();
+  }, false);
 
-      run_next_test();
-    }, false);
+  info("Opening telemetry privacy policy.");
+  EventUtils.synthesizeMouseAtCenter(btn, {}, gManagerWindow);
 
-    info("Opening telemetry privacy policy.");
-    EventUtils.synthesizeMouseAtCenter(btn, {}, gManagerWindow);
-  });
+  yield deferred.promise;
 });
 
-add_test(function testOpenPreferences() {
-  gCategoryUtilities.openType("experiment", (win) => {
-    let btn = gManagerWindow.document.getElementById("experiments-change-telemetry");
-    if (!gUseInContentUI) {
-      is_element_hidden(btn, "Change telemetry button not enabled in out of window UI.");
-      info("Skipping preferences open test because not using in-content UI.");
-      run_next_test();
-      return;
-    }
+add_task(function* testOpenPreferences() {
+  yield gCategoryUtilities.openType("experiment");
+  let btn = gManagerWindow.document.getElementById("experiments-change-telemetry");
+  if (!gUseInContentUI) {
+    is_element_hidden(btn, "Change telemetry button not enabled in out of window UI.");
+    info("Skipping preferences open test because not using in-content UI.");
+    return;
+  }
 
-    is_element_visible(btn, "Change telemetry button visible in in-content UI.");
+  is_element_visible(btn, "Change telemetry button visible in in-content UI.");
 
-    Services.obs.addObserver(function observer(prefWin, topic, data) {
-      Services.obs.removeObserver(observer, "advanced-pane-loaded");
+  let deferred = Promise.defer();
+  Services.obs.addObserver(function observer(prefWin, topic, data) {
+    Services.obs.removeObserver(observer, "advanced-pane-loaded");
 
-      info("Advanced preference pane opened.");
+    info("Advanced preference pane opened.");
 
-      // We want this test to fail if the preferences pane changes.
-      let el = prefWin.document.getElementById("dataChoicesPanel");
-      is_element_visible(el);
+    // We want this test to fail if the preferences pane changes.
+    let el = prefWin.document.getElementById("dataChoicesPanel");
+    is_element_visible(el);
 
-      prefWin.close();
-      info("Closed preferences pane.");
+    prefWin.close();
+    info("Closed preferences pane.");
 
-      run_next_test();
-    }, "advanced-pane-loaded", false);
+    deferred.resolve();
+  }, "advanced-pane-loaded", false);
 
-    info("Loading preferences pane.");
-    EventUtils.synthesizeMouseAtCenter(btn, {}, gManagerWindow);
-  });
+  info("Loading preferences pane.");
+  EventUtils.synthesizeMouseAtCenter(btn, {}, gManagerWindow);
+
+  yield deferred.promise;
 });
 
-add_test(function testButtonPresence() {
-  gCategoryUtilities.openType("experiment", (win) => {
-    let item = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org");
-    Assert.ok(item, "Got add-on element.");
+add_task(function* testButtonPresence() {
+  yield gCategoryUtilities.openType("experiment");
+  let item = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org");
+  Assert.ok(item, "Got add-on element.");
 
-    let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn");
-    // Corresponds to the uninstall permission.
-    is_element_visible(el, "Remove button is visible.");
-    // Corresponds to lack of disable permission.
-    el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "disable-btn");
-    is_element_hidden(el, "Disable button not visible.");
-    // Corresponds to lack of enable permission.
-    el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "enable-btn");
-    is_element_hidden(el, "Enable button not visible.");
+  let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn");
+  // Corresponds to the uninstall permission.
+  is_element_visible(el, "Remove button is visible.");
+  // Corresponds to lack of disable permission.
+  el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "disable-btn");
+  is_element_hidden(el, "Disable button not visible.");
+  // Corresponds to lack of enable permission.
+  el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "enable-btn");
+  is_element_hidden(el, "Enable button not visible.");
+});
 
-    run_next_test();
-  });
+add_task(function* testCleanup() {
+  for (let addon of gInstalledAddons) {
+    addon.uninstall();
+  }
+
+  yield close_manager(gManagerWindow);
+
+  if ("@mozilla.org/browser/experiments-service;1" in Components.classes) {
+    yield gContext.Experiments.instance().init();
+  }
 });
--- a/toolkit/mozapps/extensions/test/browser/head.js
+++ b/toolkit/mozapps/extensions/test/browser/head.js
@@ -278,73 +278,86 @@ function wait_for_manager_load(aManagerW
   info("Waiting for initialization");
   aManagerWindow.document.addEventListener("Initialized", function() {
     aManagerWindow.document.removeEventListener("Initialized", arguments.callee, false);
     log_exceptions(aCallback, aManagerWindow);
   }, false);
 }
 
 function open_manager(aView, aCallback, aLoadCallback, aLongerTimeout) {
+  let deferred = Promise.defer();
+
   function setup_manager(aManagerWindow) {
     if (aLoadCallback)
       log_exceptions(aLoadCallback, aManagerWindow);
 
     if (aView)
       aManagerWindow.loadView(aView);
 
     ok(aManagerWindow != null, "Should have an add-ons manager window");
     is(aManagerWindow.location, MANAGER_URI, "Should be displaying the correct UI");
 
     waitForFocus(function() {
       wait_for_manager_load(aManagerWindow, function() {
         wait_for_view_load(aManagerWindow, function() {
           // Some functions like synthesizeMouse don't like to be called during
           // the load event so ensure that has completed
           executeSoon(function() {
-            log_exceptions(aCallback, aManagerWindow);
+            if (aCallback) {
+              log_exceptions(aCallback, aManagerWindow);
+            }
+            deferred.resolve(aManagerWindow);
           });
         }, null, aLongerTimeout);
       });
     }, aManagerWindow);
   }
 
   if (gUseInContentUI) {
     gBrowser.selectedTab = gBrowser.addTab();
     switchToTabHavingURI(MANAGER_URI, true);
-    
+
     // This must be a new load, else the ping/pong would have
     // found the window above.
     Services.obs.addObserver(function (aSubject, aTopic, aData) {
       Services.obs.removeObserver(arguments.callee, aTopic);
       if (aSubject.location.href != MANAGER_URI)
         return;
       setup_manager(aSubject);
     }, "EM-loaded", false);
-    return;
+    return deferred.promise;
   }
 
   openDialog(MANAGER_URI);
   Services.obs.addObserver(function (aSubject, aTopic, aData) {
     Services.obs.removeObserver(arguments.callee, aTopic);
     setup_manager(aSubject);
   }, "EM-loaded", false);
+
+  return deferred.promise;
 }
 
 function close_manager(aManagerWindow, aCallback, aLongerTimeout) {
+  let deferred = Promise.defer();
   requestLongerTimeout(aLongerTimeout ? aLongerTimeout : 2);
 
   ok(aManagerWindow != null, "Should have an add-ons manager window to close");
   is(aManagerWindow.location, MANAGER_URI, "Should be closing window with correct URI");
 
   aManagerWindow.addEventListener("unload", function() {
     this.removeEventListener("unload", arguments.callee, false);
-    log_exceptions(aCallback);
+    if (aCallback) {
+      log_exceptions(aCallback);
+    }
+    deferred.resolve();
   }, false);
 
   aManagerWindow.close();
+
+  return deferred.promise;
 }
 
 function restart_manager(aManagerWindow, aView, aCallback, aLoadCallback) {
   if (!aManagerWindow) {
     open_manager(aView, aCallback, aLoadCallback);
     return;
   }
 
@@ -419,27 +432,35 @@ function is_element_hidden(aElement, aMs
 }
 
 /**
  * Install an add-on and call a callback when complete.
  *
  * The callback will receive the Addon for the installed add-on.
  */
 function install_addon(path, cb, pathPrefix=TESTROOT) {
+  let deferred = Promise.defer();
+
   AddonManager.getInstallForURL(pathPrefix + path, (install) => {
     install.addListener({
       onInstallEnded: () => {
         executeSoon(() => {
-          cb(install.addon);
+          if (cb) {
+            cb(install.addon);
+          }
+
+          deferred.resolve(install.addon);
         });
       },
     });
 
     install.install();
   }, "application/x-xpinstall");
+
+  return deferred.promise;
 }
 
 function CategoryUtilities(aManagerWindow) {
   this.window = aManagerWindow;
 
   var self = this;
   this.window.addEventListener("unload", function() {
     self.window.removeEventListener("unload", arguments.callee, false);
@@ -491,27 +512,36 @@ CategoryUtilities.prototype = {
     return !is_hidden(aCategory);
   },
 
   isTypeVisible: function(aCategoryType) {
     return this.isVisible(this.get(aCategoryType));
   },
 
   open: function(aCategory, aCallback) {
+    let deferred = Promise.defer();
+
     isnot(this.window, null, "Should not open category when manager window is not loaded");
     ok(this.isVisible(aCategory), "Category should be visible if attempting to open it");
 
     EventUtils.synthesizeMouse(aCategory, 2, 2, { }, this.window);
 
-    if (aCallback)
-      wait_for_view_load(this.window, aCallback);
+    wait_for_view_load(this.window, (win) => {
+      if (aCallback) {
+        log_exceptions(aCallback, win);
+      }
+
+      deferred.resolve(win);
+    });
+
+    return deferred.promise;
   },
 
   openType: function(aCategoryType, aCallback) {
-    this.open(this.get(aCategoryType), aCallback);
+    return this.open(this.get(aCategoryType), aCallback);
   }
 }
 
 function CertOverrideListener(host, bits) {
   this.host = host;
   this.bits = bits;
 }