merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Wed, 06 Sep 2017 11:26:13 +0200
changeset 379144 c959327c6b75
parent 379116 c6e59f1b2e27 (current diff)
parent 379143 a4252412b1ac (diff)
child 379145 59255da13844
child 379165 b38fde90b1c8
child 379306 21229f14023f
push id32449
push userarchaeopteryx@coole-files.de
push date2017-09-06 09:33 +0000
treeherdermozilla-central@c959327c6b75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone57.0a1
first release with
nightly linux64
c959327c6b75 / 57.0a1 / 20170906100107 / files
nightly mac
c959327c6b75 / 57.0a1 / 20170906100107 / files
nightly win32
c959327c6b75 / 57.0a1 / 20170906100107 / files
nightly win64
c959327c6b75 / 57.0a1 / 20170906100107 / files
nightly linux32
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central. r=merge a=merge MozReview-Commit-ID: KLssMPhSQ0O
mobile/android/mach_commands.py
testing/mozbase/manifestparser/manifestparser/manifestparser.py
testing/mozharness/manifestparser/manifestparser.py
toolkit/components/telemetry/histogram_tools.py
toolkit/components/telemetry/parse_scalars.py
toolkit/content/aboutTelemetry.js
toolkit/locales/en-US/chrome/global/aboutTelemetry.properties
--- a/browser/components/resistfingerprinting/test/browser/browser_navigator.js
+++ b/browser/components/resistfingerprinting/test/browser/browser_navigator.js
@@ -86,17 +86,17 @@ async function testWorkerNavigator() {
 
 add_task(async function setup() {
   await SpecialPowers.pushPrefEnv({"set":
     [["privacy.resistFingerprinting", true]]
   });
 
   let appInfo = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
   let appVersion = parseInt(appInfo.version);
-  let spoofedVersion = appVersion - (appVersion % 10);
+  let spoofedVersion = appVersion - ((appVersion - 3) % 7);
   spoofedUserAgent = `Mozilla/5.0 (Windows NT 6.1; rv:${spoofedVersion}.0) Gecko/20100101 Firefox/${spoofedVersion}.0`;
 });
 
 add_task(async function runNavigatorTest() {
   await testNavigator();
 });
 
 add_task(async function runWorkerNavigatorTest() {
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -2,17 +2,16 @@
 /* vim: set ts=2 sw=2 et tw=80: */
 /* 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/. */
 
 #include "mozilla/BasePrincipal.h"
 
 #include "nsDocShell.h"
-#include "nsIAddonPolicyService.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIStandardURL.h"
 
 #include "ContentPrincipal.h"
 #include "nsNetUtil.h"
 #include "nsIURIWithPrincipal.h"
@@ -326,34 +325,39 @@ BasePrincipal::GetPrivateBrowsingId(uint
 
 NS_IMETHODIMP
 BasePrincipal::GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement)
 {
   *aIsInIsolatedMozBrowserElement = IsInIsolatedMozBrowserElement();
   return NS_OK;
 }
 
-bool
-BasePrincipal::AddonHasPermission(const nsAString& aPerm)
+nsresult
+BasePrincipal::GetAddonPolicy(nsISupports** aResult)
 {
-  nsAutoString addonId;
-  NS_ENSURE_SUCCESS(GetAddonId(addonId), false);
+  *aResult = AddonPolicy();
+  return NS_OK;
+}
 
-  if (addonId.IsEmpty()) {
-    return false;
+extensions::WebExtensionPolicy*
+BasePrincipal::AddonPolicy()
+{
+  if (Is<ContentPrincipal>()) {
+    return As<ContentPrincipal>()->AddonPolicy();
   }
-
-  nsCOMPtr<nsIAddonPolicyService> aps =
-    do_GetService("@mozilla.org/addons/policy-service;1");
-  NS_ENSURE_TRUE(aps, false);
+  return nullptr;
+}
 
-  bool retval = false;
-  nsresult rv = aps->AddonHasPermission(addonId, aPerm, &retval);
-  NS_ENSURE_SUCCESS(rv, false);
-  return retval;
+bool
+BasePrincipal::AddonHasPermission(const nsIAtom* aPerm)
+{
+  if (auto policy = AddonPolicy()) {
+    return policy->HasPermission(aPerm);
+  }
+  return false;
 }
 
 already_AddRefed<BasePrincipal>
 BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI,
                                        const OriginAttributes& aAttrs)
 {
   MOZ_ASSERT(aURI);
 
@@ -443,29 +447,20 @@ BasePrincipal::CloneStrippingUserContext
   NS_ENSURE_SUCCESS(rv, nullptr);
 
   return BasePrincipal::CreateCodebasePrincipal(uri, attrs);
 }
 
 bool
 BasePrincipal::AddonAllowsLoad(nsIURI* aURI, bool aExplicit /* = false */)
 {
-  nsAutoString addonId;
-  NS_ENSURE_SUCCESS(GetAddonId(addonId), false);
-
-  if (addonId.IsEmpty()) {
-    return false;
+  if (auto policy = AddonPolicy()) {
+    return policy->CanAccessURI(aURI, aExplicit);
   }
-
-  nsCOMPtr<nsIAddonPolicyService> aps = do_GetService("@mozilla.org/addons/policy-service;1");
-  NS_ENSURE_TRUE(aps, false);
-
-  bool allowed = false;
-  nsresult rv = aps->AddonMayLoadURI(addonId, aURI, aExplicit, &allowed);
-  return NS_SUCCEEDED(rv) && allowed;
+  return false;
 }
 
 void
 BasePrincipal::FinishInit(const nsACString& aOriginNoSuffix,
                           const OriginAttributes& aOriginAttributes)
 {
   mInitialized = true;
   mOriginAttributes = aOriginAttributes;
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -7,24 +7,28 @@
 #ifndef mozilla_BasePrincipal_h
 #define mozilla_BasePrincipal_h
 
 #include "nsJSPrincipals.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/OriginAttributes.h"
 
+class nsIAtom;
 class nsIContentSecurityPolicy;
 class nsIObjectOutputStream;
 class nsIObjectInputStream;
 class nsIURI;
 
 class ExpandedPrincipal;
 
 namespace mozilla {
+namespace extensions {
+  class WebExtensionPolicy;
+}
 
 /*
  * Base class from which all nsIPrincipal implementations inherit. Use this for
  * default implementations and other commonalities between principal
  * implementations.
  *
  * We should merge nsJSPrincipals into this class at some point.
  */
@@ -59,16 +63,17 @@ public:
   NS_IMETHOD GetOrigin(nsACString& aOrigin) final;
   NS_IMETHOD GetOriginNoSuffix(nsACString& aOrigin) final;
   NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval) final;
   NS_IMETHOD EqualsConsideringDomain(nsIPrincipal* other, bool* _retval) final;
   NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval) final;
   NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval) final;
   NS_IMETHOD SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* other, bool* _retval) final;
   NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) final;
+  NS_IMETHOD GetAddonPolicy(nsISupports** aResult) final;
   NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
   NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
   NS_IMETHOD EnsureCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
   NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
   NS_IMETHOD EnsurePreloadCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
   NS_IMETHOD GetCspJSON(nsAString& outCSPinJSON) override;
   NS_IMETHOD GetIsNullPrincipal(bool* aResult) override;
   NS_IMETHOD GetIsCodebasePrincipal(bool* aResult) override;
@@ -76,17 +81,17 @@ public:
   NS_IMETHOD GetIsSystemPrincipal(bool* aResult) override;
   NS_IMETHOD GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) final;
   NS_IMETHOD GetOriginSuffix(nsACString& aOriginSuffix) final;
   NS_IMETHOD GetAppId(uint32_t* aAppId) final;
   NS_IMETHOD GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement) final;
   NS_IMETHOD GetUserContextId(uint32_t* aUserContextId) final;
   NS_IMETHOD GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) final;
 
-  virtual bool AddonHasPermission(const nsAString& aPerm);
+  virtual bool AddonHasPermission(const nsIAtom* aPerm);
 
   virtual bool IsCodebasePrincipal() const { return false; };
 
   static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }
 
   static already_AddRefed<BasePrincipal>
   CreateCodebasePrincipal(const nsACString& aOrigin);
 
@@ -94,16 +99,17 @@ public:
   // not possible to generate a correct origin from the passed URI. If this
   // happens, a NullPrincipal is returned.
 
   static already_AddRefed<BasePrincipal>
   CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs);
 
   const OriginAttributes& OriginAttributesRef() final { return mOriginAttributes; }
   uint32_t AppId() const { return mOriginAttributes.mAppId; }
+  extensions::WebExtensionPolicy* AddonPolicy();
   uint32_t UserContextId() const { return mOriginAttributes.mUserContextId; }
   uint32_t PrivateBrowsingId() const { return mOriginAttributes.mPrivateBrowsingId; }
   bool IsInIsolatedMozBrowserElement() const { return mOriginAttributes.mInIsolatedMozBrowser; }
 
   PrincipalKind Kind() const { return mKind; }
 
   already_AddRefed<BasePrincipal> CloneStrippingUserContextIdAndFirstPartyDomain();
 
--- a/caps/ContentPrincipal.cpp
+++ b/caps/ContentPrincipal.cpp
@@ -25,16 +25,17 @@
 #include "nsError.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsNetCID.h"
 #include "jswrapper.h"
 
 #include "mozilla/dom/nsCSPContext.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/ClearOnShutdown.h"
+#include "mozilla/ExtensionPolicyService.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/HashFunctions.h"
 
 using namespace mozilla;
 
 static bool gCodeBasePrincipalSupport = false;
 
 static bool URIIsImmutable(nsIURI* aURI)
@@ -42,27 +43,20 @@ static bool URIIsImmutable(nsIURI* aURI)
   nsCOMPtr<nsIMutable> mutableObj(do_QueryInterface(aURI));
   bool isMutable;
   return
     mutableObj &&
     NS_SUCCEEDED(mutableObj->GetMutable(&isMutable)) &&
     !isMutable;
 }
 
