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 659873 c959327c6b75cd4930a6ea087583c38b805e7524
parent 659863 c6e59f1b2e2720376a94d30ebabf9fcc60e4f87e (current diff)
parent 659872 a4252412b1ac3b90d0845e7c8af5f8231d4e8bce (diff)
child 659874 4b165c013d7faed8bc91de55e805d9567406e908
child 659879 2294bc12f299449b1592810699f4d032e771297b
child 659908 b38fde90b1c805d791cad6cb3de755c4155a661b
child 659920 e7142d7e10a2786a1d4090742f3226f392f92a06
child 659927 22b07ee426badaf05c7f62dc69159fc2e6ce803c
child 659932 771fa1d0dafd75d130dcebdbd665eb8b6bbca929
child 659951 12c8d773a391673e6f1583ff4bf3eebcb8e71675
child 659971 6b52d63bd9a6b090ba3f4edc2670909fea8c0dc1
child 659972 432b763de164040b54122943df53922a9c84ac23
child 659976 0f2cf39eb3e76128827028ae81cc808826ea9f02
child 659978 088af1f29ce960cf7f285e1c4b9b8ee3ae4eb635
child 659980 529bf8324110d215198808583c8dd510706854d2
child 659987 2e02e0a809d08ff26291a027b73a54668d6d5f9d
child 659988 d987abd79a4d7c712733ff5783bc25a863c13ad2
child 659995 54af3eb6e08b07e8d88dbe9036a72812ae24d47a
child 659998 9548eb2a6e2ef0b189703ec8752bdb9631d94867
child 659999 3aa028a47b5d0e7f72e838d898e6c7b9c2353a0c
child 660008 eb2facf35130f8b3805fafdb16087cf807471ae7
child 660009 df5387e002bef42f1f5d3af26bb52fad4f3a47c4
child 660051 be7483db711c1eae24d38194ac4b089c393f0def
child 660055 3d64bae6dd4006dc3dfc30befa7d3517a6073339
child 660075 21229f14023fd62a4acaf63ab16b3f12f58e722d
child 660115 1349ddcac55fc7bf7e02ff410e6d49d1c03facb3
child 660155 4b2af5da06148860f4c2134efdfbee3274ab57e4
child 660165 10de9a38b713646e293ab0b5dbc4fb7e31ac5efe
child 660171 a0a402fbc1305853beb476c0996fcca008371315
child 660175 374eb24b0c56a16ab47611717a00a1b248535a47
child 660180 83a31ba6e2e865dbcd39a8733c707b4f159a53bd
child 660184 db4de2901a7a053e2561bb9dfbee9f6eb4aaa20b
child 660192 34dc4e9ed00ae0ad6be8d048e8e07d4a8f86f4a3
child 660194 225332c9d3405351bd2ddda4dcf646108f0d820c
child 660198 3b3084cda48f5626b6359fc20a622506d89a6de4
child 660199 1e5f4a54b26575e2f6e39a75c781a16b8cba9b32
child 660200 fa828fa5910270a7410e10ef4efc213ac666c7cf
child 660204 79690b555940900b3befad4a0f9142c4891e6e35
child 660206 a48bdb9bd35e8198a7b4e1896ea1aa01952117f0
child 660207 59255da13844ea2da327397e5037ae19d4c47b90
child 660214 f7ee0500c8b2fab1e3fcd704556311d930a0cffd
child 660216 15231580eba48e16431d61dcb26650e4195474c4
child 660217 e4b3aeef53f33c2a91da9a517805a221d991142f
child 660258 94c02703f07c931bfb9796611403859b07c3a2c0
child 660270 58dcf7c84a22c61cf6c4d84450e446196d07962c
child 660276 c132aedbd264a329e6846649296fa620b1100cc8
child 660278 34398e433088ee1e76c72313869dddbdfd5ff8a7
child 660280 48928972c54e1b7ebaa811432689bfaf7aebfe35
child 660291 661af95cb353c0893ec74f9cbefdfa0259f7ac05
child 660308 269108a15c4543b2659e0ccd994099f050e1483a
child 660310 7a870aca1137179a4f24a4e45eb14349c7c47bb5
child 660314 1676e654729a8aff125b81b9b55bbf9e80a97fb8
child 660317 cce9dfd4a073acfe5ea475252adb56439ce537c0
child 660318 436ac51ee930e79bd54cb86135be7c8152d27227
child 660319 74b9f2c9399dbf0d1f5f133130bfb74a06827af3
child 660334 2c80020ed7af4067f8d119e8270371e817f95e4c
child 660335 9bb5069fe9c0f324a70826f60b5f2bcb94ccd4bf
child 660412 9da3a0e54eee784e724d397cdeafbc2b3aebbf82
child 660415 e97237bdf2d799e9788b54c0379bd1b2a15d0546
child 660417 84d3c2e49650dca8468b8abf1c0ccae4873fbbad
child 660420 2820ac7f60c2564d850eb983c10bbbf8a7162558
child 660424 a098c48fae4cdbc92926a1e3b1f1508dc92edd59
child 660427 5393c21a4ca0ad487d494c74bc9e251c9b248a53
child 660429 747aa319278946ac7a061c1a7ffacbeb57fcb510
child 660444 20939561e6fccfb81962cbbeacc3bf5a770d0e9c
child 660570 cc4195571b1ece28ec22b41f37df87c66e53f785
child 660581 da5154b2c49ae7b735887772374cfdf209bffb66
child 660594 c40c4384f807b695e7f9c75046bc03a37e469213
child 660595 8967ac61276c8787a79918ac888ec1aa8c3d4162
child 660798 883976a12a567a82ede466b9512a144ab5cef002
child 660808 49c4b10991f3de894806f4f2bac7e1fd324c8683
child 660875 62b8323af8e18fb72185771e1eaa8d86f8d82ccb
child 660909 891a55adf77dd74c94868d1bf40c76e6a11b5660
child 661219 b7d8dd78c07d6de7d8a4aa6f27e7218ed10c60ec
child 661244 7f3d7e642060fef4ecec73333624c3765e8edcda
child 661499 9c2417b870017ae8e6e1b86cce36ee3cc7d97edd
child 661542 5d6b546fc843b55746b89b3a3ea30da37ee25b4d
child 661547 5dcd69f358b153144ebc5b83b8f9f25a8e1fe258
child 661752 9fa4627cc4ac6ce97286e866eefb6bf93f70cfb8
child 662053 631915646fa885ce1aecf04d9b930a793d9ac040
child 663924 48ccc67400dac5d6b34e586df5b25126f0dfa9aa
child 667056 83b224667e81fba2c3dc53fcdb319d838a4c0ac5
child 667057 4befe71b082cd9755bc7a77068e4db4ef6e5c765
push id78224
push useralwu@mozilla.com
push dateWed, 06 Sep 2017 10:19:09 +0000
reviewersmerge, merge
milestone57.0a1
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) {