Merge m-c to inbound. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 25 May 2017 21:31:19 -0400
changeset 360745 862e534ade6d17176b09aeeb5dae63fdb53eddeb
parent 360711 5508827d35e1c96bec215db6adb14cb1f7c06345 (current diff)
parent 360744 0874cf4bb194d381a3afaa51276b6cee22f82211 (diff)
child 360746 ff4945a4dcc9652bd831e0d1db89efaa871660f6
child 360761 5d6fe59a9a5dfd2d381d2cdfdc968d3305b417cf
child 360766 888e4452b3eae0282608a0ab3f806e7c44c88662
push id90721
push userryanvm@gmail.com
push dateFri, 26 May 2017 01:33:12 +0000
treeherdermozilla-inbound@862e534ade6d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to inbound. a=merge
--- a/browser/components/preferences/in-content-old/advanced.js
+++ b/browser/components/preferences/in-content-old/advanced.js
@@ -212,34 +212,55 @@ var gAdvancedPane = {
         return 2;
       }
       return 1;
     }
     return 0;
   },
 
   /**
-   * security.OCSP.enabled is an integer value for legacy reasons.
-   * A value of 1 means OCSP is enabled. Any other value means it is disabled.
+   * readEnableOCSP is used by the preferences UI to determine whether or not
+   * the checkbox for OCSP fetching should be checked (it returns true if it
+   * should be checked and false otherwise). The about:config preference
+   * "security.OCSP.enabled" is an integer rather than a boolean, so it can't be
+   * directly mapped from {true,false} to {checked,unchecked}. The possible
+   * values for "security.OCSP.enabled" are:
+   * 0: fetching is disabled
+   * 1: fetch for all certificates
+   * 2: fetch only for EV certificates
+   * Hence, if "security.OCSP.enabled" is non-zero, the checkbox should be
+   * checked. Otherwise, it should be unchecked.
    */
   readEnableOCSP() {
     var preference = document.getElementById("security.OCSP.enabled");
     // This is the case if the preference is the default value.
     if (preference.value === undefined) {
       return true;
     }
-    return preference.value == 1;
+    return preference.value != 0;
   },
 
   /**
-   * See documentation for readEnableOCSP.
+   * writeEnableOCSP is used by the preferences UI to map the checked/unchecked
+   * state of the OCSP fetching checkbox to the value that the preference
+   * "security.OCSP.enabled" should be set to (it returns that value). See the
+   * readEnableOCSP documentation for more background. We unfortunately don't
+   * have enough information to map from {true,false} to all possible values for
+   * "security.OCSP.enabled", but a reasonable alternative is to map from
+   * {true,false} to {<the default value>,0}. That is, if the box is checked,
+   * "security.OCSP.enabled" will be set to whatever default it should be, given
+   * the platform and channel. If the box is unchecked, the preference will be
+   * set to 0. Obviously this won't work if the default is 0, so we will have to
+   * revisit this if we ever set it to 0.
    */
   writeEnableOCSP() {
     var checkbox = document.getElementById("enableOCSP");
-    return checkbox.checked ? 1 : 0;
+    var defaults = Services.prefs.getDefaultBranch(null);
+    var defaultValue = defaults.getIntPref("security.OCSP.enabled");
+    return checkbox.checked ? defaultValue : 0;
   },
 
   /**
    * When the user toggles the layers.acceleration.disabled pref,
    * sync its new value to the gfx.direct2d.disabled pref too.
    */
   updateHardwareAcceleration() {
     if (AppConstants.platform == "win") {
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -1126,36 +1126,56 @@ var gPrivacyPane = {
     {
       blockVisible: false,
       sessionVisible: false,
       allowVisible: true,
       prefilledHost: "",
       permissionType: "install"
     },
 
-
   /**
-   * security.OCSP.enabled is an integer value for legacy reasons.
-   * A value of 1 means OCSP is enabled. Any other value means it is disabled.
+   * readEnableOCSP is used by the preferences UI to determine whether or not
+   * the checkbox for OCSP fetching should be checked (it returns true if it
+   * should be checked and false otherwise). The about:config preference
+   * "security.OCSP.enabled" is an integer rather than a boolean, so it can't be
+   * directly mapped from {true,false} to {checked,unchecked}. The possible
+   * values for "security.OCSP.enabled" are:
+   * 0: fetching is disabled
+   * 1: fetch for all certificates
+   * 2: fetch only for EV certificates
+   * Hence, if "security.OCSP.enabled" is non-zero, the checkbox should be
+   * checked. Otherwise, it should be unchecked.
    */
   readEnableOCSP() {
     var preference = document.getElementById("security.OCSP.enabled");
     // This is the case if the preference is the default value.
     if (preference.value === undefined) {
       return true;
     }
-    return preference.value == 1;
+    return preference.value != 0;
   },
 
   /**
-   * See documentation for readEnableOCSP.
+   * writeEnableOCSP is used by the preferences UI to map the checked/unchecked
+   * state of the OCSP fetching checkbox to the value that the preference
+   * "security.OCSP.enabled" should be set to (it returns that value). See the
+   * readEnableOCSP documentation for more background. We unfortunately don't
+   * have enough information to map from {true,false} to all possible values for
+   * "security.OCSP.enabled", but a reasonable alternative is to map from
+   * {true,false} to {<the default value>,0}. That is, if the box is checked,
+   * "security.OCSP.enabled" will be set to whatever default it should be, given
+   * the platform and channel. If the box is unchecked, the preference will be
+   * set to 0. Obviously this won't work if the default is 0, so we will have to
+   * revisit this if we ever set it to 0.
    */
   writeEnableOCSP() {
     var checkbox = document.getElementById("enableOCSP");
-    return checkbox.checked ? 1 : 0;
+    var defaults = Services.prefs.getDefaultBranch(null);
+    var defaultValue = defaults.getIntPref("security.OCSP.enabled");
+    return checkbox.checked ? defaultValue : 0;
   },
 
   /**
    * Displays the user's certificates and associated options.
    */
   showCertificates() {
     gSubDialog.open("chrome://pippki/content/certManager.xul");
   },
--- a/browser/extensions/e10srollout/bootstrap.js
+++ b/browser/extensions/e10srollout/bootstrap.js
@@ -14,19 +14,22 @@ Cu.import("resource://gre/modules/AppCon
 // The amount of people to be part of e10s
 const TEST_THRESHOLD = {
   "beta": 0.9,  // 90%
   "release": 1.0,  // 100%
   "esr": 1.0,  // 100%
 };
 
 // If a user qualifies for the e10s-multi experiement, this is how many
-// content processes to use.
-const MULTI_BUCKETS = {
-  "beta": { 1: .5, 4: 1, },
+// content processes to use and whether to allow addons for the experiment.
+const MULTI_EXPERIMENT = {
+  "beta": { buckets: { 1: .5, 4: 1, }, // 1 process: 50%, 4 processes: 50%
+            addons: true },
+  "release": { buckets: { 1: .2, 4: 1 }, // 1 process: 20%, 4 processes: 80%
+               addons: false },
 };
 
 const ADDON_ROLLOUT_POLICY = {
   "beta": "50allmpc",
   "release": "50allmpc",
   "esr": "esrA", // WebExtensions and Addons with mpc=true
 };
 
@@ -155,24 +158,27 @@ function defineCohort() {
     eligibleForMulti = true;
   } else {
     setCohort(`${cohortPrefix}control`);
     Preferences.reset(PREF_TOGGLE_E10S);
     Preferences.reset(PREF_E10S_PROCESSCOUNT + ".web");
   }
 
   // Now determine if this user should be in the e10s-multi experiment.
-  // - We only run the experiment on channels defined in MULTI_BUCKETS.
+  // - We only run the experiment on channels defined in MULTI_EXPERIMENT.
+  // - If this experiment doesn't allow addons and we have a cohort prefix
+  //   (i.e. there's at least one addon installed) we stop here.
   // - We decided above whether this user qualifies for the experiment.
   // - If the user already opted into multi, then their prefs are already set
   //   correctly, we're done.
   // - If the user has addons that disqualify them for multi, leave them with
   //   the default number of content processes (1 on beta) but still in the
   //   test cohort.
-  if (!(updateChannel in MULTI_BUCKETS) ||
+  if (!(updateChannel in MULTI_EXPERIMENT) ||
+      (!MULTI_EXPERIMENT[updateChannel].addons && cohortPrefix) ||
       !eligibleForMulti ||
       userOptedIn.multi ||
       disqualified) {
     Preferences.reset(PREF_E10S_PROCESSCOUNT + ".web");
     return;
   }
 
   // If we got here with a cohortPrefix, it must be "addons-set50allmpc-",
@@ -180,17 +186,17 @@ function defineCohort() {
   // getAddonsDisqualifyForMulti returns false, that means that all installed
   // addons are webextension based, so note that in the cohort name.
   if (cohortPrefix && !getAddonsDisqualifyForMulti()) {
     cohortPrefix = "webextensions-";
   }
 
   // The user is in the multi experiment!
   // Decide how many content processes to use for this user.
-  let buckets = MULTI_BUCKETS[updateChannel];
+  let buckets = MULTI_EXPERIMENT[updateChannel].buckets;
 
   let multiUserSample = getUserSample(true);
   for (let sampleName of Object.getOwnPropertyNames(buckets)) {
     if (multiUserSample < buckets[sampleName]) {
       setCohort(`${cohortPrefix}multiBucket${sampleName}`);
       Preferences.set(PREF_E10S_PROCESSCOUNT + ".web", sampleName);
       break;
     }
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -586,18 +586,18 @@ service.toolbarbutton.label=Services
 service.toolbarbutton.tooltiptext=Services
 
 # LOCALIZATION NOTE (social.install.description): %1$S is the hostname of the social provider, %2$S is brandShortName (e.g. Firefox)
 service.install.description=Would you like to enable services from %1$S to display in your %2$S toolbar and sidebar?
 service.install.ok.label=Enable Services
 service.install.ok.accesskey=E
 
 # These are visible when opening the popup inside the bookmarks sidebar
-sidebar.moveToLeft=Move sidebar to left
-sidebar.moveToRight=Move sidebar to right
+sidebar.moveToLeft=Move Sidebar to Left
+sidebar.moveToRight=Move Sidebar to Right
 
 # LOCALIZATION NOTE (social.markpageMenu.label): %S is the name of the social provider
 social.markpageMenu.label=Save Page to %S
 # LOCALIZATION NOTE (social.marklinkMenu.label): %S is the name of the social provider
 social.marklinkMenu.label=Save Link to %S
 
 # LOCALIZATION NOTE (social.error.message): %1$S is brandShortName (e.g. Firefox), %2$S is the name of the social provider
 social.error.message=%1$S is unable to connect with %2$S right now.
--- a/devtools/client/responsivedesign/test/browser_responsiveui_touch.js
+++ b/devtools/client/responsivedesign/test/browser_responsiveui_touch.js
@@ -137,12 +137,12 @@ function synthesizeClick(element) {
   BrowserTestUtils.synthesizeMouseAtCenter(element, { type: "mousedown", isSynthesized: false },
         gBrowser.selectedBrowser);
   BrowserTestUtils.synthesizeMouseAtCenter(element, { type: "mouseup", isSynthesized: false },
         gBrowser.selectedBrowser);
   return waitForClickEvent;
 }
 
 function pushPrefs(...aPrefs) {
-  let deferred = promise.defer();
-  SpecialPowers.pushPrefEnv({"set": aPrefs}, deferred.resolve);
-  return deferred.promise;
+  return new Promise(resolve => {
+    SpecialPowers.pushPrefEnv({"set": aPrefs}, resolve);
+  });
 }
--- a/devtools/client/responsivedesign/test/head.js
+++ b/devtools/client/responsivedesign/test/head.js
@@ -125,19 +125,19 @@ var closeToolbox = Task.async(function* 
 
 /**
  * Wait for the toolbox frame to receive focus after it loads
  * @param {Toolbox} toolbox
  * @return a promise that resolves when focus has been received
  */
 function waitForToolboxFrameFocus(toolbox) {
   info("Making sure that the toolbox's frame is focused");
-  let def = promise.defer();
-  waitForFocus(def.resolve, toolbox.win);
-  return def.promise;
+  return new Promise(resolve => {
+    waitForFocus(resolve, toolbox.win);
+  });
 }
 
 /**
  * Open the toolbox, with the inspector tool visible, and the sidebar that
  * corresponds to the given id selected
  * @return a promise that resolves when the inspector is ready and the sidebar
  * view is visible and ready
  */
@@ -205,37 +205,37 @@ var addTab = Task.async(function* (url) 
 });
 
 /**
  * Waits for the next load to complete in the current browser.
  *
  * @return promise
  */
 function waitForDocLoadComplete(aBrowser = gBrowser) {
-  let deferred = promise.defer();
-  let progressListener = {
-    onStateChange: function (webProgress, req, flags, status) {
-      let docStop = Ci.nsIWebProgressListener.STATE_IS_NETWORK |
-                    Ci.nsIWebProgressListener.STATE_STOP;
-      info(`Saw state ${flags.toString(16)} and status ${status.toString(16)}`);
+  return new Promise(resolve => {
+    let progressListener = {
+      onStateChange: function (webProgress, req, flags, status) {
+        let docStop = Ci.nsIWebProgressListener.STATE_IS_NETWORK |
+                      Ci.nsIWebProgressListener.STATE_STOP;
+        info(`Saw state ${flags.toString(16)} and status ${status.toString(16)}`);
 
-      // When a load needs to be retargetted to a new process it is cancelled
-      // with NS_BINDING_ABORTED so ignore that case
-      if ((flags & docStop) == docStop && status != Cr.NS_BINDING_ABORTED) {
-        aBrowser.removeProgressListener(progressListener);
-        info("Browser loaded");
-        deferred.resolve();
-      }
-    },
-    QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
+        // When a load needs to be retargetted to a new process it is cancelled
+        // with NS_BINDING_ABORTED so ignore that case
+        if ((flags & docStop) == docStop && status != Cr.NS_BINDING_ABORTED) {
+          aBrowser.removeProgressListener(progressListener);
+          info("Browser loaded");
+          resolve();
+        }
+      },
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
                                            Ci.nsISupportsWeakReference])
-  };
-  aBrowser.addProgressListener(progressListener);
-  info("Waiting for browser load");
-  return deferred.promise;
+    };
+    aBrowser.addProgressListener(progressListener);
+    info("Waiting for browser load");
+  });
 }
 
 /**
  * Get the NodeFront for a node that matches a given css selector, via the
  * protocol.
  * @param {String|NodeFront} selector
  * @param {InspectorPanel} inspector The instance of InspectorPanel currently
  * loaded in the toolbox
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -9646,18 +9646,17 @@ public:
         nsAutoString addonId;
         if (NS_SUCCEEDED(pc->GetAddonId(addonId)) && !addonId.IsEmpty()) {
           // We want to nuke all references to the add-on compartment.
           xpc::NukeAllWrappersForCompartment(cx, cpt,
                                              win->IsInnerWindow() ? js::DontNukeWindowReferences
                                                                   : js::NukeWindowReferences);
         } else {
           // We only want to nuke wrappers for the chrome->content case
-          js::NukeCrossCompartmentWrappers(cx, BrowserCompartmentMatcher(),
-                                           js::SingleCompartment(cpt),
+          js::NukeCrossCompartmentWrappers(cx, BrowserCompartmentMatcher(), cpt,
                                            win->IsInnerWindow() ? js::DontNukeWindowReferences
                                                                 : js::NukeWindowReferences,
                                            js::NukeIncomingReferences);
         }
       }
     }
 
     return NS_OK;
--- a/gfx/vr/openvr/src/envvartools_public.cpp
+++ b/gfx/vr/openvr/src/envvartools_public.cpp
@@ -1,14 +1,14 @@
 //========= Copyright Valve Corporation ============//
 #include "envvartools_public.h"
 #include <stdlib.h>
 
 #if defined(_WIN32)
-#include <Windows.h>
+#include <windows.h>
 
 #undef GetEnvironmentVariable
 #undef SetEnvironmentVariable
 #endif
 
 
 std::string GetEnvironmentVariable( const char *pchVarName )
 {
--- a/gfx/vr/openvr/src/pathtools_public.cpp
+++ b/gfx/vr/openvr/src/pathtools_public.cpp
@@ -1,18 +1,19 @@
 //========= Copyright Valve Corporation ============//
 #include "strtools_public.h"
 #include "pathtools_public.h"
 
 #if defined( _WIN32)
-#include <Windows.h>
+#include <windows.h>
 #include <direct.h>
-#include <Shobjidl.h>
-#include <KnownFolders.h>
-#include <Shlobj.h>
+#include <shobjidl.h>
+#include <knownfolders.h>
+#include <shlobj.h>
+#include <share.h>
 
 #undef GetEnvironmentVariable
 #else
 #include <dlfcn.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
 #endif
--- a/gfx/vr/openvr/src/sharedlibtools_public.cpp
+++ b/gfx/vr/openvr/src/sharedlibtools_public.cpp
@@ -1,14 +1,14 @@
 //========= Copyright Valve Corporation ============//
 #include "sharedlibtools_public.h"
 #include <string.h>
 
 #if defined(_WIN32)
-#include <Windows.h>
+#include <windows.h>
 #endif
 
 #if defined(POSIX)
 #include <dlfcn.h>
 #endif
 
 SharedLibHandle SharedLib_Load( const char *pchPath )
 {
@@ -17,17 +17,17 @@ SharedLibHandle SharedLib_Load( const ch
 #elif defined(POSIX)
 	return (SharedLibHandle)dlopen(pchPath, RTLD_LOCAL|RTLD_NOW);
 #endif
 }
 
 void *SharedLib_GetFunction( SharedLibHandle lib, const char *pchFunctionName)
 {
 #if defined( _WIN32)
-	return GetProcAddress( (HMODULE)lib, pchFunctionName );
+  return (void*)GetProcAddress( (HMODULE)lib, pchFunctionName );
 #elif defined(POSIX)
 	return dlsym( lib, pchFunctionName );
 #endif
 }
 
 
 void SharedLib_Unload( SharedLibHandle lib )
 {
--- a/gfx/vr/openvr/src/vrpathregistry_public.cpp
+++ b/gfx/vr/openvr/src/vrpathregistry_public.cpp
@@ -4,31 +4,33 @@
 #include "json/json.h"
 #include "pathtools_public.h"
 #include "envvartools_public.h"
 #include "strtools_public.h"
 #include "dirtools_public.h"
 
 #if defined( WIN32 )
 #include <windows.h>
-#include <Shlobj.h>
+#include <shlobj.h>
 
 #undef GetEnvironmentVariable
 #elif defined OSX
 #include <Foundation/Foundation.h>
 #include <AppKit/AppKit.h>
 #elif defined(LINUX)
 #include <dlfcn.h>
 #include <stdio.h>
 #endif
 
 #include <algorithm>
 
 #ifndef VRLog
-	#if defined( WIN32 )
+	#if defined( __MINGW32__ )
+		#define VRLog(args...)		fprintf(stderr, args)
+	#elif defined( WIN32 )
 		#define VRLog(fmt, ...)		fprintf(stderr, fmt, __VA_ARGS__)
 	#else
 		#define VRLog(args...)		fprintf(stderr, args)
 	#endif
 #endif
 
 /** Returns the root of the directory the system wants us to store user config data in */
 static std::string GetAppSettingsPath()
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -2613,26 +2613,30 @@ class _GenerateProtocolActorCode(ipdl.as
                                            self.prettyside)),
                 Whitespace.NL ])
 
         self.cls.addstmt(Label.PROTECTED)
         for typedef in p.cxxTypedefs():
             self.cls.addstmt(typedef)
         for typedef in self.includedActorTypedefs:
             self.cls.addstmt(typedef)
+
+        self.cls.addstmt(Whitespace.NL)
+
+        self.cls.addstmts([ Typedef(p.fqStateType(), 'State'), Whitespace.NL ])
+
+        self.cls.addstmt(Label.PUBLIC)
         for md in p.messageDecls:
             if self.receivesMessage(md) and md.hasAsyncReturns():
                 self.cls.addstmt(
                     Typedef(_makePromise(md.returns, self.side, resolver=True),
                             md.promiseName()))
-
         self.cls.addstmt(Whitespace.NL)
 
-        self.cls.addstmts([ Typedef(p.fqStateType(), 'State'), Whitespace.NL ])
-
+        self.cls.addstmt(Label.PROTECTED)
         # interface methods that the concrete subclass has to impl
         for md in p.messageDecls:
             isctor, isdtor = md.decl.type.isCtor(), md.decl.type.isDtor()
 
             if self.receivesMessage(md):
                 # generate Recv/Answer* interface
                 implicit = (not isdtor)
                 returnsems = 'resolver' if md.decl.type.isAsync() else 'out'
--- a/js/src/devtools/rootAnalysis/annotations.js
+++ b/js/src/devtools/rootAnalysis/annotations.js
@@ -226,16 +226,18 @@ var ignoreFunctions = {
 
     // VTune internals that lazy-load a shared library and make IndirectCalls.
     "iJIT_IsProfilingActive" : true,
     "iJIT_NotifyEvent": true,
 
     // The big hammers.
     "PR_GetCurrentThread" : true,
     "calloc" : true,
+
+    "uint8 nsContentUtils::IsExpandedPrincipal(nsIPrincipal*)" : true,
 };
 
 function extraGCFunctions() {
     return ["ffi_call"];
 }
 
 function isProtobuf(name)
 {
--- a/js/src/gc/NurseryAwareHashMap.h
+++ b/js/src/gc/NurseryAwareHashMap.h
@@ -82,16 +82,17 @@ class NurseryAwareHashMap
     // This lets us avoid a full traveral of the map on each minor GC, keeping
     // the minor GC times proportional to the nursery heap size.
     Vector<Key, 0, AllocPolicy> nurseryEntries;
 
   public:
     using Lookup = typename MapType::Lookup;
     using Ptr = typename MapType::Ptr;
     using Range = typename MapType::Range;
+    using Entry = typename MapType::Entry;
 
     explicit NurseryAwareHashMap(AllocPolicy a = AllocPolicy()) : map(a) {}
 
     MOZ_MUST_USE bool init(uint32_t len = 16) { return map.init(len); }
 
     bool empty() const { return map.empty(); }
     Ptr lookup(const Lookup& l) const { return map.lookup(l); }
     void remove(Ptr p) { map.remove(p); }
--- a/js/src/gc/Statistics.cpp
+++ b/js/src/gc/Statistics.cpp
@@ -874,16 +874,17 @@ Statistics::endGC()
     runtime->addTelemetry(JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS, t(sccLongest));
 
     if (!aborted) {
         TimeDuration total, longest;
         gcDuration(&total, &longest);
 
         runtime->addTelemetry(JS_TELEMETRY_GC_MS, t(total));
         runtime->addTelemetry(JS_TELEMETRY_GC_MAX_PAUSE_MS, t(longest));
+        runtime->addTelemetry(JS_TELEMETRY_GC_MAX_PAUSE_MS_2, t(longest));
 
         const double mmu50 = computeMMU(TimeDuration::FromMilliseconds(50));
         runtime->addTelemetry(JS_TELEMETRY_GC_MMU_50, mmu50 * 100);
     }
 
     if (fp)
         printStats();
 
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -676,19 +676,19 @@ JSCompartment::getExistingTemplateLitera
 }
 
 void
 JSCompartment::traceOutgoingCrossCompartmentWrappers(JSTracer* trc)
 {
     MOZ_ASSERT(JS::CurrentThreadIsHeapMajorCollecting());
     MOZ_ASSERT(!zone()->isCollectingFromAnyThread() || trc->runtime()->gc.isHeapCompacting());
 
-    for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) {
-        Value v = e.front().value().unbarrieredGet();
+    for (NonStringWrapperEnum e(this); !e.empty(); e.popFront()) {
         if (e.front().key().is<JSObject*>()) {
+            Value v = e.front().value().unbarrieredGet();
             ProxyObject* wrapper = &v.toObject().as<ProxyObject>();
 
             /*
              * We have a cross-compartment wrapper. Its private pointer may
              * point into the compartment being collected, so we should mark it.
              */
             TraceEdge(trc, wrapper->slotOfPrivate(), "cross-compartment wrapper");
         }
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -179,25 +179,21 @@ class CrossCompartmentKey
             ReturnType match(JSObject*& obj) { return ReturnType(); }
             ReturnType match(JSString*& str) { return ReturnType(); }
             ReturnType match(DebuggerAndScript& tpl) { return f_(&mozilla::Get<0>(tpl)); }
             ReturnType match(DebuggerAndObject& tpl) { return f_(&mozilla::Get<0>(tpl)); }
         } matcher(f);
         return wrapped.match(matcher);
     }
 
-    // Valid for JSObject* and Debugger keys. Crashes immediately if used on a
-    // JSString* key.
     JSCompartment* compartment() {
         struct GetCompartmentFunctor {
             JSCompartment* operator()(JSObject** tp) const { return (*tp)->compartment(); }
             JSCompartment* operator()(JSScript** tp) const { return (*tp)->compartment(); }
-            JSCompartment* operator()(JSString** tp) const {
-                MOZ_CRASH("invalid ccw key"); return nullptr;
-            }
+            JSCompartment* operator()(JSString** tp) const { return nullptr; }
         };
         return applyToWrapped(GetCompartmentFunctor());
     }
 
     struct Hasher : public DefaultHasher<CrossCompartmentKey>
     {
         struct HashFunctor {
             HashNumber match(JSObject* obj) { return DefaultHasher<JSObject*>::hash(obj); }
@@ -234,19 +230,201 @@ class CrossCompartmentKey
     void trace(JSTracer* trc);
     bool needsSweep();
 
   private:
     CrossCompartmentKey() = delete;
     WrappedType wrapped;
 };
 
+// The data structure for storing CCWs, which has a map per target compartment
+// so we can access them easily. Note string CCWs are stored separately from the
+// others because they have target compartment nullptr.
+class WrapperMap
+{
+    static const size_t InitialInnerMapSize = 4;
 
-using WrapperMap = NurseryAwareHashMap<CrossCompartmentKey, JS::Value,
-                                       CrossCompartmentKey::Hasher, SystemAllocPolicy>;
+    using InnerMap = NurseryAwareHashMap<CrossCompartmentKey,
+                                         JS::Value,
+                                         CrossCompartmentKey::Hasher,
+                                         SystemAllocPolicy>;
+    using OuterMap = GCHashMap<JSCompartment*,
+                               InnerMap,
+                               DefaultHasher<JSCompartment*>,
+                               SystemAllocPolicy>;
+
+    OuterMap map;
+
+  public:
+    class Enum
+    {
+      public:
+        enum SkipStrings : bool {
+            WithStrings = false,
+            WithoutStrings = true
+        };
+
+      private:
+        Enum(const Enum&) = delete;
+        void operator=(const Enum&) = delete;
+
+        void goToNext() {
+            if (outer.isNothing())
+                return;
+            for (; !outer->empty(); outer->popFront()) {
+                JSCompartment* c = outer->front().key();
+                // Need to skip string at first, because the filter may not be
+                // happy with a nullptr.
+                if (!c && skipStrings)
+                    continue;
+                if (filter && !filter->match(c))
+                    continue;
+                InnerMap& m = outer->front().value();
+                if (!m.empty()) {
+                    if (inner.isSome())
+                        inner.reset();
+                    inner.emplace(m);
+                    outer->popFront();
+                    return;
+                }
+            }
+        }
+
+        mozilla::Maybe<OuterMap::Enum> outer;
+        mozilla::Maybe<InnerMap::Enum> inner;
+        const CompartmentFilter* filter;
+        SkipStrings skipStrings;
+
+      public:
+        explicit Enum(WrapperMap& m, SkipStrings s = WithStrings) :
+                filter(nullptr), skipStrings(s) {
+            outer.emplace(m.map);
+            goToNext();
+        }
+
+        Enum(WrapperMap& m, const CompartmentFilter& f, SkipStrings s = WithStrings) :
+                filter(&f), skipStrings(s) {
+            outer.emplace(m.map);
+            goToNext();
+        }
+
+        Enum(WrapperMap& m, JSCompartment* target) {
+            // Leave the outer map as nothing and only iterate the inner map we
+            // find here.
+            auto p = m.map.lookup(target);
+            if (p)
+                inner.emplace(p->value());
+        }
+
+        bool empty() const {
+            return (outer.isNothing() || outer->empty()) &&
+                   (inner.isNothing() || inner->empty());
+        }
+
+        InnerMap::Entry& front() const {
+            MOZ_ASSERT(inner.isSome() && !inner->empty());
+            return inner->front();
+        }
+
+        void popFront() {
+            MOZ_ASSERT(!empty());
+            if (!inner->empty()) {
+                inner->popFront();
+                if (!inner->empty())
+                    return;
+            }
+            goToNext();
+        }
+
+        void removeFront() {
+            MOZ_ASSERT(inner.isSome());
+            inner->removeFront();
+        }
+    };
+
+    class Ptr : public InnerMap::Ptr
+    {
+        friend class WrapperMap;
+
+        InnerMap* map;
+
+        Ptr() : InnerMap::Ptr(), map(nullptr) {}
+        Ptr(const InnerMap::Ptr& p, InnerMap& m) : InnerMap::Ptr(p), map(&m) {}
+    };
+
+    MOZ_MUST_USE bool init(uint32_t len) { return map.init(len); }
+
+    bool empty() {
+        if (map.empty())
+            return true;
+        for (OuterMap::Enum e(map); !e.empty(); e.popFront()) {
+            if (!e.front().value().empty())
+                return false;
+        }
+        return true;
+    }
+
+    Ptr lookup(const CrossCompartmentKey& k) const {
+        auto op = map.lookup(const_cast<CrossCompartmentKey&>(k).compartment());
+        if (op) {
+            auto ip = op->value().lookup(k);
+            if (ip)
+                return Ptr(ip, op->value());
+        }
+        return Ptr();
+    }
+
+    void remove(Ptr p) {
+        if (p)
+            p.map->remove(p);
+    }
+
+    MOZ_MUST_USE bool put(const CrossCompartmentKey& k, const JS::Value& v) {
+        JSCompartment* c = const_cast<CrossCompartmentKey&>(k).compartment();
+        MOZ_ASSERT(k.is<JSString*>() == !c);
+        auto p = map.lookupForAdd(c);
+        if (!p) {
+            InnerMap m;
+            if (!m.init(InitialInnerMapSize) || !map.add(p, c, mozilla::Move(m)))
+                return false;
+        }
+        return p->value().put(k, v);
+    }
+
+    size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
+        size_t size = map.sizeOfExcludingThis(mallocSizeOf);
+        for (OuterMap::Enum e(map); !e.empty(); e.popFront())
+            size += e.front().value().sizeOfExcludingThis(mallocSizeOf);
+        return size;
+    }
+    size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) {
+        size_t size = map.sizeOfIncludingThis(mallocSizeOf);
+        for (OuterMap::Enum e(map); !e.empty(); e.popFront())
+            size += e.front().value().sizeOfIncludingThis(mallocSizeOf);
+        return size;
+    }
+
+    void sweepAfterMinorGC(JSTracer* trc) {
+        for (OuterMap::Enum e(map); !e.empty(); e.popFront()) {
+            InnerMap& m = e.front().value();
+            m.sweepAfterMinorGC(trc);
+            if (m.empty())
+                e.removeFront();
+        }
+    }
+
+    void sweep() {
+        for (OuterMap::Enum e(map); !e.empty(); e.popFront()) {
+            InnerMap& m = e.front().value();
+            m.sweep();
+            if (m.empty())
+                e.removeFront();
+        }
+    }
+};
 
 // We must ensure that all newly allocated JSObjects get their metadata
 // set. However, metadata builders may require the new object be in a sane
 // state (eg, have its reserved slots initialized so they can get the
 // sizeOfExcludingThis of the object). Therefore, for objects of certain
 // JSClasses (those marked with JSCLASS_DELAY_METADATA_BUILDER), it is not safe
 // for the allocation paths to call the object metadata builder
 // immediately. Instead, the JSClass-specific "constructor" C++ function up the
@@ -673,16 +851,26 @@ struct JSCompartment
     void removeWrapper(js::WrapperMap::Ptr p) {
         crossCompartmentWrappers.remove(p);
     }
 
     struct WrapperEnum : public js::WrapperMap::Enum {
         explicit WrapperEnum(JSCompartment* c) : js::WrapperMap::Enum(c->crossCompartmentWrappers) {}
     };
 
+    struct NonStringWrapperEnum : public js::WrapperMap::Enum {
+        explicit NonStringWrapperEnum(JSCompartment* c) : js::WrapperMap::Enum(c->crossCompartmentWrappers, WithoutStrings) {}
+        explicit NonStringWrapperEnum(JSCompartment* c, const js::CompartmentFilter& f) : js::WrapperMap::Enum(c->crossCompartmentWrappers, f, WithoutStrings) {}
+        explicit NonStringWrapperEnum(JSCompartment* c, JSCompartment* target) : js::WrapperMap::Enum(c->crossCompartmentWrappers, target) { MOZ_ASSERT(target); }
+    };
+
+    struct StringWrapperEnum : public js::WrapperMap::Enum {
+        explicit StringWrapperEnum(JSCompartment* c) : js::WrapperMap::Enum(c->crossCompartmentWrappers, nullptr) {}
+    };
+
     js::LexicalEnvironmentObject*
     getOrCreateNonSyntacticLexicalEnvironment(JSContext* cx, js::HandleObject enclosing);
     js::LexicalEnvironmentObject* getNonSyntacticLexicalEnvironment(JSObject* enclosing) const;
 
     /*
      * This method traces data that is live iff we know that this compartment's
      * global is still live.
      */
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -117,16 +117,17 @@ JS_TraceObjectGroupCycleCollectorChildre
 
 enum {
     JS_TELEMETRY_GC_REASON,
     JS_TELEMETRY_GC_IS_ZONE_GC,
     JS_TELEMETRY_GC_MS,
     JS_TELEMETRY_GC_BUDGET_MS,
     JS_TELEMETRY_GC_ANIMATION_MS,
     JS_TELEMETRY_GC_MAX_PAUSE_MS,
+    JS_TELEMETRY_GC_MAX_PAUSE_MS_2,
     JS_TELEMETRY_GC_MARK_MS,
     JS_TELEMETRY_GC_SWEEP_MS,
     JS_TELEMETRY_GC_COMPACT_MS,
     JS_TELEMETRY_GC_MARK_ROOTS_MS,
     JS_TELEMETRY_GC_MARK_GRAY_MS,
     JS_TELEMETRY_GC_SLICE_MS,
     JS_TELEMETRY_GC_SLOW_PHASE,
     JS_TELEMETRY_GC_SLOW_TASK,
@@ -1225,17 +1226,17 @@ struct CompartmentsWithPrincipals : publ
     virtual bool match(JSCompartment* c) const override {
         return JS_GetCompartmentPrincipals(c) == principals;
     }
 };
 
 extern JS_FRIEND_API(bool)
 NukeCrossCompartmentWrappers(JSContext* cx,
                              const CompartmentFilter& sourceFilter,
-                             const CompartmentFilter& targetFilter,
+                             JSCompartment* target,
                              NukeReferencesToWindow nukeReferencesToWindow,
                              NukeReferencesFromTarget nukeReferencesFromTarget);
 
 /* Specify information about DOMProxy proxies in the DOM, for use by ICs. */
 
 /*
  * The DOMProxyShadowsCheck function will be called to check if the property for
  * id should be gotten from the prototype, or if there is an own property that
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -4017,19 +4017,17 @@ GCRuntime::markCompartments()
         if (comp->maybeAlive) {
             if (!workList.append(comp))
                 return;
         }
     }
 
     while (!workList.empty()) {
         JSCompartment* comp = workList.popCopy();
-        for (JSCompartment::WrapperEnum e(comp); !e.empty(); e.popFront()) {
-            if (e.front().key().is<JSString*>())
-                continue;
+        for (JSCompartment::NonStringWrapperEnum e(comp); !e.empty(); e.popFront()) {
             JSCompartment* dest = e.front().mutableKey().compartment();
             if (dest && !dest->maybeAlive) {
                 dest->maybeAlive = true;
                 if (!workList.append(dest))
                     return;
             }
         }
     }
@@ -4414,19 +4412,19 @@ static void
 DropStringWrappers(JSRuntime* rt)
 {
     /*
      * String "wrappers" are dropped on GC because their presence would require
      * us to sweep the wrappers in all compartments every time we sweep a
      * compartment group.
      */
     for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
-        for (JSCompartment::WrapperEnum e(c); !e.empty(); e.popFront()) {
-            if (e.front().key().is<JSString*>())
-                e.removeFront();
+        for (JSCompartment::StringWrapperEnum e(c); !e.empty(); e.popFront()) {
+            MOZ_ASSERT(e.front().key().is<JSString*>());
+            e.removeFront();
         }
     }
 }
 
 /*
  * Group zones that must be swept at the same time.
  *
  * If compartment A has an edge to an unmarked object in compartment B, then we
@@ -4660,20 +4658,18 @@ AssertNotOnGrayList(JSObject* obj)
 #endif
 
 static void
 AssertNoWrappersInGrayList(JSRuntime* rt)
 {
 #ifdef DEBUG
     for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
         MOZ_ASSERT(!c->gcIncomingGrayPointers);
-        for (JSCompartment::WrapperEnum e(c); !e.empty(); e.popFront()) {
-            if (!e.front().key().is<JSString*>())
-                AssertNotOnGrayList(&e.front().value().unbarrieredGet().toObject());
-        }
+        for (JSCompartment::NonStringWrapperEnum e(c); !e.empty(); e.popFront())
+            AssertNotOnGrayList(&e.front().value().unbarrieredGet().toObject());
     }
 #endif
 }
 
 static JSObject*
 CrossCompartmentPointerReferent(JSObject* obj)
 {
     MOZ_ASSERT(IsGrayListObject(obj));
--- a/js/src/proxy/CrossCompartmentWrapper.cpp
+++ b/js/src/proxy/CrossCompartmentWrapper.cpp
@@ -520,64 +520,75 @@ js::NukeCrossCompartmentWrapper(JSContex
  * obj's global.  The snag here is that we need to avoid cutting wrappers that
  * point to the window object on page navigation (inner window destruction)
  * and only do that on tab close (outer window destruction).  Thus the
  * option of how to handle the global object.
  */
 JS_FRIEND_API(bool)
 js::NukeCrossCompartmentWrappers(JSContext* cx,
                                  const CompartmentFilter& sourceFilter,
-                                 const CompartmentFilter& targetFilter,
+                                 JSCompartment* target,
                                  js::NukeReferencesToWindow nukeReferencesToWindow,
                                  js::NukeReferencesFromTarget nukeReferencesFromTarget)
 {
     CHECK_REQUEST(cx);
     JSRuntime* rt = cx->runtime();
 
     EvictAllNurseries(rt);
 
     for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
         if (!sourceFilter.match(c))
             continue;
 
         // If the compartment matches both the source and target filter, we may
         // want to cut both incoming and outgoing wrappers.
         bool nukeAll = (nukeReferencesFromTarget == NukeAllReferences &&
-                        targetFilter.match(c));
+                        target == c.get());
 
-        // Iterate the wrappers looking for anything interesting.
-        for (JSCompartment::WrapperEnum e(c); !e.empty(); e.popFront()) {
-            // Some cross-compartment wrappers are for strings.  We're not
-            // interested in those.
-            const CrossCompartmentKey& k = e.front().key();
+        // Iterate only the wrappers that have target compartment matched unless
+        // |nukeAll| is true. The string wrappers that we're not interested in
+        // won't be iterated, we can exclude them easily because they have
+        // compartment nullptr. Use Maybe to avoid copying from conditionally
+        // initializing NonStringWrapperEnum.
+        mozilla::Maybe<JSCompartment::NonStringWrapperEnum> e;
+        if (MOZ_LIKELY(!nukeAll))
+            e.emplace(c, target);
+        else
+            e.emplace(c);
+        for (; !e->empty(); e->popFront()) {
+            // Skip debugger references because NukeCrossCompartmentWrapper()
+            // doesn't know how to nuke them yet, see bug 1084626 for more
+            // information.
+            const CrossCompartmentKey& k = e->front().key();
             if (!k.is<JSObject*>())
                 continue;
 
-            AutoWrapperRooter wobj(cx, WrapperValue(e));
-            JSObject* wrapped = UncheckedUnwrap(wobj);
+            AutoWrapperRooter wobj(cx, WrapperValue(*e));
+
+            // Unwrap from the wrapped object in CrossCompartmentKey instead of
+            // the wrapper, this could save us a bit of time.
+            JSObject* wrapped = UncheckedUnwrap(k.as<JSObject*>());
 
             // We never nuke script source objects, since only ever used internally by the JS
             // engine, and are expected to remain valid throughout a scripts lifetime.
             if (MOZ_UNLIKELY(wrapped->is<ScriptSourceObject>())) {
                 continue;
             }
 
             // We only skip nuking window references that point to a target
             // compartment, not the ones that belong to it.
             if (nukeReferencesToWindow == DontNukeWindowReferences &&
                 MOZ_LIKELY(!nukeAll) && IsWindowProxy(wrapped))
             {
                 continue;
             }
 
-            if (MOZ_UNLIKELY(nukeAll) || targetFilter.match(wrapped->compartment())) {
-                // We found a wrapper to nuke.
-                e.removeFront();
-                NukeRemovedCrossCompartmentWrapper(cx, wobj);
-            }
+            // Now this is the wrapper we want to nuke.
+            e->removeFront();
+            NukeRemovedCrossCompartmentWrapper(cx, wobj);
         }
     }
 
     return true;
 }
 
 // Given a cross-compartment wrapper |wobj|, update it to point to
 // |newTarget|. This recomputes the wrapper with JS_WrapValue, and thus can be