-static nsIAddonPolicyService*
-GetAddonPolicyService(nsresult* aRv)
+static inline ExtensionPolicyService&
+EPS()
 {
-  static nsCOMPtr<nsIAddonPolicyService> addonPolicyService;
-
-  *aRv = NS_OK;
-  if (!addonPolicyService) {
-    addonPolicyService = do_GetService("@mozilla.org/addons/policy-service;1", aRv);
-    ClearOnShutdown(&addonPolicyService);
-  }
-  return addonPolicyService;
+  return ExtensionPolicyService::GetSingleton();
 }
 
 NS_IMPL_CLASSINFO(ContentPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_PRINCIPAL_CID)
 NS_IMPL_QUERY_INTERFACE_CI(ContentPrincipal,
                            nsIPrincipal,
                            nsISerializable)
 NS_IMPL_CI_INTERFACE_GETTER(ContentPrincipal,
@@ -420,44 +414,44 @@ ContentPrincipal::GetBaseDomain(nsACStri
     do_GetService(THIRDPARTYUTIL_CONTRACTID);
   if (thirdPartyUtil) {
     return thirdPartyUtil->GetBaseDomain(mCodebase, aBaseDomain);
   }
 
   return NS_OK;
 }
 
+WebExtensionPolicy*
+ContentPrincipal::AddonPolicy()
+{
+  if (!mAddon.isSome()) {
+    NS_ENSURE_TRUE(mCodebase, nullptr);
+
+    bool isMozExt;
+    if (NS_SUCCEEDED(mCodebase->SchemeIs("moz-extension", &isMozExt)) && isMozExt) {
+      mAddon.emplace(EPS().GetByURL(mCodebase.get()));
+    } else {
+      mAddon.emplace(nullptr);
+    }
+  }
+
+  return mAddon.value();
+}
+
 NS_IMETHODIMP
 ContentPrincipal::GetAddonId(nsAString& aAddonId)
 {
-  if (mAddonIdCache.isSome()) {
-    aAddonId.Assign(mAddonIdCache.ref());
-    return NS_OK;
+  auto policy = AddonPolicy();
+  if (policy) {
+    policy->GetId(aAddonId);
+  } else {
+    aAddonId.Truncate();
   }
-
-  NS_ENSURE_TRUE(mCodebase, NS_ERROR_FAILURE);
-
-  nsresult rv;
-  bool isMozExt;
-  if (NS_SUCCEEDED(mCodebase->SchemeIs("moz-extension", &isMozExt)) && isMozExt) {
-    nsIAddonPolicyService* addonPolicyService = GetAddonPolicyService(&rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsAutoString addonId;
-    rv = addonPolicyService->ExtensionURIToAddonId(mCodebase, addonId);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    mAddonIdCache.emplace(addonId);
-  } else {
-    mAddonIdCache.emplace();
-  }
-
-  aAddonId.Assign(mAddonIdCache.ref());
   return NS_OK;
-};
+}
 
 NS_IMETHODIMP
 ContentPrincipal::Read(nsIObjectInputStream* aStream)
 {
   nsCOMPtr<nsISupports> supports;
   nsCOMPtr<nsIURI> codebase;
   nsresult rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports));
   if (NS_FAILED(rv)) {
--- a/caps/ContentPrincipal.h
+++ b/caps/ContentPrincipal.h
@@ -9,16 +9,17 @@
 #include "nsCOMPtr.h"
 #include "nsJSPrincipals.h"
 #include "nsTArray.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIProtocolHandler.h"
 #include "nsNetUtil.h"
 #include "nsScriptSecurityManager.h"
 #include "mozilla/BasePrincipal.h"
+#include "mozilla/extensions/WebExtensionPolicy.h"
 
 class ContentPrincipal final : public mozilla::BasePrincipal
 {
 public:
   NS_DECL_NSISERIALIZABLE
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
   NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
   NS_IMETHOD GetURI(nsIURI** aURI) override;
@@ -42,31 +43,33 @@ public:
   /**
    * Called at startup to setup static data, e.g. about:config pref-observers.
    */
   static void InitializeStatics();
 
   static nsresult
   GenerateOriginNoSuffixFromURI(nsIURI* aURI, nsACString& aOrigin);
 
+  mozilla::extensions::WebExtensionPolicy* AddonPolicy();
+
   nsCOMPtr<nsIURI> mDomain;
   nsCOMPtr<nsIURI> mCodebase;
   // If mCodebaseImmutable is true, mCodebase is non-null and immutable
   bool mCodebaseImmutable;
   bool mDomainImmutable;
 
 protected:
   virtual ~ContentPrincipal();
 
   bool SubsumesInternal(nsIPrincipal* aOther,
                         DocumentDomainConsideration aConsideration) override;
   bool MayLoadInternal(nsIURI* aURI) override;
 
 private:
-  mozilla::Maybe<nsString> mAddonIdCache;
+  mozilla::Maybe<mozilla::WeakPtr<mozilla::extensions::WebExtensionPolicy>> mAddon;
 };
 
 #define NS_PRINCIPAL_CONTRACTID "@mozilla.org/principal;1"
 #define NS_PRINCIPAL_CID \
 { 0x653e0e4d, 0x3ee4, 0x45fa, \
   { 0xb2, 0x72, 0x97, 0xc2, 0x0b, 0xc0, 0x1e, 0xb8 } }
 
 #endif // ContentPrincipal_h
--- a/caps/ExpandedPrincipal.cpp
+++ b/caps/ExpandedPrincipal.cpp
@@ -167,17 +167,17 @@ ExpandedPrincipal::GetBaseDomain(nsACStr
 NS_IMETHODIMP
 ExpandedPrincipal::GetAddonId(nsAString& aAddonId)
 {
   aAddonId.Truncate();
   return NS_OK;
 };
 
 bool
-ExpandedPrincipal::AddonHasPermission(const nsAString& aPerm)
+ExpandedPrincipal::AddonHasPermission(const nsIAtom* aPerm)
 {
   for (size_t i = 0; i < mPrincipals.Length(); ++i) {
     if (BasePrincipal::Cast(mPrincipals[i])->AddonHasPermission(aPerm)) {
       return true;
     }
   }
   return false;
 }
--- a/caps/ExpandedPrincipal.h
+++ b/caps/ExpandedPrincipal.h
@@ -29,17 +29,17 @@ public:
   NS_IMETHOD_(MozExternalRefCountType) Release() override { return nsJSPrincipals::Release(); };
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
   NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
   NS_IMETHOD GetURI(nsIURI** aURI) override;
   NS_IMETHOD GetDomain(nsIURI** aDomain) override;
   NS_IMETHOD SetDomain(nsIURI* aDomain) override;
   NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
   NS_IMETHOD GetAddonId(nsAString& aAddonId) override;
-  virtual bool AddonHasPermission(const nsAString& aPerm) override;
+  virtual bool AddonHasPermission(const nsIAtom* aPerm) override;
   virtual nsresult GetScriptLocation(nsACString &aStr) override;
 
 protected:
   explicit ExpandedPrincipal(nsTArray<nsCOMPtr<nsIPrincipal>> &aWhiteList);
 
   virtual ~ExpandedPrincipal();
 
   bool SubsumesInternal(nsIPrincipal* aOther,
--- a/caps/nsIPrincipal.idl
+++ b/caps/nsIPrincipal.idl
@@ -269,16 +269,18 @@ interface nsIPrincipal : nsISerializable
      */
     [infallible] readonly attribute unsigned long appId;
 
     /**
      * Gets the ID of the add-on this principal belongs to.
      */
     readonly attribute AString addonId;
 
+    readonly attribute nsISupports addonPolicy;
+
     /**
      * Gets the id of the user context this principal is inside.  If this
      * principal is inside the default userContext, this returns
      * nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID.
      */
     [infallible] readonly attribute unsigned long userContextId;
 
     /**
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -764,23 +764,18 @@ nsScriptSecurityManager::CheckLoadURIWit
     }
 
     // Check for webextension
     rv = NS_URIChainHasFlags(aTargetURI,
                              nsIProtocolHandler::URI_LOADABLE_BY_EXTENSIONS,
                              &hasFlags);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    if (hasFlags) {
-      nsString addonId;
-      aPrincipal->GetAddonId(addonId);
-
-      if (!addonId.IsEmpty()) {
-        return NS_OK;
-      }
+    if (hasFlags && BasePrincipal::Cast(aPrincipal)->AddonPolicy()) {
+      return NS_OK;
     }
 
     // If we get here, check all the schemes can link to each other, from the top down:
     nsCaseInsensitiveCStringComparator stringComparator;
     nsCOMPtr<nsIURI> currentURI = sourceURI;
     nsCOMPtr<nsIURI> currentOtherURI = aTargetURI;
 
     bool denySameSchemeLinks = false;
--- a/caps/nsScriptSecurityManager.h
+++ b/caps/nsScriptSecurityManager.h
@@ -4,19 +4,17 @@
  * 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/. */
 
 #ifndef nsScriptSecurityManager_h__
 #define nsScriptSecurityManager_h__
 
 #include "nsIScriptSecurityManager.h"
 
-#include "nsIAddonPolicyService.h"
 #include "mozilla/Maybe.h"
-#include "nsIAddonPolicyService.h"
 #include "nsIPrincipal.h"
 #include "nsCOMPtr.h"
 #include "nsIObserver.h"
 #include "nsServiceManagerUtils.h"
 #include "nsStringFwd.h"
 #include "plstr.h"
 #include "js/TypeDecls.h"
 
@@ -131,27 +129,16 @@ private:
     // access to file: URIs.  Lazily initialized; isNothing() when not yet
     // initialized.
     mozilla::Maybe<nsTArray<nsCOMPtr<nsIURI>>> mFileURIWhitelist;
 
     // This machinery controls new-style domain policies. The old-style
     // policy machinery will be removed soon.
     nsCOMPtr<nsIDomainPolicy> mDomainPolicy;
 
-    // Cached addon policy service. We can't generate this in Init() because
-    // that's too early to get a service.
-    mozilla::Maybe<nsCOMPtr<nsIAddonPolicyService>> mAddonPolicyService;
-    nsIAddonPolicyService* GetAddonPolicyService()
-    {
-        if (mAddonPolicyService.isNothing()) {
-            mAddonPolicyService.emplace(do_GetService("@mozilla.org/addons/policy-service;1"));
-        }
-        return mAddonPolicyService.ref();
-    }
-
     static bool sStrictFileOriginPolicy;
 
     static nsIIOService    *sIOService;
     static nsIStringBundle *sStrBundle;
     static JSContext       *sContext;
 };
 
 #endif // nsScriptSecurityManager_h__
--- a/devtools/docs/frontend/telemetry.md
+++ b/devtools/docs/frontend/telemetry.md
@@ -33,17 +33,17 @@ The data team chose YAML for `Scalars.ya
 While we previously used JSON for similar purposes in histograms.json, we have used YAML here because it allows for comments and is generally easier to write.
 
 When the YAML format is proven the data team are considering moving the histograms over to YAML format at some point.
 
 If it's the first time you add one of these, it's advised to follow the style of existing entries.
 
 New data types have been added over the years, so it's quite feasible that some of our probes are not the most suitable nowadays.
 
-There's more information about types (and telemetry in general) on [this page](https://developer.mozilla.org/en-US/docs/Mozilla/Performance/Adding_a_new_Telemetry_probe) and [this other page](https://gecko.readthedocs.io/en/latest/toolkit/components/telemetry/telemetry/collection/index.html).
+There's more information about types (and telemetry in general) on [this page](https://developer.mozilla.org/en-US/docs/Mozilla/Performance/Adding_a_new_Telemetry_probe) and [this other page](https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/index.html).
 
 And of course, in case of doubt, ask!
 
 ### Adding probes to `Histograms.json`
 
 Our entries are prefixed with `DEVTOOLS_`. For example:
 
 ```javascript
--- a/devtools/server/actors/object.js
+++ b/devtools/server/actors/object.js
@@ -116,18 +116,17 @@ ObjectActor.prototype = {
       // FF40+: Allow to know how many properties an object has
       // to lazily display them when there is a bunch.
       // Throws on some MouseEvent object in tests.
       try {
         if (TYPED_ARRAY_CLASSES.indexOf(g.class) != -1) {
           // Bug 1348761: getOwnPropertyNames is unecessary slow on TypedArrays
           let length = DevToolsUtils.getProperty(this.obj, "length");
           g.ownPropertyLength = length;
-        } else if (!["Function", "Proxy"].includes(g.class)) {
-          // Bug 1163520: Assert on internal functions
+        } else if (g.class != "Proxy") {
           g.ownPropertyLength = this.obj.getOwnPropertyNames().length;
         }
       } catch (e) {
         // ignored
       }
 
       let raw = this.obj.unsafeDereference();
 
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -2326,30 +2326,30 @@ nsContentUtils::CanCallerAccess(nsPIDOMW
   nsCOMPtr<nsIScriptObjectPrincipal> scriptObject = do_QueryInterface(aWindow);
   NS_ENSURE_TRUE(scriptObject, false);
 
   return CanCallerAccess(SubjectPrincipal(), scriptObject->GetPrincipal());
 }
 
 // static
 bool
-nsContentUtils::PrincipalHasPermission(nsIPrincipal* aPrincipal, const nsAString& aPerm)
+nsContentUtils::PrincipalHasPermission(nsIPrincipal* aPrincipal, const nsIAtom* aPerm)
 {
   // Chrome gets access by default.
   if (IsSystemPrincipal(aPrincipal)) {
     return true;
   }
 
   // Otherwise, only allow if caller is an addon with the permission.
   return BasePrincipal::Cast(aPrincipal)->AddonHasPermission(aPerm);
 }
 
 // static
 bool
-nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAString& aPerm)
+nsContentUtils::CallerHasPermission(JSContext* aCx, const nsIAtom* aPerm)
 {
   return PrincipalHasPermission(SubjectPrincipal(aCx), aPerm);
 }
 
 //static
 bool
 nsContentUtils::InProlog(nsINode *aNode)
 {
@@ -7345,17 +7345,17 @@ nsContentUtils::IsRequestFullScreenAllow
 /* static */
 bool
 nsContentUtils::IsCutCopyAllowed(nsIPrincipal* aSubjectPrincipal)
 {
   if (!IsCutCopyRestricted() && EventStateManager::IsHandlingUserInput()) {
     return true;
   }
 
-  return PrincipalHasPermission(aSubjectPrincipal, NS_LITERAL_STRING("clipboardWrite"));
+  return PrincipalHasPermission(aSubjectPrincipal, nsGkAtoms::clipboardWrite);
 }
 
 /* static */
 bool
 nsContentUtils::IsFrameTimingEnabled()
 {
   return sIsFrameTimingPrefEnabled;
 }
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -52,16 +52,17 @@ class imgICache;
 class imgIContainer;
 class imgINotificationObserver;
 class imgIRequest;
 class imgLoader;
 class imgRequestProxy;
 class nsAutoScriptBlockerSuppressNodeRemoved;
 class nsCacheableFuncStringHTMLCollection;
 class nsHtml5StringParser;
+class nsIAtom;
 class nsIChannel;
 class nsIConsoleService;
 class nsIContent;
 class nsIContentPolicy;
 class nsIContentSecurityPolicy;
 class nsIDocShellTreeItem;
 class nsIDocumentLoaderFactory;
 class nsIDOMDocument;
@@ -585,20 +586,20 @@ public:
   static bool CanCallerAccess(nsIDOMNode *aNode);
   static bool CanCallerAccess(nsINode* aNode);
 
   // Check if the (JS) caller can access aWindow.
   // aWindow can be either outer or inner window.
   static bool CanCallerAccess(nsPIDOMWindowInner* aWindow);
 
   // Check if the principal is chrome or an addon with the permission.
-  static bool PrincipalHasPermission(nsIPrincipal* aPrincipal, const nsAString& aPerm);
+  static bool PrincipalHasPermission(nsIPrincipal* aPrincipal, const nsIAtom* aPerm);
 
   // Check if the JS caller is chrome or an addon with the permission.
-  static bool CallerHasPermission(JSContext* aCx, const nsAString& aPerm);
+  static bool CallerHasPermission(JSContext* aCx, const nsIAtom* aPerm);
 
   /**
    * GetDocumentFromCaller gets its document by looking at the last called
    * function and finding the document that the function itself relates to.
    * For example, consider two windows A and B in the same origin. B has a
    * function which does something that ends up needing the current document.
    * If a script in window A were to call B's function, GetDocumentFromCaller
    * would find that function (in B) and return B's document.
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -204,17 +204,16 @@
 #include "mozilla/dom/TouchEvent.h"
 
 #include "mozilla/Preferences.h"
 
 #include "imgILoader.h"
 #include "imgRequestProxy.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsSandboxFlags.h"
-#include "nsIAddonPolicyService.h"
 #include "mozilla/dom/AnimatableBinding.h"
 #include "mozilla/dom/AnonymousContent.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/DocumentTimeline.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/HTMLBodyElement.h"
 #include "mozilla/dom/HTMLInputElement.h"
@@ -222,16 +221,17 @@
 #include "mozilla/dom/MediaQueryList.h"
 #include "mozilla/dom/NodeFilterBinding.h"
 #include "mozilla/OwningNonNull.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/WebComponentsBinding.h"
 #include "mozilla/dom/CustomElementRegistryBinding.h"
 #include "mozilla/dom/CustomElementRegistry.h"
 #include "mozilla/dom/TimeoutManager.h"
+#include "mozilla/ExtensionPolicyService.h"
 #include "nsFrame.h"
 #include "nsDOMCaretPosition.h"
 #include "nsIDOMHTMLTextAreaElement.h"
 #include "nsViewportInfo.h"
 #include "mozilla/StaticPtr.h"
 #include "nsITextControlElement.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIEditor.h"
@@ -2935,30 +2935,28 @@ nsDocument::InitCSP(nsIChannel* aChannel
     Unused << httpChannel->GetResponseHeader(
         NS_LITERAL_CSTRING("content-security-policy-report-only"),
         tCspROHeaderValue);
   }
   NS_ConvertASCIItoUTF16 cspHeaderValue(tCspHeaderValue);
   NS_ConvertASCIItoUTF16 cspROHeaderValue(tCspROHeaderValue);
 
   // Check if this is a document from a WebExtension.
-  nsString addonId;
   nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
-  principal->GetAddonId(addonId);
-  bool applyAddonCSP = !addonId.IsEmpty();
+  auto addonPolicy = BasePrincipal::Cast(principal)->AddonPolicy();
 
   // Check if this is a signed content to apply default CSP.
   bool applySignedContentCSP = false;
   nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
   if (loadInfo && loadInfo->GetVerifySignedContent()) {
     applySignedContentCSP = true;
   }
 
   // If there's no CSP to apply, go ahead and return early
-  if (!applyAddonCSP &&
+  if (!addonPolicy &&
       !applySignedContentCSP &&
       cspHeaderValue.IsEmpty() &&
       cspROHeaderValue.IsEmpty()) {
     if (MOZ_LOG_TEST(gCspPRLog, LogLevel::Debug)) {
       nsCOMPtr<nsIURI> chanURI;
       aChannel->GetURI(getter_AddRefs(chanURI));
       nsAutoCString aspec;
       chanURI->GetAsciiSpec(aspec);
@@ -2972,29 +2970,24 @@ nsDocument::InitCSP(nsIChannel* aChannel
 
   MOZ_LOG(gCspPRLog, LogLevel::Debug, ("Document is an add-on or CSP header specified %p", this));
 
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   rv = principal->EnsureCSP(this, getter_AddRefs(csp));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // ----- if the doc is an addon, apply its CSP.
-  if (applyAddonCSP) {
+  if (addonPolicy) {
     nsCOMPtr<nsIAddonPolicyService> aps = do_GetService("@mozilla.org/addons/policy-service;1");
 
     nsAutoString addonCSP;
-    rv = aps->GetBaseCSP(addonCSP);
-    if (NS_SUCCEEDED(rv)) {
-      csp->AppendPolicy(addonCSP, false, false);
-    }
-
-    rv = aps->GetAddonCSP(addonId, addonCSP);
-    if (NS_SUCCEEDED(rv)) {
-      csp->AppendPolicy(addonCSP, false, false);
-    }
+    Unused << ExtensionPolicyService::GetSingleton().GetBaseCSP(addonCSP);
+    csp->AppendPolicy(addonCSP, false, false);
+
+    csp->AppendPolicy(addonPolicy->ContentSecurityPolicy(), false, false);
   }
 
   // ----- if the doc is a signed content, apply the default CSP.
   // Note that when the content signing becomes a standard, we might have
   // to restrict this enforcement to "remote content" only.
   if (applySignedContentCSP) {
     nsAutoString signedContentCSP;
     Preferences::GetString("security.signed_content.CSP.default",
@@ -13178,19 +13171,25 @@ nsDocument::UpdateIntersectionObservatio
 
   DOMHighResTimeStamp time = 0;
   if (nsPIDOMWindowInner* window = GetInnerWindow()) {
     Performance* perf = window->GetPerformance();
     if (perf) {
       time = perf->Now();
     }
   }
+  nsTArray<RefPtr<DOMIntersectionObserver>> observers(mIntersectionObservers.Count());
   for (auto iter = mIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
     DOMIntersectionObserver* observer = iter.Get()->GetKey();
-    observer->Update(this, time);
+      observers.AppendElement(observer);
+  }
+  for (const auto& observer : observers) {
+    if (observer) {
+      observer->Update(this, time);
+    }
   }
 }
 
 void
 nsDocument::ScheduleIntersectionObserverNotification()
 {
   if (mIntersectionObservers.IsEmpty()) {
     return;
@@ -13207,17 +13206,19 @@ void
 nsDocument::NotifyIntersectionObservers()
 {
   nsTArray<RefPtr<DOMIntersectionObserver>> observers(mIntersectionObservers.Count());
   for (auto iter = mIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
     DOMIntersectionObserver* observer = iter.Get()->GetKey();
     observers.AppendElement(observer);
   }
   for (const auto& observer : observers) {
-    observer->Notify();
+    if (observer) {
+      observer->Notify();
+    }
   }
 }
 
 static bool
 NotifyLayerManagerRecreatedCallback(nsIDocument* aDocument, void* aData)
 {
   aDocument->NotifyLayerManagerRecreated();
   return true;
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -2064,16 +2064,21 @@ GK_ATOM(ondevicelight, "ondevicelight")
 GK_ATOM(ondevicechange, "ondevicechange")
 
 // HTML element attributes that only exposed to XBL and chrome content
 GK_ATOM(mozinputrangeignorepreventdefault, "mozinputrangeignorepreventdefault")
 
 // WebExtensions
 GK_ATOM(moz_extension, "moz-extension")
 GK_ATOM(all_urlsPermission, "<all_urls>")
+GK_ATOM(clipboardRead, "clipboardRead")
+GK_ATOM(clipboardWrite, "clipboardWrite")
+GK_ATOM(debugger, "debugger")
+GK_ATOM(tabs, "tabs")
+GK_ATOM(webRequestBlocking, "webRequestBlocking")
 GK_ATOM(http, "http")
 GK_ATOM(https, "https")
 
 //---------------------------------------------------------------------------
 // Special atoms
 //---------------------------------------------------------------------------
 
 // Node types
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -3339,19 +3339,18 @@ nsGlobalWindow::SetNewDocument(nsIDocume
     // doesn't have one).
     newInnerWindow->mChromeEventHandler = mChromeEventHandler;
   }
 
   // Ask the JS engine to assert that it's valid to access our DocGroup whenever
   // it runs JS code for this compartment. We skip the check if this window is
   // for chrome JS or an add-on.
   nsCOMPtr<nsIPrincipal> principal = mDoc->NodePrincipal();
-  nsString addonId;
-  principal->GetAddonId(addonId);
-  if (GetDocGroup() && !nsContentUtils::IsSystemPrincipal(principal) && addonId.IsEmpty()) {
+  if (GetDocGroup() && !nsContentUtils::IsSystemPrincipal(principal) &&
+      !BasePrincipal::Cast(principal)->AddonPolicy()) {
     js::SetCompartmentValidAccessPtr(cx, newInnerGlobal,
                                      newInnerWindow->GetDocGroup()->GetValidAccessPtr());
   }
 
   kungFuDeathGrip->DidInitializeContext();
 
   // We wait to fire the debugger hook until the window is all set up and hooked
   // up with the outer. See bug 969156.
@@ -9822,18 +9821,17 @@ public:
           NS_ENSURE_TRUE(currentInner, NS_OK);
 
           AutoSafeJSContext cx;
           JS::Rooted<JSObject*> obj(cx, currentInner->FastGetGlobalJSObject());
           if (obj && !js::IsSystemCompartment(js::GetObjectCompartment(obj))) {
             JSCompartment* cpt = js::GetObjectCompartment(obj);
             nsCOMPtr<nsIPrincipal> pc = nsJSPrincipals::get(JS_GetCompartmentPrincipals(cpt));
 
-            nsAutoString addonId;
-            if (NS_SUCCEEDED(pc->GetAddonId(addonId)) && !addonId.IsEmpty()) {
+            if (BasePrincipal::Cast(pc)->AddonPolicy()) {
               // 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(), cpt,
                                                win->IsInnerWindow() ? js::DontNukeWindowReferences
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -5682,17 +5682,17 @@ CanvasRenderingContext2D::GetImageData(J
 
   // Check only if we have a canvas element; if we were created with a docshell,
   // then it's special internal use.
   if (mCanvasElement && mCanvasElement->IsWriteOnly() &&
       // We could ask bindings for the caller type, but they already hand us a
       // JSContext, and we're at least _somewhat_ perf-sensitive (so may not
       // want to compute the caller type in the common non-write-only case), so
       // let's just use what we have.
-      !nsContentUtils::CallerHasPermission(aCx, NS_LITERAL_STRING("<all_urls>")))
+      !nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::all_urlsPermission))
   {
     // XXX ERRMSG we need to report an error to developers here! (bug 329026)
     aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return nullptr;
   }
 
   if (!IsFinite(aSx) || !IsFinite(aSy) ||
       !IsFinite(aSw) || !IsFinite(aSh)) {
--- a/dom/canvas/CanvasUtils.cpp
+++ b/dom/canvas/CanvasUtils.cpp
@@ -113,13 +113,13 @@ CoerceDouble(const JS::Value& v, double*
         return false;
     }
     return true;
 }
 
 bool
 HasDrawWindowPrivilege(JSContext* aCx, JSObject* /* unused */)
 {
-  return nsContentUtils::CallerHasPermission(aCx, NS_LITERAL_STRING("<all_urls>"));
+  return nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::all_urlsPermission);
 }
 
 } // namespace CanvasUtils
 } // namespace mozilla
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -647,17 +647,17 @@ HTMLCanvasElement::ParseAttribute(int32_
 void
 HTMLCanvasElement::ToDataURL(JSContext* aCx, const nsAString& aType,
                              JS::Handle<JS::Value> aParams,
                              nsAString& aDataURL,
                              ErrorResult& aRv)
 {
   // do a trust check if this is a write-only canvas
   if (mWriteOnly &&
-      !nsContentUtils::CallerHasPermission(aCx, NS_LITERAL_STRING("<all_urls>"))) {
+      !nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::all_urlsPermission)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   aRv = ToDataURLImpl(aCx, aType, aParams, aDataURL);
 }
 
 void
@@ -830,17 +830,17 @@ void
 HTMLCanvasElement::ToBlob(JSContext* aCx,
                           BlobCallback& aCallback,
                           const nsAString& aType,
                           JS::Handle<JS::Value> aParams,
                           ErrorResult& aRv)
 {
   // do a trust check if this is a write-only canvas
   if (mWriteOnly &&
-      !nsContentUtils::CallerHasPermission(aCx, NS_LITERAL_STRING("<all_urls>"))) {
+      !nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::all_urlsPermission)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   nsCOMPtr<nsIGlobalObject> global = OwnerDoc()->GetScopeObject();
   MOZ_ASSERT(global);
 
   nsIntSize elemSize = GetWidthHeight();
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -7565,19 +7565,18 @@ HTMLMediaElement::MarkAsTainted()
   if (mDecoder) {
     mDecoder->SetSuspendTaint(true);
   }
 }
 
 bool
 HasDebuggerOrTabsPrivilege(JSContext* aCx, JSObject* aObj)
 {
-  return nsContentUtils::CallerHasPermission(aCx,
-                                             NS_LITERAL_STRING("debugger")) ||
-         nsContentUtils::CallerHasPermission(aCx, NS_LITERAL_STRING("tabs"));
+  return nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::debugger) ||
+         nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::tabs);
  }
 
 void
 HTMLMediaElement::AsyncResolveSeekDOMPromiseIfExists()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mSeekDOMPromise) {
     RefPtr<dom::Promise> promise = mSeekDOMPromise.forget();
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -3285,17 +3285,17 @@ nsHTMLDocument::ExecCommand(const nsAStr
 
   if (commandID.LowerCaseEqualsLiteral("gethtml")) {
     rv.Throw(NS_ERROR_FAILURE);
     return false;
   }
 
   bool restricted = commandID.LowerCaseEqualsLiteral("paste");
   if (restricted && !nsContentUtils::PrincipalHasPermission(&aSubjectPrincipal,
-                                                            NS_LITERAL_STRING("clipboardRead"))) {
+                                                            nsGkAtoms::clipboardRead)) {
     return false;
   }
 
   // get command manager and dispatch command to our window if it's acceptable
   nsCOMPtr<nsICommandManager> cmdMgr;
   GetMidasCommandManager(getter_AddRefs(cmdMgr));
   if (!cmdMgr) {
     rv.Throw(NS_ERROR_FAILURE);
--- a/dom/svg/SVGAElement.cpp
+++ b/dom/svg/SVGAElement.cpp
@@ -33,33 +33,22 @@ nsSVGElement::StringInfo SVGAElement::sS
   { &nsGkAtoms::href, kNameSpaceID_XLink, true },
   { &nsGkAtoms::target, kNameSpaceID_None, true }
 };
 
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
-NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(SVGAElement)
-  NS_INTERFACE_TABLE_INHERITED(SVGAElement,
-                               nsIDOMNode,
-                               nsIDOMElement,
-                               nsIDOMSVGElement,
-                               Link)
-NS_INTERFACE_TABLE_TAIL_INHERITING(SVGAElementBase)
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(SVGAElement)
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGAElement,
-                                                  SVGAElementBase)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGAElement,
-                                                SVGAElementBase)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_INTERFACE_MAP_BEGIN(SVGAElement)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMElement)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement)
+  NS_INTERFACE_MAP_ENTRY(Link)
+NS_INTERFACE_MAP_END_INHERITING(SVGAElementBase)
 
 NS_IMPL_ADDREF_INHERITED(SVGAElement, SVGAElementBase)
 NS_IMPL_RELEASE_INHERITED(SVGAElement, SVGAElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 SVGAElement::SVGAElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
--- a/dom/svg/SVGAElement.h
+++ b/dom/svg/SVGAElement.h
@@ -29,17 +29,16 @@ class SVGAElement final : public SVGAEle
 protected:
   explicit SVGAElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   friend nsresult (::NS_NewSVGAElement(nsIContent **aResult,
                                        already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
   virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGAElement, SVGAElementBase)
 
   // nsINode interface methods
   virtual nsresult GetEventTargetParent(
                      EventChainPreVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(
                      EventChainPostVisitor& aVisitor) override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
--- a/dom/tests/mochitest/beacon/mochitest.ini
+++ b/dom/tests/mochitest/beacon/mochitest.ini
@@ -3,12 +3,13 @@ support-files = beacon-frame.html
                 beacon-handler.sjs
                 beacon-preflight-handler.sjs
                 beacon-originheader-handler.sjs
                 beacon-redirect-handler.sjs
 
 [test_beacon.html]
 [test_beaconFrame.html]
 [test_beaconPreflightWithCustomContentType.html]
+skip-if = toolkit == 'android'  # Bug 1373945
 [test_beaconContentPolicy.html]
 [test_beaconOriginHeader.html]
 [test_beaconRedirect.html]
 skip-if = toolkit == 'android' && debug    # Bug 1296845 - Android Debug on emulator is too slow
--- a/dom/xul/templates/nsIXULTemplateBuilder.idl
+++ b/dom/xul/templates/nsIXULTemplateBuilder.idl
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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/. */
 
 #include "domstubs.idl"
 
-interface nsIAtom;
+interface nsIAtom;  // used in [noscript] methods only
 interface nsIContent;
 interface nsIXULBuilderListener;
 interface nsIXULTemplateResult;
 interface nsIXULTemplateRuleFilter;
 interface nsIXULTemplateQueryProcessor;
 interface nsIRDFResource;
 interface nsIRDFCompositeDataSource;
 interface nsIDOMDataTransfer;
@@ -262,17 +262,18 @@ interface nsIXULTemplateBuilder : nsISup
      * Returns true if the node has content generated for it. This method is
      * intended to be called only by the RDF query processor. If aTag is set,
      * the content must have a tag name that matches aTag. aTag may be ignored
      * for builders that don't generate real DOM content.
      *
      * @param aNode node to check
      * @param aTag tag that must match
      */
-    boolean hasGeneratedContent(in nsIRDFResource aNode, in nsIAtom aTag);
+    [noscript] boolean hasGeneratedContent(in nsIRDFResource aNode,
+                                           in nsIAtom aTag);
 
     /**
      * Adds a rule filter for a given rule, which may be used for specialized
      * rule filtering. Any existing filter on the rule is removed. The default
      * conditions specified inside the <rule> tag are applied before the
      * rule filter is applied, meaning that the filter may be used to further
      * filter out results but not reaccept results that have already been
      * rejected.
--- a/dom/xul/templates/nsIXULTemplateQueryProcessor.idl
+++ b/dom/xul/templates/nsIXULTemplateQueryProcessor.idl
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #include "domstubs.idl"
 
-interface nsIAtom;
+interface nsIAtom;  // used in [noscript] methods only
 interface nsIArray;
 interface nsISimpleEnumerator;
 interface nsIXULTemplateResult;
 interface nsIXULTemplateRuleFilter;
 interface nsIXULTemplateBuilder;
 
 /**
  * A query processor takes a template query and generates results for it given
@@ -157,20 +157,20 @@ interface nsIXULTemplateQueryProcessor :
    *
    * @param aBuilder the template builder
    * @param aQuery <query> node to compile
    * @param aRefVariable the reference variable
    * @param aMemberVariable the member variable
    *
    * @returns a compiled query object
    */
-  nsISupports compileQuery(in nsIXULTemplateBuilder aBuilder,
-                           in nsIDOMNode aQuery,
-                           in nsIAtom aRefVariable,
-                           in nsIAtom aMemberVariable);
+  [noscript] nsISupports compileQuery(in nsIXULTemplateBuilder aBuilder,
+                                      in nsIDOMNode aQuery,
+                                      in nsIAtom aRefVariable,
+                                      in nsIAtom aMemberVariable);
 
   /**
    * Generate the results of a query and return them in an enumerator. The
    * enumerator must contain nsIXULTemplateResult objects. If there are no
    * results, an empty enumerator must be returned.
    *
    * The datasource will be the same as the one passed to the earlier
    * initializeForBuilding method. The context reference (aRef) is a reference
@@ -217,20 +217,20 @@ interface nsIXULTemplateQueryProcessor :
    * of the variable aVar would be 7, assuming the query processor considers
    * the syntax '+2' to mean add two to the reference.
    *
    * @param aRuleNode rule to add the binding to
    * @param aVar variable that will be bound
    * @param aRef variable that holds reference value
    * @param aExpr expression used to compute the value to assign
    */
-  void addBinding(in nsIDOMNode aRuleNode,
-                  in nsIAtom aVar,
-                  in nsIAtom aRef,
-                  in AString aExpr);
+  [noscript] void addBinding(in nsIDOMNode aRuleNode,
+                             in nsIAtom aVar,
+                             in nsIAtom aRef,
+                             in AString aExpr);
 
   /**
    * Translate a ref attribute string into a result. This is used as the
    * reference point by the template builder when generating the first level
    * of content. For recursive generation, the result from the parent
    * generation phase will be used directly as the reference so a translation
    * is not needed. This allows all levels to be generated using objects that
    * all implement the nsIXULTemplateResult interface.
@@ -264,13 +264,13 @@ interface nsIXULTemplateQueryProcessor :
    * query processor.
    *
    * @param aLeft the left result to compare
    * @param aRight the right result to compare
    * @param aVar variable to compare
    *
    * @param returns -1 if less, 0 if equal, or 1 if greater
    */
-   int32_t compareResults(in nsIXULTemplateResult aLeft,
-                          in nsIXULTemplateResult aRight,
-                          in nsIAtom aVar,
-                          in unsigned long aSortHints);
+   [noscript] int32_t compareResults(in nsIXULTemplateResult aLeft,
+                                     in nsIXULTemplateResult aRight,
+                                     in nsIAtom aVar,
+                                     in unsigned long aSortHints);
 };
--- a/dom/xul/templates/nsIXULTemplateResult.idl
+++ b/dom/xul/templates/nsIXULTemplateResult.idl
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 #include "nsISupports.idl"
 
-interface nsIAtom;
+interface nsIAtom;  // used in [noscript] methods only
 interface nsIDOMNode;
 interface nsIRDFResource;
 
 /**
  * A single result generated from a template query. Each result is identified
  * by an id, which must be unique within the set of results produced from a
  * query. The result may optionally be identified by an RDF resource.
  *
@@ -75,30 +75,30 @@ interface nsIXULTemplateResult : nsISupp
    * attribute within the action body, it will be replaced with the result
    * of this method. The question mark is considered part of the variable
    * name, thus aVar should be ?name and not simply name.
    *
    * @param aVar the variable to look up
    *
    * @return the value for the variable or a null string if it has no value
    */
-  AString getBindingFor(in nsIAtom aVar);
+  [noscript] AString getBindingFor(in nsIAtom aVar);
 
   /**
    * Get an object value for a variable such as ?name for this result. 
    *
    * This method may return null for a variable, even if getBindingFor returns
    * a non-null value for the same variable. This method is provided as a
    * convenience when sorting results.
    *
    * @param aVar the variable to look up
    *
    * @return the value for the variable or null if it has no value
    */
-  nsISupports getBindingObjectFor(in nsIAtom aVar);
+  [noscript] nsISupports getBindingObjectFor(in nsIAtom aVar);
 
   /**
    * Indicate that a particular rule of a query has matched and that output
    * will be generated for it. Both the query as compiled by the query
    * processor's compileQuery method and the XUL <rule> element are supplied.
    * The query must always be one that was compiled by the query processor
    * that created this result. The <rule> element must always be a child of
    * the <query> element that was used to compile the query.
--- a/gfx/2d/NativeFontResourceDWrite.cpp
+++ b/gfx/2d/NativeFontResourceDWrite.cpp
@@ -6,21 +6,23 @@
 
 #include "NativeFontResourceDWrite.h"
 #include "UnscaledFontDWrite.h"
 
 #include <unordered_map>
 
 #include "Logging.h"
 #include "mozilla/RefPtr.h"
+#include "mozilla/StaticMutex.h"
 
 namespace mozilla {
 namespace gfx {
 
-static Atomic<uint64_t> sNextFontFileKey;
+static StaticMutex sFontFileStreamsMutex;
+static uint64_t sNextFontFileKey = 0;
 static std::unordered_map<uint64_t, IDWriteFontFileStream*> sFontFileStreams;
 
 class DWriteFontFileLoader : public IDWriteFontFileLoader
 {
 public:
   DWriteFontFileLoader()
   {
   }
@@ -104,59 +106,58 @@ public:
       return S_OK;
     } else {
       return E_NOINTERFACE;
     }
   }
 
   IFACEMETHOD_(ULONG, AddRef)()
   {
-    ++mRefCnt;
-    return mRefCnt;
+    return ++mRefCnt;
   }
 
   IFACEMETHOD_(ULONG, Release)()
   {
-    --mRefCnt;
-    if (mRefCnt == 0) {
+    uint32_t count = --mRefCnt;
+    if (count == 0) {
       delete this;
-      return 0;
     }
-    return mRefCnt;
+    return count;
   }
 
   // IDWriteFontFileStream methods
   virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(void const** fragmentStart,
                                                      UINT64 fileOffset,
                                                      UINT64 fragmentSize,
                                                      OUT void** fragmentContext);
 
   virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext);
 
   virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize);
 
   virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime);
 
 private:
   std::vector<uint8_t> mData;
-  uint32_t mRefCnt;
+  Atomic<uint32_t> mRefCnt;
   uint64_t mFontFileKey;
 };
 
 IDWriteFontFileLoader* DWriteFontFileLoader::mInstance = nullptr;
 
 HRESULT STDMETHODCALLTYPE
 DWriteFontFileLoader::CreateStreamFromKey(const void *fontFileReferenceKey,
                                           UINT32 fontFileReferenceKeySize,
                                           IDWriteFontFileStream **fontFileStream)
 {
   if (!fontFileReferenceKey || !fontFileStream) {
     return E_POINTER;
   }
 
+  StaticMutexAutoLock lock(sFontFileStreamsMutex);
   uint64_t fontFileKey = *static_cast<const uint64_t*>(fontFileReferenceKey);
   auto found = sFontFileStreams.find(fontFileKey);
   if (found == sFontFileStreams.end()) {
     *fontFileStream = nullptr;
     return E_FAIL;
   }
 
   found->second->AddRef();
@@ -170,16 +171,17 @@ DWriteFontFileStream::DWriteFontFileStre
   , mFontFileKey(aFontFileKey)
 {
   mData.resize(aSize);
   memcpy(&mData.front(), aData, aSize);
 }
 
 DWriteFontFileStream::~DWriteFontFileStream()
 {
+  StaticMutexAutoLock lock(sFontFileStreamsMutex);
   sFontFileStreams.erase(mFontFileKey);
 }
 
 HRESULT STDMETHODCALLTYPE
 DWriteFontFileStream::GetFileSize(UINT64 *fileSize)
 {
   *fileSize = mData.size();
   return S_OK;
@@ -222,20 +224,22 @@ NativeFontResourceDWrite::Create(uint8_t
                                  bool aNeedsCairo)
 {
   RefPtr<IDWriteFactory> factory = Factory::GetDWriteFactory();
   if (!factory) {
     gfxWarning() << "Failed to get DWrite Factory.";
     return nullptr;
   }
 
+  sFontFileStreamsMutex.Lock();
   uint64_t fontFileKey = sNextFontFileKey++;
   RefPtr<IDWriteFontFileStream> ffsRef =
     new DWriteFontFileStream(aFontData, aDataLength, fontFileKey);
   sFontFileStreams[fontFileKey] = ffsRef;
+  sFontFileStreamsMutex.Unlock();
 
   RefPtr<IDWriteFontFile> fontFile;
   HRESULT hr =
     factory->CreateCustomFontFileReference(&fontFileKey, sizeof(fontFileKey),
                                            DWriteFontFileLoader::Instance(),
                                            getter_AddRefs(fontFile));
   if (FAILED(hr)) {
     gfxWarning() << "Failed to load font file from data!";
--- a/gfx/gl/GLBlitHelper.cpp
+++ b/gfx/gl/GLBlitHelper.cpp
@@ -180,37 +180,16 @@ public:
     ~ScopedBindArrayBuffer()
     {
         mGL.fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mOldVBO);
     }
 };
 
 // --
 
-class ScopedBindVAO final
-{
-    GLContext& mGL;
-    const GLuint mOldVAO;
-
-public:
-    ScopedBindVAO(GLContext* const gl, const GLuint vao)
-        : mGL(*gl)
-        , mOldVAO(mGL.GetIntAs<GLuint>(LOCAL_GL_VERTEX_ARRAY_BINDING))
-    {
-        mGL.fBindVertexArray(vao);
-    }
-
-    ~ScopedBindVAO()
-    {
-        mGL.fBindVertexArray(mOldVAO);
-    }
-};
-
-// --
-
 class ScopedShader final
 {
     GLContext& mGL;
     const GLuint mName;
 
 public:
     ScopedShader(GLContext* const gl, const GLenum shaderType)
         : mGL(*gl)
@@ -362,56 +341,96 @@ DrawBlitProg::Draw(const BaseArgs& args,
         gl->fUniform2f(mLoc_uDivisors, argsYUV->divisors.width, argsYUV->divisors.height);
         const auto& colorMatrix = gfxUtils::YuvToRgbMatrix4x4ColumnMajor(argsYUV->colorSpace);
         gl->fUniformMatrix4fv(mLoc_uColorMatrix, 1, false, colorMatrix);
     }
 
     // --
 
     const ScopedDrawBlitState drawState(gl, args.destSize);
-    const ScopedBindVAO bindVAO(gl, mParent.mQuadVAO);
+
+    GLuint oldVAO;
+    GLint vaa0Enabled;
+    GLint vaa0Size;
+    GLenum vaa0Type;
+    GLint vaa0Normalized;
+    GLsizei vaa0Stride;
+    GLvoid* vaa0Pointer;
+    if (mParent.mQuadVAO) {
+        oldVAO = gl->GetIntAs<GLuint>(LOCAL_GL_VERTEX_ARRAY_BINDING);
+        gl->fBindVertexArray(mParent.mQuadVAO);
+    } else {
+        gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED, &vaa0Enabled);
+        gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE, &vaa0Size);
+        gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE, (GLint*)&vaa0Type);
+        gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &vaa0Normalized);
+        gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE, (GLint*)&vaa0Stride);
+        gl->fGetVertexAttribPointerv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER, &vaa0Pointer);
+
+        gl->fEnableVertexAttribArray(0);
+        const ScopedBindArrayBuffer bindVBO(gl, mParent.mQuadVBO);
+        gl->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, false, 0, 0);
+    }
+
     gl->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
+
+    if (mParent.mQuadVAO) {
+        gl->fBindVertexArray(oldVAO);
+    } else {
+        if (vaa0Enabled) {
+            gl->fEnableVertexAttribArray(0);
+        } else {
+            gl->fDisableVertexAttribArray(0);
+        }
+        gl->fVertexAttribPointer(0, vaa0Size, vaa0Type, bool(vaa0Normalized), vaa0Stride,
+                                 vaa0Pointer);
+    }
 }
 
 // --
 
 GLBlitHelper::GLBlitHelper(GLContext* const gl)
     : mGL(gl)
     , mQuadVAO(0)
+    , mQuadVBO(0)
     , mDrawBlitProg_VertShader(mGL->fCreateShader(LOCAL_GL_VERTEX_SHADER))
     , mYuvUploads{0}
     , mYuvUploads_YSize(0, 0)
     , mYuvUploads_UVSize(0, 0)
 {
     if (!mGL->IsSupported(GLFeature::vertex_array_object)) {
         gfxCriticalError() << "GLBlitHelper requires vertex_array_object.";
         return;
     }
 
-    GLuint vbo = 0;
-    mGL->fGenBuffers(1, &vbo);
+    mGL->fGenBuffers(1, &mQuadVBO);
     {
-        const ScopedBindArrayBuffer bindVBO(mGL, vbo);
+        const ScopedBindArrayBuffer bindVBO(mGL, mQuadVBO);
 
         const float quadData[] = {
             0, 0,
             1, 0,
             0, 1,
             1, 1
         };
         const HeapCopyOfStackArray<float> heapQuadData(quadData);
         mGL->fBufferData(LOCAL_GL_ARRAY_BUFFER, heapQuadData.ByteLength(),
                          heapQuadData.Data(), LOCAL_GL_STATIC_DRAW);
 
-        mGL->fGenVertexArrays(1, &mQuadVAO);
-        const ScopedBindVAO bindVAO(mGL, mQuadVAO);
-        mGL->fEnableVertexAttribArray(0);
-        mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, false, 0, 0);
+        if (mGL->IsSupported(GLFeature::vertex_array_object)) {
+            const auto prev = mGL->GetIntAs<GLuint>(LOCAL_GL_VERTEX_ARRAY_BINDING);
+
+            mGL->fGenVertexArrays(1, &mQuadVAO);
+            mGL->fBindVertexArray(mQuadVAO);
+            mGL->fEnableVertexAttribArray(0);
+            mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, false, 0, 0);
+
+            mGL->fBindVertexArray(prev);
+        }
     }
-    mGL->fDeleteBuffers(1, &vbo);
 
     // --
 
     if (!mGL->IsGLES()) {
         const auto glslVersion = mGL->ShadingLanguageVersion();
         if (glslVersion >= 130) {
             mDrawBlitProg_VersionLine = nsPrintfCString("#version %u\n", glslVersion);
         }
@@ -466,17 +485,21 @@ GLBlitHelper::~GLBlitHelper()
         delete ptr;
     }
     mDrawBlitProgs.clear();
 
     if (!mGL->MakeCurrent())
         return;
 
     mGL->fDeleteShader(mDrawBlitProg_VertShader);
-    mGL->fDeleteVertexArrays(1, &mQuadVAO);
+    mGL->fDeleteBuffers(1, &mQuadVBO);
+
+    if (mQuadVAO) {
+        mGL->fDeleteVertexArrays(1, &mQuadVAO);
+    }
 }
 
 // --
 
 const DrawBlitProg*
 GLBlitHelper::GetDrawBlitProg(const DrawBlitProg::Key& key) const
 {
     const auto& res = mDrawBlitProgs.insert({key, nullptr});
--- a/gfx/gl/GLBlitHelper.h
+++ b/gfx/gl/GLBlitHelper.h
@@ -103,16 +103,17 @@ class GLBlitHelper final
     friend class BindAnglePlanes;
     friend class DrawBlitProg;
     friend class GLContext;
 
     GLContext* const mGL;
     mutable std::map<DrawBlitProg::Key, const DrawBlitProg*> mDrawBlitProgs;
 
     GLuint mQuadVAO;
+    GLuint mQuadVBO;
     nsCString mDrawBlitProg_VersionLine;
     const GLuint mDrawBlitProg_VertShader;
 
     GLuint mYuvUploads[3];
     gfx::IntSize mYuvUploads_YSize;
     gfx::IntSize mYuvUploads_UVSize;
 
 #ifdef XP_WIN
--- a/gfx/gl/GLBlitHelperD3D.cpp
+++ b/gfx/gl/GLBlitHelperD3D.cpp
@@ -19,16 +19,22 @@
 namespace mozilla {
 namespace gl {
 
 static EGLStreamKHR
 StreamFromD3DTexture(ID3D11Texture2D* const texD3D,
                      const EGLAttrib* const postAttribs)
 {
     auto& egl = sEGLLibrary;
+    if (!egl.IsExtensionSupported(GLLibraryEGL::NV_stream_consumer_gltexture_yuv) ||
+        !egl.IsExtensionSupported(GLLibraryEGL::ANGLE_stream_producer_d3d_texture_nv12))
+    {
+        return 0;
+    }
+
     const auto& display = egl.Display();
     const auto stream = egl.fCreateStreamKHR(display, nullptr);
     MOZ_ASSERT(stream);
     if (!stream)
         return 0;
     bool ok = true;
     MOZ_ALWAYS_TRUE( ok &= bool(egl.fStreamConsumerGLTextureExternalAttribsNV(display,
                                                                               stream,
--- a/gfx/layers/composite/FPSCounter.cpp
+++ b/gfx/layers/composite/FPSCounter.cpp
@@ -205,33 +205,38 @@ FPSCounter::BuildHistogram(std::map<int,
 
 // Iterate the same way we do in GetFPS()
 void
 FPSCounter::WriteFrameTimeStamps(PRFileDesc* fd)
 {
   const int bufferSize = 256;
   char buffer[bufferSize];
   int writtenCount = SprintfLiteral(buffer, "FPS Data for: %s\n", mFPSName);
-  MOZ_ASSERT(writtenCount >= 0);
+  MOZ_ASSERT(writtenCount < bufferSize);
+  if (writtenCount >= bufferSize) {
+    return;
+  }
   PR_Write(fd, buffer, writtenCount);
 
   ResetReverseIterator();
   TimeStamp startTimeStamp = GetLatestTimeStamp();
 
   MOZ_ASSERT(HasNext(startTimeStamp));
   TimeStamp previousSample = GetNextTimeStamp();
 
   MOZ_ASSERT(HasNext(startTimeStamp));
   TimeStamp nextTimeStamp = GetNextTimeStamp();
 
   while (HasNext(startTimeStamp)) {
     TimeDuration duration = previousSample - nextTimeStamp;
     writtenCount = SprintfLiteral(buffer, "%f,\n", duration.ToMilliseconds());
-
-    MOZ_ASSERT(writtenCount >= 0);
+    MOZ_ASSERT(writtenCount < bufferSize);
+    if (writtenCount >= bufferSize) {
+      continue;
+    }
     PR_Write(fd, buffer, writtenCount);
 
     previousSample = nextTimeStamp;
     nextTimeStamp = GetNextTimeStamp();
   }
 }
 
 double
@@ -294,29 +299,39 @@ FPSCounter::PrintFPS()
                 mFPSName, totalFrames, measurementInterval.ToSecondsSigDigits());
 
   PrintHistogram(histogram);
 }
 
 void
 FPSCounter::PrintHistogram(std::map<int, int>& aHistogram)
 {
+  if (aHistogram.size() == 0) {
+    return;
+  }
+
   int length = 0;
   const int kBufferLength = 512;
+  int availableSpace = kBufferLength;
   char buffer[kBufferLength];
 
   for (std::map<int, int>::iterator iter = aHistogram.begin();
     iter != aHistogram.end(); iter++)
   {
     int fps = iter->first;
     int count = iter->second;
 
-    length += snprintf(buffer + length, kBufferLength - length,
-                       "FPS: %d = %d. ", fps, count);
-    NS_ASSERTION(length >= kBufferLength, "Buffer overrun while printing FPS histogram.");
+    int lengthRequired = snprintf(buffer + length, availableSpace,
+                                  "FPS: %d = %d. ", fps, count);
+    // Ran out of buffer space. Oh well - just print what we have.
+    if (lengthRequired > availableSpace) {
+      break;
+    }
+    length += lengthRequired;
+    availableSpace -= lengthRequired;
   }
 
   printf_stderr("%s\n", buffer);
   printf_stderr("Mean: %f , std dev %f\n", GetMean(aHistogram), GetStdDev(aHistogram));
 }
 
 // Write FPS timestamp data to a file only if
 // draw-fps.write-to-file is true
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -752,16 +752,21 @@ gfxMacPlatformFontList::gfxMacPlatformFo
 
     // cache this in a static variable so that MacOSFontFamily objects
     // don't have to repeatedly look it up
     sFontManager = [NSFontManager sharedFontManager];
 }
 
 gfxMacPlatformFontList::~gfxMacPlatformFontList()
 {
+    ::CFNotificationCenterRemoveObserver(::CFNotificationCenterGetLocalCenter(),
+                                         this,
+                                         kCTFontManagerRegisteredFontsChangedNotification,
+                                         0);
+
     if (mDefaultFont) {
         ::CFRelease(mDefaultFont);
     }
 }
 
 void
 gfxMacPlatformFontList::AddFamily(const nsAString& aFamilyName,
                                   bool aSystemFont)
--- a/image/imgLoader.cpp
+++ b/image/imgLoader.cpp
@@ -970,55 +970,87 @@ imgCacheQueue::GetSize() const
 }
 
 #include <algorithm>
 using namespace std;
 
 void
 imgCacheQueue::Remove(imgCacheEntry* entry)
 {
-  auto it = find(mQueue.begin(), mQueue.end(), entry);
-  if (it != mQueue.end()) {
-    mSize -= (*it)->GetDataSize();
-    mQueue.erase(it);
-    MarkDirty();
+  uint64_t index = mQueue.IndexOf(entry);
+  if (index == queueContainer::NoIndex) {
+    return;
+  }
+
+  mSize -= mQueue[index]->GetDataSize();
+
+  // If the queue is clean and this is the first entry,
+  // then we can efficiently remove the entry without
+  // dirtying the sort order.
+  if (!IsDirty() && index == 0) {
+    std::pop_heap(mQueue.begin(), mQueue.end(),
+                  imgLoader::CompareCacheEntries);
+    mQueue.RemoveElementAt(mQueue.Length() - 1);
+    return;
   }
+
+  // Remove from the middle of the list.  This potentially
+  // breaks the binary heap sort order.
+  mQueue.RemoveElementAt(index);
+
+  // If we only have one entry or the queue is empty, though,
+  // then the sort order is still effectively good.  Simply
+  // refresh the list to clear the dirty flag.
+  if (mQueue.Length() <= 1) {
+    Refresh();
+    return;
+  }
+
+  // Otherwise we must mark the queue dirty and potentially
+  // trigger an expensive sort later.
+  MarkDirty();
 }
 
 void
 imgCacheQueue::Push(imgCacheEntry* entry)
 {
   mSize += entry->GetDataSize();
 
   RefPtr<imgCacheEntry> refptr(entry);
-  mQueue.push_back(refptr);
-  MarkDirty();
+  mQueue.AppendElement(Move(refptr));
+  // If we're not dirty already, then we can efficiently add this to the
+  // binary heap immediately.  This is only O(log n).
+  if (!IsDirty()) {
+    std::push_heap(mQueue.begin(), mQueue.end(), imgLoader::CompareCacheEntries);
+  }
 }
 
 already_AddRefed<imgCacheEntry>
 imgCacheQueue::Pop()
 {
-  if (mQueue.empty()) {
+  if (mQueue.IsEmpty()) {
     return nullptr;
   }
   if (IsDirty()) {
     Refresh();
   }
 
-  RefPtr<imgCacheEntry> entry = mQueue[0];
   std::pop_heap(mQueue.begin(), mQueue.end(), imgLoader::CompareCacheEntries);
-  mQueue.pop_back();
+  RefPtr<imgCacheEntry> entry = Move(mQueue.LastElement());
+  mQueue.RemoveElementAt(mQueue.Length() - 1);
 
   mSize -= entry->GetDataSize();
   return entry.forget();
 }
 
 void
 imgCacheQueue::Refresh()
 {
+  // Resort the list.  This is an O(3 * n) operation and best avoided
+  // if possible.
   std::make_heap(mQueue.begin(), mQueue.end(), imgLoader::CompareCacheEntries);
   mDirty = false;
 }
 
 void
 imgCacheQueue::MarkDirty()
 {
   mDirty = true;
@@ -1028,17 +1060,17 @@ bool
 imgCacheQueue::IsDirty()
 {
   return mDirty;
 }
 
 uint32_t
 imgCacheQueue::GetNumElements() const
 {
-  return mQueue.size();
+  return mQueue.Length();
 }
 
 imgCacheQueue::iterator
 imgCacheQueue::begin()
 {
   return mQueue.begin();
 }
 
@@ -1609,17 +1641,22 @@ imgLoader::SetHasProxies(imgRequest* aRe
 
   return false;
 }
 
 void
 imgLoader::CacheEntriesChanged(bool aForChrome, int32_t aSizeDiff /* = 0 */)
 {
   imgCacheQueue& queue = GetCacheQueue(aForChrome);
-  queue.MarkDirty();
+  // We only need to dirty the queue if there is any sorting
+  // taking place.  Empty or single-entry lists can't become
+  // dirty.
+  if (queue.GetNumElements() > 1) {
+    queue.MarkDirty();
+  }
   queue.UpdateSize(aSizeDiff);
 }
 
 void
 imgLoader::CheckCacheLimits(imgCacheTable& cache, imgCacheQueue& queue)
 {
   if (queue.GetNumElements() == 0) {
     NS_ASSERTION(queue.GetSize() == 0,
@@ -2004,23 +2041,23 @@ imgLoader::EvictEntries(imgCacheTable& a
 nsresult
 imgLoader::EvictEntries(imgCacheQueue& aQueueToClear)
 {
   LOG_STATIC_FUNC(gImgLog, "imgLoader::EvictEntries queue");
 
   // We have to make a temporary, since RemoveFromCache removes the element
   // from the queue, invalidating iterators.
   nsTArray<RefPtr<imgCacheEntry> > entries(aQueueToClear.GetNumElements());
-  for (imgCacheQueue::const_iterator i = aQueueToClear.begin();
-       i != aQueueToClear.end(); ++i) {
+  for (auto i = aQueueToClear.begin(); i != aQueueToClear.end(); ++i) {
     entries.AppendElement(*i);
   }
 
-  for (uint32_t i = 0; i < entries.Length(); ++i) {
-    if (!RemoveFromCache(entries[i])) {
+  // Iterate in reverse order to minimize array copying.
+  for (auto& entry : entries) {
+    if (!RemoveFromCache(entry)) {
       return NS_ERROR_FAILURE;
     }
   }
 
   MOZ_ASSERT(aQueueToClear.GetNumElements() == 0);
 
   return NS_OK;
 }
--- a/image/imgLoader.h
+++ b/image/imgLoader.h
@@ -196,17 +196,17 @@ public:
   void Push(imgCacheEntry*);
   void MarkDirty();
   bool IsDirty();
   already_AddRefed<imgCacheEntry> Pop();
   void Refresh();
   uint32_t GetSize() const;
   void UpdateSize(int32_t diff);
   uint32_t GetNumElements() const;
-  typedef std::vector<RefPtr<imgCacheEntry> > queueContainer;
+  typedef nsTArray<RefPtr<imgCacheEntry> > queueContainer;
   typedef queueContainer::iterator iterator;
   typedef queueContainer::const_iterator const_iterator;
 
   iterator begin();
   const_iterator begin() const;
   iterator end();
   const_iterator end() const;
 
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -554,18 +554,17 @@ XPCJSContext::ActivityCallback(void* arg
 
     XPCJSContext* self = static_cast<XPCJSContext*>(arg);
     self->mWatchdogManager->RecordContextActivity(self, active);
 }
 
 static inline bool
 IsWebExtensionPrincipal(nsIPrincipal* principal, nsAString& addonId)
 {
-    return (NS_SUCCEEDED(principal->GetAddonId(addonId)) &&
-            !addonId.IsEmpty());
+    return BasePrincipal::Cast(principal)->AddonPolicy();
 }
 
 static bool
 IsWebExtensionContentScript(BasePrincipal* principal, nsAString& addonId)
 {
     if (!principal->Is<ExpandedPrincipal>()) {
         return false;
     }
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -2215,20 +2215,20 @@ RecreateLostWaivers(JSContext* cx, const
                     MutableHandle<PropertyDescriptor> wrapped)
 {
     // Compute whether the original objects were waived, and implicitly, whether
     // they were objects at all.
     bool valueWasWaived =
         orig->value.isObject() &&
         WrapperFactory::HasWaiveXrayFlag(&orig->value.toObject());
     bool getterWasWaived =
-        (orig->attrs & JSPROP_GETTER) &&
+        (orig->attrs & JSPROP_GETTER) && orig->getter &&
         WrapperFactory::HasWaiveXrayFlag(JS_FUNC_TO_DATA_PTR(JSObject*, orig->getter));
     bool setterWasWaived =
-        (orig->attrs & JSPROP_SETTER) &&
+        (orig->attrs & JSPROP_SETTER) && orig->setter &&
         WrapperFactory::HasWaiveXrayFlag(JS_FUNC_TO_DATA_PTR(JSObject*, orig->setter));
 
     // Recreate waivers. Note that for value, we need an extra UncheckedUnwrap
     // to handle same-compartment security wrappers (see above). This should
     // never happen for getters/setters.
 
     RootedObject rewaived(cx);
     if (valueWasWaived && !IsCrossCompartmentWrapper(&wrapped.value().toObject())) {
--- a/layout/reftests/backgrounds/reftest.list
+++ b/layout/reftests/backgrounds/reftest.list
@@ -164,17 +164,17 @@ fuzzy-if(skiaContent,1,400) fuzzy-if(web
 fuzzy(50,500) fuzzy-if(skiaContent,51,320) fails-if(webrender) == attachment-local-clipping-color-6.html attachment-local-clipping-color-6-ref.html
 
 == attachment-local-clipping-image-1.html attachment-local-clipping-image-1-ref.html
 == attachment-local-clipping-image-2.html attachment-local-clipping-image-1-ref.html  # Same ref as the previous test.
 == attachment-local-clipping-image-3.html attachment-local-clipping-image-3-ref.html
 # The next three tests are fuzzy due to bug 1128229.
 fuzzy(16,69) fuzzy-if(skiaContent,95,2200) == attachment-local-clipping-image-4.html attachment-local-clipping-image-4-ref.html
 fuzzy(16,69) fuzzy-if(skiaContent,95,2200) == attachment-local-clipping-image-5.html attachment-local-clipping-image-4-ref.html
-fuzzy(80,500) fuzzy-if(skiaContent,100,908) fails-if(webrender) == attachment-local-clipping-image-6.html attachment-local-clipping-image-6-ref.html
+fuzzy(80,500) fuzzy-if(skiaContent,109,908) fails-if(webrender) == attachment-local-clipping-image-6.html attachment-local-clipping-image-6-ref.html
 
 fuzzy-if(skiaContent,1,8) fuzzy-if(webrender,1,84) == background-multiple-with-border-radius.html background-multiple-with-border-radius-ref.html
 == background-repeat-large-area.html background-repeat-large-area-ref.html
 
 fuzzy(30,474) fuzzy-if(skiaContent,31,474) == background-tiling-zoom-1.html background-tiling-zoom-1-ref.html
 
 skip-if(!cocoaWidget) == background-repeat-resampling.html background-repeat-resampling-ref.html
 
--- a/layout/tools/reftest/reftestcommandline.py
+++ b/layout/tools/reftest/reftestcommandline.py
@@ -246,16 +246,26 @@ class ReftestArgumentsParser(argparse.Ar
                           dest="workPath",
                           help="Path to the base dir of all source files.")
 
         self.add_argument("--obj-path",
                           action="store",
                           dest="objPath",
                           help="Path to the base dir of all object files.")
 
+        self.add_argument("--verify",
+                          action="store_true",
+                          default=False,
+                          help="Test verification mode.")
+
+        self.add_argument("--verify-max-time",
+                          type=int,
+                          default=3600,
+                          help="Maximum time, in seconds, to run in --verify mode..")
+
         mozlog.commandline.add_logging_group(self)
 
     def get_ip(self):
         import moznetwork
         if os.name != "nt":
             return moznetwork.get_ip()
         else:
             self.error(
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -2,27 +2,29 @@
 # 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/.
 
 """
 Runs the reftest test harness.
 """
 
 import collections
+import copy
 import itertools
 import json
 import multiprocessing
 import os
 import platform
 import re
 import shutil
 import signal
 import subprocess
 import sys
 import threading
+from datetime import datetime, timedelta
 
 SCRIPT_DIRECTORY = os.path.abspath(
     os.path.realpath(os.path.dirname(__file__)))
 if SCRIPT_DIRECTORY not in sys.path:
     sys.path.insert(0, SCRIPT_DIRECTORY)
 
 import mozcrash
 import mozdebug
@@ -410,16 +412,89 @@ class RefTest(object):
         self.leakLogFile = os.path.join(profileDir, "runreftest_leaks.log")
         browserEnv["XPCOM_MEM_BLOAT_LOG"] = self.leakLogFile
         return browserEnv
 
     def cleanup(self, profileDir):
         if profileDir:
             shutil.rmtree(profileDir, True)
 
+    def verifyTests(self, tests, options):
+        """
+        Support --verify mode: Run test(s) many times in a variety of
+        configurations/environments in an effort to find intermittent
+        failures.
+        """
+
+        self._populate_logger(options)
+
+        # Number of times to repeat test(s) when running with --repeat
+        VERIFY_REPEAT = 20
+        # Number of times to repeat test(s) when running test in separate browser
+        VERIFY_REPEAT_SINGLE_BROWSER = 10
+
+        def step1():
+            stepOptions = copy.deepcopy(options)
+            stepOptions.repeat = VERIFY_REPEAT
+            stepOptions.runUntilFailure = True
+            result = self.runTests(tests, stepOptions)
+            return result
+
+        def step2():
+            stepOptions = copy.deepcopy(options)
+            for i in xrange(VERIFY_REPEAT_SINGLE_BROWSER):
+                result = self.runTests(tests, stepOptions)
+                if result != 0:
+                    break
+            return result
+
+        steps = [
+            ("1. Run each test %d times in one browser." % VERIFY_REPEAT,
+             step1),
+            ("2. Run each test %d times in a new browser each time." %
+             VERIFY_REPEAT_SINGLE_BROWSER,
+             step2),
+        ]
+
+        stepResults = {}
+        for (descr, step) in steps:
+            stepResults[descr] = "not run / incomplete"
+
+        startTime = datetime.now()
+        maxTime = timedelta(seconds=options.verify_max_time)
+        finalResult = "PASSED"
+        for (descr, step) in steps:
+            if (datetime.now() - startTime) > maxTime:
+                self.log.info("::: Test verification is taking too long: Giving up!")
+                self.log.info("::: So far, all checks passed, but not all checks were run.")
+                break
+            self.log.info(':::')
+            self.log.info('::: Running test verification step "%s"...' % descr)
+            self.log.info(':::')
+            result = step()
+            if result != 0:
+                stepResults[descr] = "FAIL"
+                finalResult = "FAILED!"
+                break
+            stepResults[descr] = "Pass"
+
+        self.log.info(':::')
+        self.log.info('::: Test verification summary for:')
+        self.log.info(':::')
+        for test in tests:
+            self.log.info('::: '+test)
+        self.log.info(':::')
+        for descr in sorted(stepResults.keys()):
+            self.log.info('::: %s : %s' % (descr, stepResults[descr]))
+        self.log.info(':::')
+        self.log.info('::: Test verification %s' % finalResult)
+        self.log.info(':::')
+
+        return result
+
     def runTests(self, tests, options, cmdargs=None):
         cmdargs = cmdargs or []
         self._populate_logger(options)
 
         if options.cleanupCrashes:
             mozcrash.cleanup_pending_crash_reports()
 
         manifests = self.resolver.resolveManifests(options, tests)
@@ -758,15 +833,20 @@ def run_test_harness(parser, options):
     options.app = reftest.getFullPath(options.app)
     if not os.path.exists(options.app):
         parser.error("Error: Path %(app)s doesn't exist. Are you executing "
                      "$objdir/_tests/reftest/runreftest.py?" % {"app": options.app})
 
     if options.xrePath is None:
         options.xrePath = os.path.dirname(options.app)
 
-    return reftest.runTests(options.tests, options)
+    if options.verify:
+        result = reftest.verifyTests(options.tests, options)
+    else:
+        result = reftest.runTests(options.tests, options)
+
+    return result
 
 
 if __name__ == "__main__":
     parser = reftestcommandline.DesktopArgumentsParser()
     options = parser.parse_args()
     sys.exit(run_test_harness(parser, options))
--- a/layout/xul/tree/nsITreeColumns.idl
+++ b/layout/xul/tree/nsITreeColumns.idl
@@ -1,31 +1,29 @@
 /* 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/. */
 
 #include "nsISupports.idl"
 
 interface nsITreeColumns;
 interface nsIDOMElement;
-interface nsIAtom;
 
 [scriptable, uuid(ae835ecf-6b32-4660-9b43-8a270df56e02)]
 interface nsITreeColumn : nsISupports
 {
   readonly attribute nsIDOMElement element;
 
   readonly attribute nsITreeColumns columns;
 
   readonly attribute long x;
   readonly attribute long width;
 
   readonly attribute AString id;
   [noscript] void getIdConst([shared] out wstring idConst);
-  [noscript] readonly attribute nsIAtom atom;
 
   readonly attribute long index;
 
   readonly attribute boolean primary;
   readonly attribute boolean cycler;
   readonly attribute boolean editable;
   readonly attribute boolean selectable;
 
--- a/layout/xul/tree/nsTreeColumns.cpp
+++ b/layout/xul/tree/nsTreeColumns.cpp
@@ -197,23 +197,16 @@ nsTreeColumn::GetId(nsAString& aId)
 NS_IMETHODIMP
 nsTreeColumn::GetIdConst(const char16_t** aIdConst)
 {
   *aIdConst = mId.get();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsTreeColumn::GetAtom(nsIAtom** aAtom)
-{
-  NS_IF_ADDREF(*aAtom = GetAtom());
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsTreeColumn::GetIndex(int32_t* aIndex)
 {
   *aIndex = GetIndex();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTreeColumn::GetPrimary(bool* aPrimary)
--- a/mobile/android/base/java/org/mozilla/gecko/telemetry/TelemetryBackgroundReceiver.java
+++ b/mobile/android/base/java/org/mozilla/gecko/telemetry/TelemetryBackgroundReceiver.java
@@ -33,17 +33,17 @@ import org.mozilla.gecko.util.ThreadUtil
 import java.io.IOException;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Set;
 
 /**
  * Receives and processes telemetry broadcasts from background services, namely Sync.
  * Nomenclature:
- * - Bundled Sync Ping: a Sync Ping as documented at http://gecko.readthedocs.io/en/latest/toolkit/components/telemetry/telemetry/data/sync-ping.html
+ * - Bundled Sync Ping: a Sync Ping as documented at https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/data/sync-ping.html
  *   as of commit https://github.com/mozilla-services/docs/commit/7eb4b412d3ab5ec46b280eff312ace32e7cf27e6
  * - Telemetry data: incoming background telemetry, of two types: "sync" and "sync event"
  * - Local Sync Ping: a persistable representation of incoming telemetry data. Not intended for upload.
  *   See {@link TelemetryLocalPing}
  *
  * General flow:
  * - background telemetry bundles come in, describing syncs or events that happened
  * - telemetry bundles are transformed into a local pings and persisted
--- a/mobile/android/base/java/org/mozilla/gecko/telemetry/pingbuilders/TelemetryCorePingBuilder.java
+++ b/mobile/android/base/java/org/mozilla/gecko/telemetry/pingbuilders/TelemetryCorePingBuilder.java
@@ -31,17 +31,17 @@ import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
 /**
  * Builds a {@link TelemetryOutgoingPing} representing a core ping.
  *
- * See https://gecko.readthedocs.org/en/latest/toolkit/components/telemetry/telemetry/core-ping.html
+ * See https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/data/core-ping.html
  * for details on the core ping.
  */
 public class TelemetryCorePingBuilder extends TelemetryPingBuilder {
     private static final String LOGTAG = StringUtils.safeSubstring(TelemetryCorePingBuilder.class.getSimpleName(), 0, 23);
 
     // For legacy reasons, this preference key is not namespaced with "core".
     private static final String PREF_SEQ_COUNT = "telemetry-seqCount";
 
--- a/mobile/android/base/java/org/mozilla/gecko/telemetry/pingbuilders/TelemetrySyncPingBundleBuilder.java
+++ b/mobile/android/base/java/org/mozilla/gecko/telemetry/pingbuilders/TelemetrySyncPingBundleBuilder.java
@@ -21,17 +21,17 @@ import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.List;
 import java.util.Locale;
 import java.util.TimeZone;
 
 /**
  * Responsible for building a Sync Ping, based on the telemetry docs:
- * http://gecko.readthedocs.io/en/latest/toolkit/components/telemetry/telemetry/data/sync-ping.html
+ * https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/data/sync-ping.html
  *
  * This builder takes two stores ('sync' and 'event') and produces a single "sync ping".
  *
  * Note that until Bug 1363924, event telemetry will be ignored.
  *
  * Sample result will look something like:
  * {
  *     "syncs": [list of syncs, as produced by the SyncBuilder],
old mode 100644
new mode 100755
--- a/mobile/android/mach_commands.py
+++ b/mobile/android/mach_commands.py
@@ -257,17 +257,17 @@ class MachCommands(MachCommandBase):
             print("TinderboxPrint: report<br/><a href='{}/{}'>HTML {} report</a>, visit \"Inspect Task\" link for details".format(root_url, report.replace('.xml', '.html'), title))
             print("TinderboxPrint: report<br/><a href='{}/{}'>XML {} report</a>, visit \"Inspect Task\" link for details".format(root_url, report, title))
 
         return ret
 
 
     @SubCommand('android', 'gradle-dependencies',
         """Collect Android Gradle dependencies.
-        See https://gecko.readthedocs.io/en/latest/build/buildsystem/toolchains.html#firefox-for-android-with-gradle""")
+        See http://firefox-source-docs.mozilla.org/build/buildsystem/toolchains.html#firefox-for-android-with-gradle""")
     @CommandArgument('args', nargs=argparse.REMAINDER)
     def android_gradle_dependencies(self, args):
         # The union, plus a bit more, of all of the Gradle tasks
         # invoked by the android-* automation jobs.
         gradle_targets = [
             'app:checkstyle',
             'app:assembleOfficialPhotonRelease',
             'app:assembleOfficialPhotonDebug',
--- a/netwerk/cookie/CookieServiceChild.cpp
+++ b/netwerk/cookie/CookieServiceChild.cpp
@@ -2,16 +2,17 @@
 /* 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/. */
 
 #include "mozilla/net/CookieServiceChild.h"
 #include "mozilla/net/NeckoChannelParams.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/BasePrincipal.h"
+#include "mozilla/ClearOnShutdown.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/SystemGroup.h"
 #include "nsCookie.h"
 #include "nsCookieService.h"
 #include "nsContentUtils.h"
 #include "nsNetCID.h"
@@ -31,26 +32,27 @@ namespace net {
 
 // Pref string constants
 static const char kPrefCookieBehavior[] = "network.cookie.cookieBehavior";
 static const char kPrefThirdPartySession[] =
   "network.cookie.thirdparty.sessionOnly";
 static const char kPrefCookieIPCSync[] = "network.cookie.ipc.sync";
 static const char kCookieLeaveSecurityAlone[] = "network.cookie.leave-secure-alone";
 
-static CookieServiceChild *gCookieService;
+static StaticRefPtr<CookieServiceChild> gCookieService;
 
-CookieServiceChild*
+already_AddRefed<CookieServiceChild>
 CookieServiceChild::GetSingleton()
 {
-  if (!gCookieService)
+  if (!gCookieService) {
     gCookieService = new CookieServiceChild();
+    ClearOnShutdown(&gCookieService);
+  }
 
-  NS_ADDREF(gCookieService);
-  return gCookieService;
+  return do_AddRef(gCookieService);
 }
 
 NS_IMPL_ISUPPORTS(CookieServiceChild,
                   nsICookieService,
                   nsIObserver,
                   nsISupportsWeakReference)
 
 CookieServiceChild::CookieServiceChild()
--- a/netwerk/cookie/CookieServiceChild.h
+++ b/netwerk/cookie/CookieServiceChild.h
@@ -35,17 +35,17 @@ public:
   NS_DECL_NSICOOKIESERVICE
   NS_DECL_NSIOBSERVER
 
   typedef nsTArray<RefPtr<nsCookie>> CookiesList;
   typedef nsClassHashtable<nsCookieKey, CookiesList> CookiesMap;
 
   CookieServiceChild();
 
-  static CookieServiceChild* GetSingleton();
+  static already_AddRefed<CookieServiceChild> GetSingleton();
 
   void
   TrackCookieLoad(nsIChannel *aChannel);
 
 protected:
   virtual ~CookieServiceChild();
 
   void SerializeURIs(nsIURI *aHostURI,
--- a/netwerk/cookie/CookieServiceParent.cpp
+++ b/netwerk/cookie/CookieServiceParent.cpp
@@ -65,18 +65,17 @@ namespace net {
 
 CookieServiceParent::CookieServiceParent()
 {
   // Instantiate the cookieservice via the service manager, so it sticks around
   // until shutdown.
   nsCOMPtr<nsICookieService> cs = do_GetService(NS_COOKIESERVICE_CONTRACTID);
 
   // Get the nsCookieService instance directly, so we can call internal methods.
-  mCookieService =
-    already_AddRefed<nsCookieService>(nsCookieService::GetSingleton());
+  mCookieService = nsCookieService::GetSingleton();
   NS_ASSERTION(mCookieService, "couldn't get nsICookieService");
 }
 
 CookieServiceParent::~CookieServiceParent()
 {
 }
 
 void
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set sw=2 ts=8 et tw=80 : */
 /* 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/. */
 
 #include "mozilla/Attributes.h"
+#include "mozilla/ClearOnShutdown.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Likely.h"
 #include "mozilla/Printf.h"
 #include "mozilla/Unused.h"
 
 #include "mozilla/net/CookieServiceChild.h"
 #include "mozilla/net/NeckoCommon.h"
 
@@ -67,17 +68,17 @@ using namespace mozilla::net;
 #define DEFAULT_APP_KEY(baseDomain) \
         nsCookieKey(baseDomain, OriginAttributes())
 
 /******************************************************************************
  * nsCookieService impl:
  * useful types & constants
  ******************************************************************************/
 
-static nsCookieService *gCookieService;
+static StaticRefPtr<nsCookieService> gCookieService;
 
 // XXX_hack. See bug 178993.
 // This is a hack to hide HttpOnly cookies from older browsers
 #define HTTP_ONLY_PREFIX "#HttpOnly_"
 
 #define COOKIES_FILE "cookies.sqlite"
 #define COOKIES_SCHEMA_VERSION 8
 
@@ -633,50 +634,50 @@ DBState::SizeOfIncludingThis(MallocSizeO
   return amount;
 }
 
 /******************************************************************************
  * nsCookieService impl:
  * singleton instance ctor/dtor methods
  ******************************************************************************/
 
-nsICookieService*
+already_AddRefed<nsICookieService>
 nsCookieService::GetXPCOMSingleton()
 {
   if (IsNeckoChild())
     return CookieServiceChild::GetSingleton();
 
   return GetSingleton();
 }
 
-nsCookieService*
+already_AddRefed<nsCookieService>
 nsCookieService::GetSingleton()
 {
   NS_ASSERTION(!IsNeckoChild(), "not a parent process");
 
   if (gCookieService) {
-    NS_ADDREF(gCookieService);
-    return gCookieService;
+    return do_AddRef(gCookieService);
   }
 
   // Create a new singleton nsCookieService.
   // We AddRef only once since XPCOM has rules about the ordering of module
   // teardowns - by the time our module destructor is called, it's too late to
   // Release our members (e.g. nsIObserverService and nsIPrefBranch), since GC
   // cycles have already been completed and would result in serious leaks.
   // See bug 209571.
   gCookieService = new nsCookieService();
   if (gCookieService) {
-    NS_ADDREF(gCookieService);
-    if (NS_FAILED(gCookieService->Init())) {
-      NS_RELEASE(gCookieService);
+    if (NS_SUCCEEDED(gCookieService->Init())) {
+      ClearOnShutdown(&gCookieService);
+    } else {
+      gCookieService = nullptr;
     }
   }
 
-  return gCookieService;
+  return do_AddRef(gCookieService);
 }
 
 /* static */ void
 nsCookieService::AppClearDataObserverInit()
 {
   nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
   nsCOMPtr<nsIObserver> obs = new AppClearDataObserver();
   observerService->AddObserver(obs, TOPIC_CLEAR_ORIGIN_DATA,
--- a/netwerk/cookie/nsCookieService.h
+++ b/netwerk/cookie/nsCookieService.h
@@ -210,18 +210,18 @@ class nsCookieService final : public nsI
     NS_DECL_ISUPPORTS
     NS_DECL_NSIOBSERVER
     NS_DECL_NSICOOKIESERVICE
     NS_DECL_NSICOOKIEMANAGER
     NS_DECL_NSICOOKIEMANAGER2
     NS_DECL_NSIMEMORYREPORTER
 
     nsCookieService();
-    static nsICookieService*      GetXPCOMSingleton();
-    nsresult                      Init();
+    static already_AddRefed<nsICookieService> GetXPCOMSingleton();
+    nsresult Init();
 
   /**
    * Start watching the observer service for messages indicating that an app has
    * been uninstalled.  When an app is uninstalled, we get the cookie service
    * (thus instantiating it, if necessary) and clear all the cookies for that
    * app.
    */
   static void AppClearDataObserverInit();
@@ -325,13 +325,13 @@ class nsCookieService final : public nsI
     uint16_t                      mMaxCookiesPerHost;
     int64_t                       mCookiePurgeAge;
 
     // friends!
     friend class DBListenerErrorHandler;
     friend class ReadCookieDBListener;
     friend class CloseCookieDBListener;
 
-    static nsCookieService*       GetSingleton();
+    static already_AddRefed<nsCookieService> GetSingleton();
     friend class mozilla::net::CookieServiceParent;
 };
 
 #endif // nsCookieService_h__
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -198,17 +198,17 @@ HttpChannelChild::HttpChannelChild()
     sSecurityPrefChecked = true;
   }
 #endif
 
   // Ensure that the cookie service is initialized before the first
   // IPC HTTP channel is created.
   // We require that the parent cookie service actor exists while
   // processing HTTP responses.
-  CookieServiceChild::GetSingleton();
+  RefPtr<CookieServiceChild> cookieService = CookieServiceChild::GetSingleton();
 }
 
 HttpChannelChild::~HttpChannelChild()
 {
   LOG(("Destroying HttpChannelChild @%p\n", this));
 
   ReleaseMainThreadOnlyReferences();
 }
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -456,26 +456,22 @@ nsHttpHandler::Init()
           appInfo->GetName(mAppName);
         }
         appInfo->GetVersion(mAppVersion);
         mAppName.StripChars(R"( ()<>@,;:\"/[]?={})");
     } else {
         mAppVersion.AssignLiteral(MOZ_APP_UA_VERSION);
     }
 
-    // Generating the spoofed userAgent for fingerprinting resistance.
-    // The browser version will be rounded down to a multiple of 10.
-    // By doing so, the anonymity group will cover more versions instead of one
-    // version.
-    uint32_t spoofedVersion = mAppVersion.ToInteger(&rv);
-    if (NS_SUCCEEDED(rv)) {
-        spoofedVersion = spoofedVersion - (spoofedVersion % 10);
-        mSpoofedUserAgent.Assign(nsPrintfCString(
-            "Mozilla/5.0 (%s; rv:%d.0) Gecko/%s Firefox/%d.0",
-            SPOOFED_OSCPU, spoofedVersion, LEGACY_BUILD_ID, spoofedVersion));
+    // Generating the spoofed User Agent for fingerprinting resistance.
+    rv = nsRFPService::GetSpoofedUserAgent(mSpoofedUserAgent);
+    if (NS_FAILED(rv)) {
+      // Empty mSpoofedUserAgent to make sure the unsuccessful spoofed UA string
+      // will not be used anywhere.
+      mSpoofedUserAgent.Truncate();
     }
 
     mSessionStartTime = NowInSeconds();
     mHandlerActive = true;
 
     rv = mAuthCache.Init();
     if (NS_FAILED(rv)) return rv;
 
old mode 100644
new mode 100755
--- a/testing/mozbase/manifestparser/manifestparser/manifestparser.py
+++ b/testing/mozbase/manifestparser/manifestparser/manifestparser.py
@@ -60,17 +60,17 @@ class ManifestParser(object):
                        are not considered fatal. Those errors include duplicate
                        section names, redefining variables, and defining empty
                        variables.
         :param rootdir: The directory used as the basis for conversion to and from
                         relative paths during manifest reading.
         :param finder: If provided, this finder object will be used for filesystem
                        interactions. Finder objects are part of the mozpack package,
                        documented at
-                       http://gecko.readthedocs.org/en/latest/python/mozpack.html#module-mozpack.files
+                       http://firefox-source-docs.mozilla.org/python/mozpack.html#module-mozpack.files
         :param handle_defaults: If not set, do not propagate manifest defaults to individual
                                 test objects. Callers are expected to manage per-manifest
                                 defaults themselves via the manifest_defaults member
                                 variable in this case.
         """
         self._defaults = defaults or {}
         self._ancestor_defaults = {}
         self.tests = []
old mode 100644
new mode 100755
--- a/testing/mozharness/manifestparser/manifestparser.py
+++ b/testing/mozharness/manifestparser/manifestparser.py
@@ -60,17 +60,17 @@ class ManifestParser(object):
                        are not considered fatal. Those errors include duplicate
                        section names, redefining variables, and defining empty
                        variables.
         :param rootdir: The directory used as the basis for conversion to and from
                         relative paths during manifest reading.
         :param finder: If provided, this finder object will be used for filesystem
                        interactions. Finder objects are part of the mozpack package,
                        documented at
-                       http://gecko.readthedocs.org/en/latest/python/mozpack.html#module-mozpack.files
+                       http://firefox-source-docs.mozilla.org/python/mozpack.html#module-mozpack.files
         :param handle_defaults: If not set, do not propagate manifest defaults to individual
                                 test objects. Callers are expected to manage per-manifest
                                 defaults themselves via the manifest_defaults member
                                 variable in this case.
         """
         self._defaults = defaults or {}
         self._ancestor_defaults = {}
         self.tests = []
--- a/toolkit/components/extensions/ExtensionPolicyService.cpp
+++ b/toolkit/components/extensions/ExtensionPolicyService.cpp
@@ -245,20 +245,17 @@ ExtensionPolicyService::CheckDocument(ns
   nsCOMPtr<nsPIDOMWindowOuter> win = aDocument->GetWindow();
   if (win) {
     if (win->GetDocumentURI()) {
       CheckContentScripts(win.get(), false);
     }
 
     nsIPrincipal* principal = aDocument->NodePrincipal();
 
-    nsAutoString addonId;
-    Unused << principal->GetAddonId(addonId);
-
-    RefPtr<WebExtensionPolicy> policy = GetByID(addonId);
+    RefPtr<WebExtensionPolicy> policy = BasePrincipal::Cast(principal)->AddonPolicy();
     if (policy) {
       nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aDocument);
       ProcessScript().InitExtensionDocument(policy, doc);
     }
   }
 }
 
 // Checks for loads of about:blank into new window globals, and loads any
--- a/toolkit/components/extensions/webrequest/StreamFilter.cpp
+++ b/toolkit/components/extensions/webrequest/StreamFilter.cpp
@@ -256,17 +256,17 @@ StreamFilter::FireErrorEvent(const nsASt
 
 /*****************************************************************************
  * Glue
  *****************************************************************************/
 
 /* static */ bool
 StreamFilter::IsAllowedInContext(JSContext* aCx, JSObject* /* unused */)
 {
-  return nsContentUtils::CallerHasPermission(aCx, NS_LITERAL_STRING("webRequestBlocking"));
+  return nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::webRequestBlocking);
 }
 
 JSObject*
 StreamFilter::WrapObject(JSContext* aCx, HandleObject aGivenProto)
 {
   return StreamFilterBinding::Wrap(aCx, this, aGivenProto);
 }
 
--- a/toolkit/components/resistfingerprinting/nsRFPService.cpp
+++ b/toolkit/components/resistfingerprinting/nsRFPService.cpp
@@ -13,20 +13,23 @@
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 
 #include "nsCOMPtr.h"
 #include "nsCoord.h"
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
 #include "nsXULAppAPI.h"
+#include "nsPrintfCString.h"
 
 #include "nsIObserverService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
+#include "nsIXULAppInfo.h"
+#include "nsIXULRuntime.h"
 #include "nsJSUtils.h"
 
 #include "prenv.h"
 
 #include "js/Date.h"
 
 using namespace mozilla;
 using namespace std;
@@ -157,16 +160,69 @@ nsRFPService::GetSpoofedPresentedFrames(
 
   double time = ReduceTimePrecisionAsSecs(aTime);
   // Bound the dropped ratio from 0 to 100.
   uint32_t boundedDroppedRatio = min(sVideoDroppedRatio, 100u);
 
   return NSToIntFloor(time * sVideoFramesPerSec * ((100 - boundedDroppedRatio) / 100.0));
 }
 
+/* static */
+nsresult
+nsRFPService::GetSpoofedUserAgent(nsACString &userAgent)
+{
+  // This function generates the spoofed value of User Agent.
+  // We spoof the values of the platform and Firefox version, which could be
+  // used as fingerprinting sources to identify individuals.
+  // Reference of the format of User Agent:
+  // https://developer.mozilla.org/en-US/docs/Web/API/NavigatorID/userAgent
+  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent
+
+  nsresult rv;
+  nsCOMPtr<nsIXULAppInfo> appInfo =
+    do_GetService("@mozilla.org/xre/app-info;1", &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsAutoCString appVersion;
+  rv = appInfo->GetVersion(appVersion);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // The browser version will be spoofed as the last ESR version.
+  // By doing so, the anonymity group will cover more versions instead of one
+  // version.
+  uint32_t firefoxVersion = appVersion.ToInteger(&rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Starting from Firefox 10, Firefox ESR was released once every seven
+  // Firefox releases, e.g. Firefox 10, 17, 24, 31, and so on.
+  // We infer the last and closest ESR version based on this rule.
+  nsCOMPtr<nsIXULRuntime> runtime =
+    do_GetService("@mozilla.org/xre/runtime;1", &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsAutoCString updateChannel;
+  rv = runtime->GetDefaultUpdateChannel(updateChannel);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // If we are running in Firefox ESR, determine whether the formula of ESR
+  // version has changed.  Once changed, we must update the formula in this
+  // function.
+  if (updateChannel.Equals("esr")) {
+    MOZ_ASSERT(((firefoxVersion % 7) == 3),
+      "Please udpate ESR version formula in nsRFPService.cpp");
+  }
+
+  uint32_t spoofedVersion = firefoxVersion - ((firefoxVersion - 3) % 7);
+  userAgent.Assign(nsPrintfCString(
+    "Mozilla/5.0 (%s; rv:%d.0) Gecko/%s Firefox/%d.0",
+    SPOOFED_OSCPU, spoofedVersion, LEGACY_BUILD_ID, spoofedVersion));
+
+  return rv;
+}
+
 nsresult
 nsRFPService::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsresult rv;
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
--- a/toolkit/components/resistfingerprinting/nsRFPService.h
+++ b/toolkit/components/resistfingerprinting/nsRFPService.h
@@ -44,16 +44,19 @@ public:
   static uint32_t CalculateTargetVideoResolution(uint32_t aVideoQuality);
 
   // Methods for getting spoofed media statistics and the return value will
   // depend on the video resolution.
   static uint32_t GetSpoofedTotalFrames(double aTime);
   static uint32_t GetSpoofedDroppedFrames(double aTime, uint32_t aWidth, uint32_t aHeight);
   static uint32_t GetSpoofedPresentedFrames(double aTime, uint32_t aWidth, uint32_t aHeight);
 
+  // This method generates the spoofed value of User Agent.
+  static nsresult GetSpoofedUserAgent(nsACString &userAgent);
+
 private:
   nsresult Init();
 
   nsRFPService() {}
 
   ~nsRFPService() {}
 
   void UpdatePref();
--- a/toolkit/components/telemetry/Processes.yaml
+++ b/toolkit/components/telemetry/Processes.yaml
@@ -1,12 +1,12 @@
 # This lists the known child processes we collect Telemetry for.
 # The entries are keyed with the names used in Telemetry internally, the same name that is used
 # in the main pings payload, i.e. "payload/processes/<process name>". See:
-# https://gecko.readthedocs.io/en/latest/toolkit/components/telemetry/telemetry/data/main-ping.html#processes
+# https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/data/main-ping.html#processes
 #
 # For now this is only used to inform the data pipeline about new processes, but will be used to
 # generate headers with C++ data later (enums, strings, ...).
 parent:
   gecko_enum: GeckoProcessType_Default
   description: This is the main process. It is also known as the parent or chrome process.
 content:
   gecko_enum: GeckoProcessType_Content
old mode 100644
new mode 100755
--- a/toolkit/components/telemetry/histogram_tools.py
+++ b/toolkit/components/telemetry/histogram_tools.py
@@ -30,17 +30,17 @@ ALWAYS_ALLOWED_KEYS = [
     'alert_emails',
     'keyed',
     'releaseChannelCollection',
     'bug_numbers',
     'keys',
     'record_in_processes',
 ]
 
-BASE_DOC_URL = ("https://gecko.readthedocs.io/en/latest/toolkit/components/"
+BASE_DOC_URL = ("https://firefox-source-docs.mozilla.org/toolkit/components/"
                 "telemetry/telemetry/")
 HISTOGRAMS_DOC_URL = (BASE_DOC_URL + "collection/histograms.html")
 SCALARS_DOC_URL = (BASE_DOC_URL + "collection/scalars.html")
 
 # histogram_tools.py is used by scripts from a mozilla-central build tree
 # and also by outside consumers, such as the telemetry server.  We need
 # to ensure that importing things works in both contexts.  Therefore,
 # unconditionally importing things that are local to the build tree, such
old mode 100644
new mode 100755
--- a/toolkit/components/telemetry/parse_scalars.py
+++ b/toolkit/components/telemetry/parse_scalars.py
@@ -6,17 +6,17 @@ import re
 import yaml
 import shared_telemetry_utils as utils
 
 from shared_telemetry_utils import ParserError
 
 # The map of containing the allowed scalar types and their mapping to
 # nsITelemetry::SCALAR_* type constants.
 
-BASE_DOC_URL = 'https://gecko.readthedocs.io/en/latest/toolkit/components/' + \
+BASE_DOC_URL = 'https://firefox-source-docs.mozilla.org/toolkit/components/' + \
                'telemetry/telemetry/collection/scalars.html'
 
 SCALAR_TYPES_MAP = {
     'uint': 'nsITelemetry::SCALAR_COUNT',
     'string': 'nsITelemetry::SCALAR_STRING',
     'boolean': 'nsITelemetry::SCALAR_BOOLEAN'
 }
 
old mode 100644
new mode 100755
--- a/toolkit/content/aboutTelemetry.js
+++ b/toolkit/content/aboutTelemetry.js
@@ -302,17 +302,17 @@ var PingPicker = {
   },
 
   onPingDisplayChanged() {
     this.update();
   },
 
   render() {
     let pings = bundle.GetStringFromName("pingExplanationLink");
-    let pingLink = "<a href=\"http://gecko.readthedocs.io/en/latest/toolkit/components/telemetry/telemetry/concepts/pings.html\">" + pings + "</a>";
+    let pingLink = "<a href=\"https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/concepts/pings.html\">" + pings + "</a>";
     let pingName = this._getSelectedPingName();
 
     // Display the type and controls if the ping is not current
     let pingDate = document.getElementById("ping-date");
     let pingType = document.getElementById("ping-type");
     let controls = document.getElementById("controls");
     let explanation;
     if (!this.viewCurrentPingData) {
--- a/toolkit/content/tests/widgets/mochitest.ini
+++ b/toolkit/content/tests/widgets/mochitest.ini
@@ -45,9 +45,9 @@ skip-if = toolkit == 'android' # bug 107
 skip-if = os == 'win'
 [test_videocontrols_video_noaudio.html]
 skip-if = toolkit == 'android'
 [test_bug1319301.html]
 skip-if = toolkit == 'android'
 [test_bug898940.html]
 [test_videocontrols_error.html]
 [test_videocontrols_orientation.html]
-run-if = toolkit == 'android'
\ No newline at end of file
+run-if = toolkit == 'android'
--- a/toolkit/content/tests/widgets/test_videocontrols_orientation.html
+++ b/toolkit/content/tests/widgets/test_videocontrols_orientation.html
@@ -17,37 +17,36 @@
 <script class="testbody" type="text/javascript">
 
 SimpleTest.waitForExplicitFinish();
 var video = document.getElementById("video");
 
 let onLoaded = event => {
   SpecialPowers.pushPrefEnv(
     {"set": [["full-screen-api.allow-trusted-requests-only", false],
-             ["full-screen-api.unprefix.enabled", true],
              ["media.videocontrols.lock-video-orientation", true]]},
     startMediaLoad);
 }
 window.addEventListener("load", onLoaded);
 
 let startMediaLoad = () => {
   // Kick off test once video has loaded, in its canplaythrough event handler.
   video.src = "video.ogg";
   video.addEventListener("canplaythrough", runTest);
 }
 
 function runTest() {
-  is(document.fullscreenElement, null, "should not be in fullscreen initially");
+  is(document.mozFullScreenElement, null, "should not be in fullscreen initially");
   isnot(window.screen.orientation.type, "landscape-primary", "should not be in landscape");
   isnot(window.screen.orientation.type, "landscape-secondary", "should not be in landscape");
 
   let originalOnChange = window.screen.orientation.onchange;
 
   window.screen.orientation.onchange = () => {
-    is(document.fullscreenElement, video);
+    is(document.mozFullScreenElement, video, "should be in fullscreen");
     ok(window.screen.orientation.type === "landscape-primary" ||
        window.screen.orientation.type === "landscape-secondary", "should be in landscape");
 
     window.screen.orientation.onchange = () => {
       window.screen.orientation.onchange = originalOnChange;
       isnot(window.screen.orientation.type, "landscape-primary", "should not be in landscape");
       isnot(window.screen.orientation.type, "landscape-secondary", "should not be in landscape");
       SimpleTest.finish();
old mode 100644
new mode 100755
--- a/toolkit/locales/en-US/chrome/global/aboutTelemetry.properties
+++ b/toolkit/locales/en-US/chrome/global/aboutTelemetry.properties
@@ -42,32 +42,33 @@ currentPing = current
 # Used as a tooltip for the "current" ping title in the sidebar
 currentPingSidebar = current ping
 
 # Note to translators:
 # - %1$S will be replaced by the current text in the search input
 resultsForSearch = Results for ā€œ%1$Sā€
 
 # Note to translators:
-# - %1$S will be replaced by the section name from the structure of the ping. More info about it can be found here : http://gecko.readthedocs.io/en/latest/toolkit/components/telemetry/telemetry/data/main-ping.html
+# - %1$S will be replaced by the section name from the structure of the ping. More info about it can be found here : https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/data/main-ping.html
 # - %2$S will be replaced by the current text in the search input
 noSearchResults = Sorry! There are no results in %1$S for ā€œ%2$Sā€
 
 telemetryPingTypeAll = all
 
 telemetryLogTitle = Telemetry Log
 
 telemetryLogHeadingId = Id
 
 telemetryLogHeadingTimestamp = Timestamp
 
 telemetryLogHeadingData = Data
 
 # Note to translators:
-# - %1$S will be replaced by the section name from the structure of the ping. More info about it can be found here : http://gecko.readthedocs.io/en/latest/toolkit/components/telemetry/telemetry/data/main-ping.html
+# - %1$S will be replaced by the section name from the structure of the ping. More info about it can be found here : https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/data/main-ping.html
+
 filterPlaceholder = Find in %1$S
 
 allSections = all sections
 
 slowSqlMain = Slow SQL Statements on Main Thread
 
 slowSqlOther = Slow SQL Statements on Helper Threads
 
--- a/tools/lint/eslint/eslint-plugin-mozilla/README.md
+++ b/tools/lint/eslint/eslint-plugin-mozilla/README.md
@@ -24,17 +24,17 @@ Install ESLint [ESLint](http://eslint.or
 Next, install `eslint-plugin-mozilla`:
 
 ```
 $ npm install eslint-plugin-mozilla --save-dev
 ```
 
 ## Documentation
 
-For details about the rules, please see the [gecko documentation page](http://gecko.readthedocs.io/en/latest/tools/lint/linters/eslint-plugin-mozilla.html).
+For details about the rules, please see the [firefox documentation page](http://firefox-source-docs.mozilla.org/tools/lint/linters/eslint-plugin-mozilla.html).
 
 ## Source Code
 
 The sources can be found at:
 
 * Code: https://dxr.mozilla.org/mozilla-central/source/tools/lint/eslint/eslint-plugin-mozilla
 * Documentation: https://dxr.mozilla.org/mozilla-central/source/tools/lint/docs/linters
 
--- a/tools/lint/eslint/eslint-plugin-mozilla/package.json
+++ b/tools/lint/eslint/eslint-plugin-mozilla/package.json
@@ -7,17 +7,17 @@
     "eslintplugin",
     "eslint-plugin",
     "mozilla",
     "firefox"
   ],
   "bugs": {
     "url": "https://bugzilla.mozilla.org/enter_bug.cgi?product=Testing&component=Lint"
   },
-  "homepage": "http://gecko.readthedocs.io/en/latest/tools/lint/linters/eslint-plugin-mozilla.html",
+  "homepage": "http://firefox-source-docs.mozilla.org/tools/lint/linters/eslint-plugin-mozilla.html",
   "repository": {
     "type": "hg",
     "url": "https://hg.mozilla.org/mozilla-central/"
   },
   "author": "Mike Ratcliffe",
   "main": "lib/index.js",
   "dependencies": {
     "escope": "3.6.0",
--- a/tools/lint/eslint/eslint-plugin-spidermonkey-js/package.json
+++ b/tools/lint/eslint/eslint-plugin-spidermonkey-js/package.json
@@ -7,17 +7,17 @@
     "eslintplugin",
     "eslint-plugin",
     "mozilla",
     "spidermonkey"
   ],
   "bugs": {
     "url": "https://bugzilla.mozilla.org/enter_bug.cgi?product=Testing&component=Lint"
   },
-  "homepage": "http://gecko.readthedocs.io/en/latest/tools/lint/linters/eslint-plugin-spidermonkey-js.html",
+  "homepage": "http://firefox-source-docs.mozilla.org/tools/lint/linters/eslint-plugin-spidermonkey-js.html",
   "repository": {
     "type": "hg",
     "url": "https://hg.mozilla.org/mozilla-central/"
   },
   "author": "Mozilla",
   "main": "lib/index.js",
   "dependencies": {
   },
--- a/xpcom/base/StaticPtr.h
+++ b/xpcom/base/StaticPtr.h
@@ -269,9 +269,17 @@ RefPtr<T>::RefPtr(const mozilla::StaticR
 
 template<class T> template<class U>
 RefPtr<T>&
 RefPtr<T>::operator=(const mozilla::StaticRefPtr<U>& aOther)
 {
   return operator=(aOther.get());
 }
 
+template <class T>
+inline already_AddRefed<T>
+do_AddRef(const mozilla::StaticRefPtr<T>& aObj)
+{
+  RefPtr<T> ref(aObj);
+  return ref.forget();
+}
+
 #endif
--- a/xpcom/base/nsIWeakReferenceUtils.h
+++ b/xpcom/base/nsIWeakReferenceUtils.h
@@ -37,30 +37,38 @@ do_QueryReferent(nsIWeakReference* aRawP
 }
 
 
 /**
  * Deprecated, use |do_GetWeakReference| instead.
  */
 extern nsIWeakReference* NS_GetWeakReference(nsISupports*,
                                              nsresult* aResult = 0);
+extern nsIWeakReference* NS_GetWeakReference(nsISupportsWeakReference*,
+                                             nsresult* aResult = 0);
 
 /**
  * |do_GetWeakReference| is a convenience function that bundles up all the work needed
  * to get a weak reference to an arbitrary object, i.e., the |QueryInterface|, test, and
  * call through to |GetWeakReference|, and put it into your |nsCOMPtr|.
  * It is specifically designed to cooperate with |nsCOMPtr| (or |nsWeakPtr|) like so:
  * |nsWeakPtr myWeakPtr = do_GetWeakReference(aPtr);|.
  */
 inline already_AddRefed<nsIWeakReference>
 do_GetWeakReference(nsISupports* aRawPtr, nsresult* aError = 0)
 {
   return dont_AddRef(NS_GetWeakReference(aRawPtr, aError));
 }
 
+inline already_AddRefed<nsIWeakReference>
+do_GetWeakReference(nsISupportsWeakReference* aRawPtr, nsresult* aError = 0)
+{
+  return dont_AddRef(NS_GetWeakReference(aRawPtr, aError));
+}
+
 inline void
 do_GetWeakReference(nsIWeakReference* aRawPtr, nsresult* aError = 0)
 {
   // This signature exists solely to _stop_ you from doing a bad thing.
   //  Saying |do_GetWeakReference()| on a weak reference itself,
   //  is very likely to be a programmer error.
 }
 
--- a/xpcom/base/nsWeakReference.cpp
+++ b/xpcom/base/nsWeakReference.cpp
@@ -62,16 +62,36 @@ nsQueryReferent::operator()(const nsIID&
   }
 
   if (mErrorPtr) {
     *mErrorPtr = status;
   }
   return status;
 }
 
+nsIWeakReference*
+NS_GetWeakReference(nsISupportsWeakReference* aInstancePtr, nsresult* aErrorPtr)
+{
+  nsresult status;
+
+  nsIWeakReference* result = nullptr;
+
+  if (aInstancePtr) {
+    status = aInstancePtr->GetWeakReference(&result);
+  } else {
+    status = NS_ERROR_NULL_POINTER;
+  }
+
+  if (aErrorPtr) {
+    *aErrorPtr = status;
+  }
+
+  return result;
+}
+
 nsIWeakReference*  // or else |already_AddRefed<nsIWeakReference>|
 NS_GetWeakReference(nsISupports* aInstancePtr, nsresult* aErrorPtr)
 {
   nsresult status;
 
   nsIWeakReference* result = nullptr;
 
   if (aInstancePtr) {