@@ -686,26 +697,22 @@ js::RecomputeWrappers(JSContext* cx, con
 
     AutoWrapperVector toRecompute(cx);
     for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next()) {
         // Filter by source compartment.
         if (!sourceFilter.match(c))
             continue;
 
         // Iterate over the wrappers, filtering appropriately.
-        for (JSCompartment::WrapperEnum e(c); !e.empty(); e.popFront()) {
+        for (JSCompartment::NonStringWrapperEnum e(c, targetFilter); !e.empty(); e.popFront()) {
             // Filter out non-objects.
             CrossCompartmentKey& k = e.front().mutableKey();
             if (!k.is<JSObject*>())
                 continue;
 
-            // Filter by target compartment.
-            if (!targetFilter.match(k.compartment()))
-                continue;
-
             // Add it to the list.
             if (!toRecompute.append(WrapperValue(e)))
                 return false;
         }
     }
 
     // Recompute all the wrappers in the list.
     for (const WrapperValue& v : toRecompute) {
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -586,18 +586,17 @@ NukeAllWrappersForCompartment(JSContext*
                               js::NukeReferencesToWindow nukeReferencesToWindow)
 {
     // First, nuke all wrappers into or out of the target compartment. Once
     // the compartment is marked as nuked, WrapperFactory will refuse to
     // create new live wrappers for it, in either direction. This means that
     // we need to be sure that we don't have any existing cross-compartment
     // wrappers which may be replaced with dead wrappers during unrelated
     // wrapper recomputation *before* we set that bit.
-    js::NukeCrossCompartmentWrappers(cx, js::AllCompartments(),
-                                     js::SingleCompartment(compartment),
+    js::NukeCrossCompartmentWrappers(cx, js::AllCompartments(), compartment,
                                      nukeReferencesToWindow,
                                      js::NukeAllReferences);
 
     // At this point, we should cross-compartment wrappers for the nuked
     // compartment. Set the wasNuked bit so WrapperFactory will return a
     // DeadObjectProxy when asked to create a new wrapper for it, and mark as
     // unscriptable.
     auto compartmentPrivate = xpc::CompartmentPrivate::Get(compartment);
@@ -2691,16 +2690,19 @@ AccumulateTelemetryCallback(int id, uint
         Telemetry::Accumulate(Telemetry::GC_BUDGET_MS, sample);
         break;
       case JS_TELEMETRY_GC_ANIMATION_MS:
         Telemetry::Accumulate(Telemetry::GC_ANIMATION_MS, sample);
         break;
       case JS_TELEMETRY_GC_MAX_PAUSE_MS:
         Telemetry::Accumulate(Telemetry::GC_MAX_PAUSE_MS, sample);
         break;
+      case JS_TELEMETRY_GC_MAX_PAUSE_MS_2:
+        Telemetry::Accumulate(Telemetry::GC_MAX_PAUSE_MS_2, sample);
+        break;
       case JS_TELEMETRY_GC_MARK_MS:
         Telemetry::Accumulate(Telemetry::GC_MARK_MS, sample);
         break;
       case JS_TELEMETRY_GC_SWEEP_MS:
         Telemetry::Accumulate(Telemetry::GC_SWEEP_MS, sample);
         break;
       case JS_TELEMETRY_GC_COMPACT_MS:
         Telemetry::Accumulate(Telemetry::GC_COMPACT_MS, sample);
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/FxAccountPushHandler.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/fxa/FxAccountPushHandler.java
@@ -92,15 +92,13 @@ public class FxAccountPushHandler {
     private static void handleDeviceDisconnection(Context context, JSONObject data) throws JSONException {
         final Account account = FirefoxAccounts.getFirefoxAccount(context);
         if (account == null) {
             Log.e(LOG_TAG, "The account does not exist anymore");
             return;
         }
         final AndroidFxAccount fxAccount = new AndroidFxAccount(context, account);
         if (!fxAccount.getDeviceId().equals(data.getString("id"))) {
-            Log.e(LOG_TAG, "The device ID to disconnect doesn't match with the local device ID.\n"
-                            + "Local: " + fxAccount.getDeviceId() + ", ID to disconnect: " + data.getString("id"));
             return;
         }
         AccountManager.get(context).removeAccount(account, null, null);
     }
 }
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -1,15 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, # You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import argparse
+import collections
 import errno
 import itertools
 import json
 import logging
 import operator
 import os
 import subprocess
 import sys
@@ -470,31 +471,65 @@ class Build(MachCommandBase):
             # inline output from the compiler itself. However, unlike inline
             # output, this list is sorted and grouped by file, making it
             # easier to triage output.
             #
             # Only do this if we had a successful build. If the build failed,
             # there are more important things in the log to look for than
             # whatever code we warned about.
             if not status:
+                # Suppress warnings for 3rd party projects in local builds
+                # until we suppress them for real.
+                # TODO remove entries/feature once we stop generating warnings
+                # in these directories.
+                LOCAL_SUPPRESS_DIRS = (
+                    'gfx/angle',
+                    'gfx/cairo',
+                    'intl/icu/source',
+                    'js/src/ctypes/libffi',
+                    'media/libtheora',
+                    'media/mtransport/third_party/nICEr',
+                    'media/mtransport/third_party/nrappkit',
+                    'media/webrtc/trunk/webrtc',
+                    'netwerk/sctp/src/netinet',
+                    'nsprpub',
+                    'security/nss',
+                )
+
+                suppressed_by_dir = collections.Counter()
+
                 for warning in sorted(monitor.instance_warnings):
                     path = mozpath.normsep(warning['filename'])
                     if path.startswith(self.topsrcdir):
                         path = path[len(self.topsrcdir) + 1:]
 
                     warning['normpath'] = path
 
+                    if (path.startswith(LOCAL_SUPPRESS_DIRS) and
+                            'MOZ_AUTOMATION' not in os.environ):
+                        for d in LOCAL_SUPPRESS_DIRS:
+                            if path.startswith(d):
+                                suppressed_by_dir[d] += 1
+                                break
+
+                        continue
+
                     if warning['column'] is not None:
                         self.log(logging.WARNING, 'compiler_warning', warning,
                                  'warning: {normpath}:{line}:{column} [{flag}] '
                                  '{message}')
                     else:
                         self.log(logging.WARNING, 'compiler_warning', warning,
                                  'warning: {normpath}:{line} [{flag}] {message}')
 
+                for d, count in sorted(suppressed_by_dir.items()):
+                    self.log(logging.WARNING, 'suppressed_warning',
+                             {'dir': d, 'count': count},
+                             '(suppressed {count} warnings in {dir})')
+
             monitor.finish(record_usage=status==0)
 
         high_finder, finder_percent = monitor.have_high_finder_usage()
         if high_finder:
             print(FINDER_SLOW_MESSAGE % finder_percent)
 
         ccache_end = monitor.ccache_stats()
 
--- a/security/certverifier/ExtendedValidation.cpp
+++ b/security/certverifier/ExtendedValidation.cpp
@@ -643,28 +643,16 @@ static const struct EVInfo kEVInfos[] = 
     { 0xEE, 0xC5, 0x49, 0x6B, 0x98, 0x8C, 0xE9, 0x86, 0x25, 0xB9, 0x34,
       0x09, 0x2E, 0xEC, 0x29, 0x08, 0xBE, 0xD0, 0xB0, 0xF3, 0x16, 0xC2,
       0xD4, 0x73, 0x0C, 0x84, 0xEA, 0xF1, 0xF3, 0xD3, 0x48, 0x81 },
     "MFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMM"
     "IUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOQ==",
     "CYP0",
   },
   {
-    // CN=Swisscom Root EV CA 2,OU=Digital Certificate Services,O=Swisscom,C=ch
-    "2.16.756.1.83.21.0",
-    "Swisscom  EV OID",
-    { 0xD9, 0x5F, 0xEA, 0x3C, 0xA4, 0xEE, 0xDC, 0xE7, 0x4C, 0xD7, 0x6E,
-      0x75, 0xFC, 0x6D, 0x1F, 0xF6, 0x2C, 0x44, 0x1F, 0x0F, 0xA8, 0xBC,
-      0x77, 0xF0, 0x34, 0xB1, 0x9E, 0x5D, 0xB2, 0x58, 0x01, 0x5D },
-    "MGcxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln"
-    "aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEeMBwGA1UEAxMVU3dpc3Njb20gUm9v"
-    "dCBFViBDQSAy",
-    "APL6ZOJ0Y9ON/RAdBB92ylg=",
-  },
-  {
     // CN=VeriSign Universal Root Certification Authority,OU="(c) 2008 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US
     "2.16.840.1.113733.1.7.23.6",
     "VeriSign EV OID",
     { 0x23, 0x99, 0x56, 0x11, 0x27, 0xA5, 0x71, 0x25, 0xDE, 0x8C, 0xEF,
       0xEA, 0x61, 0x0D, 0xDF, 0x2F, 0xA0, 0x78, 0xB5, 0xC8, 0x06, 0x7F,
       0x4E, 0x82, 0x82, 0x90, 0xBF, 0xB8, 0x60, 0xE8, 0x4B, 0x3C },
     "MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNV"
     "BAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZl"
--- a/security/manager/ssl/security-prefs.js
+++ b/security/manager/ssl/security-prefs.js
@@ -42,17 +42,25 @@ pref("security.password_lifetime",      
 // 0: disable detecting Family Safety mode and importing the root
 // 1: only attempt to detect Family Safety mode (don't import the root)
 // 2: detect Family Safety mode and import the root
 // (This is only relevant to Windows 8.1)
 pref("security.family_safety.mode", 2);
 
 pref("security.enterprise_roots.enabled", false);
 
+// The supported values of this pref are:
+// 0: do not fetch OCSP
+// 1: fetch OCSP for DV and EV certificates
+// 2: fetch OCSP only for EV certificates
+#ifdef RELEASE_OR_BETA
 pref("security.OCSP.enabled", 1);
+#else
+pref("security.OCSP.enabled", 2);
+#endif
 pref("security.OCSP.require", false);
 pref("security.OCSP.GET.enabled", false);
 #ifdef RELEASE_OR_BETA
 pref("security.OCSP.timeoutMilliseconds.soft", 2000);
 #else
 pref("security.OCSP.timeoutMilliseconds.soft", 1000);
 #endif
 pref("security.OCSP.timeoutMilliseconds.hard", 10000);
--- a/services/fxaccounts/FxAccounts.jsm
+++ b/services/fxaccounts/FxAccounts.jsm
@@ -1567,19 +1567,16 @@ FxAccountsInternal.prototype = {
           // caused us to get here via push!), so don't make noise here.
           log.info(`Push request to disconnect, but we've already disconnected`);
           return null;
         }
         if (deviceId == localDeviceId) {
           this.notifyObservers(ON_DEVICE_DISCONNECTED_NOTIFICATION);
           return this.signOut(true);
         }
-        log.error(
-          `The device ID to disconnect doesn't match with the local device ID. ` +
-          `Local: ${localDeviceId}, ID to disconnect: ${deviceId}`);
         return null;
     });
   },
 
   handleAccountDestroyed(uid) {
     return this.currentAccountState.getUserAccountData()
       .then(data => data ? data.uid : null)
       .then(localUid => {
--- a/services/sync/modules/policies.js
+++ b/services/sync/modules/policies.js
@@ -179,19 +179,21 @@ SyncScheduler.prototype = {
           // changed during the last sync, and we should schedule an immediate
           // follow-up sync.
           this._resyncs++;
           if (this._resyncs <= this.maxResyncs) {
             sync_interval = 0;
           } else {
             this._log.warn(`Resync attempt ${this._resyncs} exceeded ` +
                            `maximum ${this.maxResyncs}`);
+            Svc.Obs.notify("weave:service:resyncs-finished");
           }
         } else {
           this._resyncs = 0;
+          Svc.Obs.notify("weave:service:resyncs-finished");
         }
 
         this._syncErrors = 0;
         if (Status.sync == NO_SYNC_NODE_FOUND) {
           // If we don't have a Sync node, override the interval, even if we've
           // scheduled a follow-up sync.
           this._log.trace("Scheduling a sync at interval NO_SYNC_NODE_FOUND.");
           sync_interval = NO_SYNC_NODE_INTERVAL;
--- a/services/sync/tps/extensions/tps/resource/modules/tabs.jsm
+++ b/services/sync/tps/extensions/tps/resource/modules/tabs.jsm
@@ -24,20 +24,20 @@ var BrowserTabs = {
    * @return nothing
    */
   Add(uri, fn) {
     // Open the uri in a new tab in the current browser window, and calls
     // the callback fn from the tab's onload handler.
     let wm = Cc["@mozilla.org/appshell/window-mediator;1"]
                .getService(Ci.nsIWindowMediator);
     let mainWindow = wm.getMostRecentWindow("navigator:browser");
-    let newtab = mainWindow.getBrowser().addTab(uri);
-    mainWindow.getBrowser().selectedTab = newtab;
-    let win = mainWindow.getBrowser().getBrowserForTab(newtab);
-    win.addEventListener("load", function() { fn.call(); }, true);
+    let browser = mainWindow.getBrowser();
+    browser.addEventListener("load", fn, { once: true });
+    let newtab = browser.addTab(uri);
+    browser.selectedTab = newtab;
   },
 
   /**
    * Find
    *
    * Finds the specified uri and title in Weave's list of remote tabs
    * for the specified profile.
    *
--- a/services/sync/tps/extensions/tps/resource/tps.jsm
+++ b/services/sync/tps/extensions/tps/resource/tps.jsm
@@ -95,17 +95,18 @@ const OBSERVER_TOPICS = ["fxaccounts:onl
                          "sessionstore-windows-restored",
                          "weave:engine:start-tracking",
                          "weave:engine:stop-tracking",
                          "weave:service:login:error",
                          "weave:service:setup-complete",
                          "weave:service:sync:finish",
                          "weave:service:sync:delayed",
                          "weave:service:sync:error",
-                         "weave:service:sync:start"
+                         "weave:service:sync:start",
+                         "weave:service:resyncs-finished",
                         ];
 
 var TPS = {
   _currentAction: -1,
   _currentPhase: -1,
   _enabledEngines: null,
   _errors: 0,
   _isTracking: false,
@@ -208,17 +209,17 @@ var TPS = {
           } else {
             this._triggeredSync = false;
             this.DumpError("Sync error; aborting test");
             return;
           }
 
           break;
 
-        case "weave:service:sync:finish":
+        case "weave:service:resyncs-finished":
           this._syncActive = false;
           this._syncErrors = 0;
           this._triggeredSync = false;
 
           this.delayAutoSync();
 
           // Wait a second before continuing, otherwise we can get
           // 'sync not complete' errors.
@@ -1112,17 +1113,17 @@ var TPS = {
     }
   },
 
   /**
    * Waits for Sync to be finished before returning
    */
   waitForSyncFinished: function TPS__waitForSyncFinished() {
     if (this._syncActive) {
-      this.waitForEvent("weave:service:sync:finished");
+      this.waitForEvent("weave:service:resyncs-finished");
     }
   },
 
   /**
    * Waits for Sync to start tracking before returning.
    */
   waitForTracking: function waitForTracking() {
     if (!this._isTracking) {
--- a/servo/support/android/openssl.makefile
+++ b/servo/support/android/openssl.makefile
@@ -5,10 +5,10 @@ all: openssl
 # From http://wiki.openssl.org/index.php/Android
 .PHONY: openssl
 openssl: openssl-1.0.1t/libssl.so
 
 openssl-1.0.1t/libssl.so: openssl-1.0.1t/Configure
 	./openssl.sh ${ANDROID_NDK}
 
 openssl-1.0.1t/Configure:
-	wget https://www.openssl.org/source/openssl-1.0.1t.tar.gz
+	wget https://www.openssl.org/source/old/1.0.1/openssl-1.0.1t.tar.gz
 	tar -zxf openssl-1.0.1t.tar.gz
--- a/taskcluster/docs/parameters.rst
+++ b/taskcluster/docs/parameters.rst
@@ -17,20 +17,16 @@ file if necessary, rather than starting 
 complete set of parameters.
 
 The properties of the parameters object are described here, divided rougly by
 topic.
 
 Push Information
 ----------------
 
-``triggered_by``
-   The event that precipitated this decision task; one of ``"nightly"`` or
-   ``"push"``.
-
 ``base_repository``
    The repository from which to do an initial clone, utilizing any available
    caching.
 
 ``head_repository``
    The repository containing the changeset to be built.  This may differ from
    ``base_repository`` in cases where ``base_repository`` is likely to be cached
    and only a few additional commits are needed from ``head_repository``.
--- a/taskcluster/mach_commands.py
+++ b/taskcluster/mach_commands.py
@@ -144,20 +144,16 @@ class MachCommands(MachCommandBase):
                      type=int,
                      default=0)
     @CommandArgument('--owner',
                      required=True,
                      help='email address of who owns this graph')
     @CommandArgument('--level',
                      required=True,
                      help='SCM level of this repository')
-    @CommandArgument('--triggered-by',
-                     choices=['nightly', 'push'],
-                     default='push',
-                     help='Source of execution of the decision graph')
     @CommandArgument('--target-tasks-method',
                      help='method for selecting the target tasks to generate')
     def taskgraph_decision(self, **options):
         """Run the decision task: generate a task graph and submit to
         TaskCluster.  This is only meant to be called within decision tasks,
         and requires a great many arguments.  Commands like `mach taskgraph
         optimized` are better suited to use on the command line, and can take
         the parameters file generated by a decision task.  """
--- a/taskcluster/taskgraph/cron/decision.py
+++ b/taskcluster/taskgraph/cron/decision.py
@@ -11,18 +11,16 @@ import pipes
 import yaml
 import re
 import os
 import slugid
 
 
 def run_decision_task(job, params):
     arguments = []
-    if 'triggered-by' in job:
-        arguments.append('--triggered-by={}'.format(job['triggered-by']))
     if 'target-tasks-method' in job:
         arguments.append('--target-tasks-method={}'.format(job['target-tasks-method']))
     return [
         make_decision_task(
             params,
             symbol=job['treeherder-symbol'],
             arguments=arguments),
     ]
--- a/taskcluster/taskgraph/cron/schema.py
+++ b/taskcluster/taskgraph/cron/schema.py
@@ -28,19 +28,16 @@ cron_yml_schema = Schema({
 
         # Description of the job to run, keyed by 'type'
         Required('job'): Any({
             Required('type'): 'decision-task',
 
             # Treeherder symbol for the cron task
             Required('treeherder-symbol'): basestring,
 
-            # --triggered-by './mach taskgraph decision' argument
-            'triggered-by': basestring,
-
             # --target-tasks-method './mach taskgraph decision' argument
             'target-tasks-method': basestring,
         }),
 
         # when to run it
 
         # Optional set of projects on which this job should run; if omitted, this will
         # run on all projects for which cron tasks are set up.  This works just like the
--- a/taskcluster/taskgraph/decision.py
+++ b/taskcluster/taskgraph/decision.py
@@ -152,17 +152,16 @@ def get_decision_parameters(options):
         'head_rev',
         'head_ref',
         'message',
         'project',
         'pushlog_id',
         'pushdate',
         'owner',
         'level',
-        'triggered_by',
         'target_tasks_method',
     ] if n in options}
 
     # Define default filter list, as most configurations shouldn't need
     # custom filters.
     parameters['filters'] = [
         'check_servo',
         'target_tasks_method',
--- a/taskcluster/taskgraph/parameters.py
+++ b/taskcluster/taskgraph/parameters.py
@@ -23,17 +23,16 @@ PARAMETER_NAMES = set([
     'message',
     'moz_build_date',
     'optimize_target_tasks',
     'owner',
     'project',
     'pushdate',
     'pushlog_id',
     'target_tasks_method',
-    'triggered_by',
 ])
 
 
 class Parameters(ReadOnlyDict):
     """An immutable dictionary with nicer KeyError messages on failure"""
     def check(self):
         names = set(self)
         msg = []
--- a/testing/mozharness/configs/builds/releng_base_android_64_builds.py
+++ b/testing/mozharness/configs/builds/releng_base_android_64_builds.py
@@ -43,16 +43,25 @@ config = {
          'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/mozilla-fennec-geoloc-api.key',
          'min_scm_level': 2, 'default': 'try-build-has-no-secrets'},
         {'filename': '/builds/adjust-sdk.token',
          'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/adjust-sdk.token',
          'min_scm_level': 2, 'default': 'try-build-has-no-secrets'},
         {'filename': '/builds/adjust-sdk-beta.token',
          'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/adjust-sdk-beta.token',
          'min_scm_level': 2, 'default': 'try-build-has-no-secrets'},
+        {'filename': '/builds/leanplum-sdk-release.token',
+         'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/leanplum-sdk-release.token',
+         'min_scm_level': 2, 'default': 'try-build-has-no-secrets'},
+        {'filename': '/builds/leanplum-sdk-beta.token',
+         'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/leanplum-sdk-beta.token',
+         'min_scm_level': 2, 'default': 'try-build-has-no-secrets'},
+        {'filename': '/builds/leanplum-sdk-nightly.token',
+         'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/leanplum-sdk-nightly.token',
+         'min_scm_level': 2, 'default': 'try-build-has-no-secrets'},
     ],
     'vcs_share_base': '/builds/hg-shared',
     'objdir': 'obj-firefox',
     'tooltool_script': ["/builds/tooltool.py"],
     'tooltool_bootstrap': "setup.sh",
     'enable_count_ctors': False,
     'enable_talos_sendchange': False,
     'enable_unittest_sendchange': True,
--- a/testing/tps/tps/testrunner.py
+++ b/testing/tps/tps/testrunner.py
@@ -73,16 +73,17 @@ class TPSTestRunner(object):
         'extensions.update.notifyUser': False,
         'services.sync.firstSync': 'notReady',
         'services.sync.lastversion': '1.0',
         'toolkit.startup.max_resumed_crashes': -1,
         # hrm - not sure what the release/beta channels will do?
         'xpinstall.signatures.required': False,
         'services.sync.testing.tps': True,
         'engine.bookmarks.repair.enabled': False,
+        'extensions.allow-non-mpc-extensions': True,
     }
 
     debug_preferences = {
         'services.sync.log.appender.console': 'Trace',
         'services.sync.log.appender.dump': 'Trace',
         'services.sync.log.appender.file.level': 'Trace',
         'services.sync.log.appender.file.logOnSuccess': True,
         'services.sync.log.rootLogger': 'Trace',
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -748,20 +748,22 @@
     "kind": "exponential",
     "high": 10000,
     "n_buckets": 50,
     "description": "Full pause time for one cycle collection, including preparation (ms)"
   },
   "CYCLE_COLLECTOR_MAX_PAUSE": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"],
-    "expires_in_version": "never",
-    "kind": "exponential",
-    "high": 10000,
-    "n_buckets": 50,
+    "bug_numbers": [1364503],
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": 10000,
+    "n_buckets": 50,
+    "releaseChannelCollection": "opt-out",
     "description": "Longest pause for an individual slice of one cycle collection, including preparation (ms)"
   },
   "CYCLE_COLLECTOR_FINISH_IGC": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"],
     "expires_in_version": "never",
     "kind": "boolean",
     "description": "Cycle collection finished an incremental GC"
@@ -991,22 +993,34 @@
     "kind": "exponential",
     "high": 10000,
     "n_buckets": 50,
     "description": "Time spent running JS GC when animating (ms)"
   },
   "GC_MAX_PAUSE_MS": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"],
-    "expires_in_version": "never",
+    "bug_numbers": [1364503],
+    "expires_in_version": "61",
     "kind": "linear",
     "high": 1000,
     "n_buckets": 50,
     "description": "Longest GC slice in a GC (ms)"
   },
+  "GC_MAX_PAUSE_MS_2": {
+    "record_in_processes": ["main", "content"],
+    "alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"],
+    "bug_numbers": [1364503],
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": 10000,
+    "n_buckets": 50,
+    "releaseChannelCollection": "opt-out",
+    "description": "Longest GC slice in a GC (ms)"
+  },
   "GC_MARK_MS": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 10000,
     "n_buckets": 50,
     "description": "Time spent running JS GC mark phase (ms)"
--- a/toolkit/components/telemetry/histogram-whitelists.json
+++ b/toolkit/components/telemetry/histogram-whitelists.json
@@ -766,17 +766,16 @@
     "CONTENT_DOCUMENTS_DESTROYED",
     "COOKIE_SCHEME_SECURITY",
     "CRASH_STORE_COMPRESSED_BYTES",
     "CYCLE_COLLECTOR",
     "CYCLE_COLLECTOR_ASYNC_SNOW_WHITE_FREEING",
     "CYCLE_COLLECTOR_COLLECTED",
     "CYCLE_COLLECTOR_FINISH_IGC",
     "CYCLE_COLLECTOR_FULL",
-    "CYCLE_COLLECTOR_MAX_PAUSE",
     "CYCLE_COLLECTOR_NEED_GC",
     "CYCLE_COLLECTOR_OOM",
     "CYCLE_COLLECTOR_SYNC_SKIPPABLE",
     "CYCLE_COLLECTOR_TIME_BETWEEN",
     "CYCLE_COLLECTOR_VISITED_GCED",
     "CYCLE_COLLECTOR_VISITED_REF_COUNTED",
     "CYCLE_COLLECTOR_WORKER",
     "CYCLE_COLLECTOR_WORKER_COLLECTED",
@@ -971,17 +970,16 @@
     "GC_ANIMATION_MS",
     "GC_BUDGET_MS",
     "GC_COMPACT_MS",
     "GC_INCREMENTAL_DISABLED",
     "GC_IS_COMPARTMENTAL",
     "GC_MARK_GRAY_MS",
     "GC_MARK_MS",
     "GC_MARK_ROOTS_MS",
-    "GC_MAX_PAUSE_MS",
     "GC_MINOR_REASON",
     "GC_MINOR_REASON_LONG",
     "GC_MINOR_US",
     "GC_MMU_50",
     "GC_MS",
     "GC_NON_INCREMENTAL",
     "GC_REASON_2",
     "GC_RESET",
--- a/toolkit/components/telemetry/histogram_tools.py
+++ b/toolkit/components/telemetry/histogram_tools.py
@@ -69,30 +69,32 @@ def exponential_buckets(dmin, dmax, n_bu
         ret_array[bucket_index] = current
     return ret_array
 
 always_allowed_keys = ['kind', 'description', 'cpp_guard', 'expires_in_version',
                        'alert_emails', 'keyed', 'releaseChannelCollection',
                        'bug_numbers', 'record_in_processes']
 
 whitelists = None
-try:
-    whitelist_path = os.path.join(os.path.abspath(os.path.realpath(os.path.dirname(__file__))),
-                                  'histogram-whitelists.json')
-    with open(whitelist_path, 'r') as f:
-        try:
-            whitelists = json.load(f)
-            for name, whitelist in whitelists.iteritems():
-                whitelists[name] = set(whitelist)
-        except ValueError, e:
-            raise ParserError('Error parsing whitelist: %s' % whitelist_path)
-except IOError:
-    whitelists = None
-    print('Unable to parse whitelist: %s.\nAssuming all histograms are acceptable.' %
-          whitelist_path)
+
+
+def load_whitelist():
+    try:
+        whitelist_path = os.path.join(os.path.abspath(os.path.realpath(os.path.dirname(__file__))),
+                                      'histogram-whitelists.json')
+        with open(whitelist_path, 'r') as f:
+            try:
+                whitelists = json.load(f)
+                for name, whitelist in whitelists.iteritems():
+                    whitelists[name] = set(whitelist)
+            except ValueError:
+                raise ParserError('Error parsing whitelist: %s' % whitelist_path)
+    except IOError:
+        whitelists = None
+        raise ParserError('Unable to parse whitelist: %s.' % whitelist_path)
 
 
 class Histogram:
     """A class for representing a histogram definition."""
 
     def __init__(self, name, definition, strict_type_checks=False):
         """Initialize a histogram named name with the given definition.
 definition is a dict-like object that must contain at least the keys:
@@ -589,16 +591,19 @@ try:
 except ImportError:
     pass
 
 
 def from_files(filenames, strict_type_checks=True):
     """Return an iterator that provides a sequence of Histograms for
 the histograms defined in filenames.
     """
+    if strict_type_checks:
+        load_whitelist()
+
     all_histograms = OrderedDict()
     for filename in filenames:
         parser = FILENAME_PARSERS[os.path.basename(filename)]
         histograms = parser(filename, strict_type_checks)
 
         # OrderedDicts are important, because then the iteration order over
         # the parsed histograms is stable, which makes the insertion into
         # all_histograms stable, which makes ordering in generated files
--- a/toolkit/content/tests/widgets/test_videocontrols.html
+++ b/toolkit/content/tests/widgets/test_videocontrols.html
@@ -415,20 +415,25 @@ function runTest(event) {
       is(event.type, "seeked", "checking event type");
       ok(true, "video position is at " + video.currentTime);
       synthesizeMouse(video, scrubberOffsetX + 10, scrubberCenterY, {});
       break;
 
     case 33:
       is(event.type, "play", "checking event type");
       ok(true, "video resume after mouseup");
+      synthesizeMouse(video, playButtonCenterX, playButtonCenterY, { });
+      break;
+
+    // Bug 1367194: Always ensure video is paused before calling SimpleTest.finish().
+    case 34:
+      is(event.type, "pause", "checking event type");
       SimpleTest.finish();
       break;
 
-
     default:
       throw "unexpected test #" + testnum + " w/ event " + event.type;
   }
 
   testnum++;
 }
 
 
--- a/toolkit/mozapps/extensions/AddonManagerWebAPI.cpp
+++ b/toolkit/mozapps/extensions/AddonManagerWebAPI.cpp
@@ -15,16 +15,32 @@
 #include "nsIDocShell.h"
 #include "nsIScriptObjectPrincipal.h"
 
 namespace mozilla {
 using namespace mozilla::dom;
 
 static bool
 IsValidHost(const nsACString& host) {
+  // This is ugly, but Preferences.h doesn't have support
+  // for default prefs or locked prefs
+  nsCOMPtr<nsIPrefService> prefService (do_GetService(NS_PREFSERVICE_CONTRACTID));
+  nsCOMPtr<nsIPrefBranch> prefs;
+  if (prefService) {
+    prefService->GetDefaultBranch(nullptr, getter_AddRefs(prefs));
+    bool isEnabled;
+    if (NS_SUCCEEDED(prefs->GetBoolPref("xpinstall.enabled", &isEnabled)) && !isEnabled) {
+      bool isLocked;
+      prefs->PrefIsLocked("xpinstall.enabled", &isLocked);
+      if (isLocked) {
+        return false;
+      }
+    }
+  }
+
   if (host.Equals("addons.mozilla.org") ||
       host.Equals("discovery.addons.mozilla.org") ||
       host.Equals("testpilot.firefox.com")) {
     return true;
   }
 
   // When testing allow access to the developer sites.
   if (Preferences::GetBool("extensions.webapi.testing", false)) {
--- a/xpcom/threads/MozPromise.h
+++ b/xpcom/threads/MozPromise.h
@@ -1046,40 +1046,49 @@ public:
   explicit Private(const char* aCreationSite, bool aIsCompletionPromise = false)
     : MozPromise(aCreationSite, aIsCompletionPromise) {}
 
   template<typename ResolveValueT_>
   void Resolve(ResolveValueT_&& aResolveValue, const char* aResolveSite)
   {
     PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic && mMagic3 == sMagic && mMagic4 == &mMutex);
     MutexAutoLock lock(mMutex);
-    MOZ_ASSERT(IsPending());
     PROMISE_LOG("%s resolving MozPromise (%p created at %s)", aResolveSite, this, mCreationSite);
+    if (!IsPending()) {
+      PROMISE_LOG("%s ignored already resolved or rejected MozPromise (%p created at %s)", aResolveSite, this, mCreationSite);
+      return;
+    }
     mValue.SetResolve(Forward<ResolveValueT_>(aResolveValue));
     DispatchAll();
   }
 
   template<typename RejectValueT_>
   void Reject(RejectValueT_&& aRejectValue, const char* aRejectSite)
   {
     PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic && mMagic3 == sMagic && mMagic4 == &mMutex);
     MutexAutoLock lock(mMutex);
-    MOZ_ASSERT(IsPending());
     PROMISE_LOG("%s rejecting MozPromise (%p created at %s)", aRejectSite, this, mCreationSite);
+    if (!IsPending()) {
+      PROMISE_LOG("%s ignored already resolved or rejected MozPromise (%p created at %s)", aRejectSite, this, mCreationSite);
+      return;
+    }
     mValue.SetReject(Forward<RejectValueT_>(aRejectValue));
     DispatchAll();
   }
 
   template<typename ResolveOrRejectValue_>
   void ResolveOrReject(ResolveOrRejectValue_&& aValue, const char* aSite)
   {
     PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic && mMagic3 == sMagic && mMagic4 == &mMutex);
     MutexAutoLock lock(mMutex);
-    MOZ_ASSERT(IsPending());
     PROMISE_LOG("%s resolveOrRejecting MozPromise (%p created at %s)", aSite, this, mCreationSite);
+    if (!IsPending()) {
+      PROMISE_LOG("%s ignored already resolved or rejected MozPromise (%p created at %s)", aSite, this, mCreationSite);
+      return;
+    }
     mValue = Forward<ResolveOrRejectValue_>(aValue);
     DispatchAll();
   }
 };
 
 // A generic promise type that does the trick for simple use cases.
 typedef MozPromise<bool, nsresult, /* IsExclusive = */ false> GenericPromise;