Merge inbound to mozilla-central. a=merge
authorCiure Andrei <aciure@mozilla.com>
Tue, 18 Sep 2018 10:42:35 +0300
changeset 492639 85b4d2bf888a
parent 492624 30f9c0bd088b (current diff)
parent 492638 930f94ff8388 (diff)
child 492663 81ee0f886558
child 492688 7a2270f05923
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone64.0a1
first release with
nightly linux32
85b4d2bf888a / 64.0a1 / 20180918075510 / files
nightly linux64
85b4d2bf888a / 64.0a1 / 20180918075510 / files
nightly mac
85b4d2bf888a / 64.0a1 / 20180918075510 / files
nightly win32
85b4d2bf888a / 64.0a1 / 20180918075510 / files
nightly win64
85b4d2bf888a / 64.0a1 / 20180918075510 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -60,16 +60,17 @@
 #include "nsAtom.h"
 #include "nsIURI.h"
 #include "nsArrayUtils.h"
 #include "nsIMutableArray.h"
 #include "nsIObserverService.h"
 #include "nsIServiceManager.h"
 #include "nsWhitespaceTokenizer.h"
 #include "nsAttrName.h"
+#include "nsPersistentProperties.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/MouseEvents.h"
@@ -1014,18 +1015,17 @@ Accessible::Attributes()
   }
 
   return attributes.forget();
 }
 
 already_AddRefed<nsIPersistentProperties>
 Accessible::NativeAttributes()
 {
-  nsCOMPtr<nsIPersistentProperties> attributes =
-    do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
+  RefPtr<nsPersistentProperties> attributes = new nsPersistentProperties();
 
   nsAutoString unused;
 
   // We support values, so expose the string value as well, via the valuetext
   // object attribute. We test for the value interface because we don't want
   // to expose traditional Value() information such as URL's on links and
   // documents, or text in an input.
   if (HasNumericValue()) {
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -20,17 +20,17 @@
 #include "nsCaret.h"
 #include "nsContentUtils.h"
 #include "nsFocusManager.h"
 #include "nsIEditingSession.h"
 #include "nsContainerFrame.h"
 #include "nsFrameSelection.h"
 #include "nsILineIterator.h"
 #include "nsIInterfaceRequestorUtils.h"
-#include "nsIPersistentProperties2.h"
+#include "nsPersistentProperties.h"
 #include "nsIScrollableFrame.h"
 #include "nsIServiceManager.h"
 #include "nsITextControlElement.h"
 #include "nsIMathMLFrame.h"
 #include "nsRange.h"
 #include "nsTextFragment.h"
 #include "mozilla/BinarySearch.h"
 #include "mozilla/dom/Element.h"
@@ -875,18 +875,17 @@ HyperTextAccessible::TextAttributes(bool
 
   *aStartOffset = *aEndOffset = 0;
   index_t offset = ConvertMagicOffset(aOffset);
   if (!offset.IsValid() || offset > CharacterCount()) {
     NS_ERROR("Wrong in offset!");
     return nullptr;
   }
 
-  nsCOMPtr<nsIPersistentProperties> attributes =
-    do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
+  RefPtr<nsPersistentProperties> attributes = new nsPersistentProperties();
 
   Accessible* accAtOffset = GetChildAtOffset(offset);
   if (!accAtOffset) {
     // Offset 0 is correct offset when accessible has empty text. Include
     // default attributes if they were requested, otherwise return empty set.
     if (offset == 0) {
       if (aIncludeDefAttrs) {
         TextAttrsMgr textAttrsMgr(this);
@@ -920,18 +919,17 @@ HyperTextAccessible::TextAttributes(bool
   *aStartOffset = startOffset;
   *aEndOffset = endOffset;
   return attributes.forget();
 }
 
 already_AddRefed<nsIPersistentProperties>
 HyperTextAccessible::DefaultTextAttributes()
 {
-  nsCOMPtr<nsIPersistentProperties> attributes =
-    do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
+  RefPtr<nsPersistentProperties> attributes = new nsPersistentProperties();
 
   TextAttrsMgr textAttrsMgr(this);
   textAttrsMgr.GetAttributes(attributes);
   return attributes.forget();
 }
 
 int32_t
 HyperTextAccessible::GetLevelInternal()
--- a/accessible/windows/msaa/ApplicationAccessibleWrap.cpp
+++ b/accessible/windows/msaa/ApplicationAccessibleWrap.cpp
@@ -6,33 +6,32 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ApplicationAccessibleWrap.h"
 
 #include "AccessibleApplication_i.c"
 #include "IUnknownImpl.h"
 
 #include "nsIGfxInfo.h"
-#include "nsIPersistentProperties2.h"
+#include "nsPersistentProperties.h"
 #include "nsServiceManagerUtils.h"
 #include "mozilla/Services.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 NS_IMPL_ISUPPORTS_INHERITED0(ApplicationAccessibleWrap,
                              ApplicationAccessible)
 
 already_AddRefed<nsIPersistentProperties>
 ApplicationAccessibleWrap::NativeAttributes()
 {
-  nsCOMPtr<nsIPersistentProperties> attributes =
-    do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
+  RefPtr<nsPersistentProperties> attributes = new nsPersistentProperties();
 
   nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
   if (gfxInfo) {
     bool isD2DEnabled = false;
     gfxInfo->GetD2DEnabled(&isD2DEnabled);
     nsAutoString unused;
     attributes->SetStringProperty(
       NS_LITERAL_CSTRING("D2D"),
--- a/accessible/xpcom/xpcAccessible.cpp
+++ b/accessible/xpcom/xpcAccessible.cpp
@@ -11,17 +11,17 @@
 #include "nsIAccessibleRole.h"
 #include "nsAccessibleRelation.h"
 #include "Relation.h"
 #include "Role.h"
 #include "RootAccessible.h"
 #include "xpcAccessibleDocument.h"
 
 #include "nsIMutableArray.h"
-#include "nsIPersistentProperties2.h"
+#include "nsPersistentProperties.h"
 
 using namespace mozilla::a11y;
 
 NS_IMETHODIMP
 xpcAccessible::GetParent(nsIAccessible** aParent)
 {
   NS_ENSURE_ARG_POINTER(aParent);
   *aParent = nullptr;
@@ -411,18 +411,17 @@ xpcAccessible::GetAttributes(nsIPersiste
     attributes.swap(*aAttributes);
     return NS_OK;
   }
 
   ProxyAccessible* proxy = IntlGeneric().AsProxy();
   AutoTArray<Attribute, 10> attrs;
   proxy->Attributes(&attrs);
 
-  nsCOMPtr<nsIPersistentProperties> props =
-    do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
+  RefPtr<nsPersistentProperties> props = new nsPersistentProperties();
   uint32_t attrCount = attrs.Length();
   nsAutoString unused;
   for (uint32_t i = 0; i < attrCount; i++) {
     props->SetStringProperty(attrs[i].Name(), attrs[i].Value(), unused);
   }
 
   props.forget(aAttributes);
   return NS_OK;
--- a/accessible/xul/XULTreeGridAccessible.cpp
+++ b/accessible/xul/XULTreeGridAccessible.cpp
@@ -13,17 +13,17 @@
 #include "Relation.h"
 #include "Role.h"
 #include "States.h"
 #include "nsQueryObject.h"
 #include "nsTreeColumns.h"
 
 #include "nsIBoxObject.h"
 #include "nsIMutableArray.h"
-#include "nsIPersistentProperties2.h"
+#include "nsPersistentProperties.h"
 #include "nsITreeSelection.h"
 #include "nsComponentManagerUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/TreeColumnBinding.h"
 
 using namespace mozilla::a11y;
 using namespace mozilla;
 
@@ -641,18 +641,17 @@ XULTreeGridCellAccessible::Selected()
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeGridCellAccessible: Accessible public implementation
 
 already_AddRefed<nsIPersistentProperties>
 XULTreeGridCellAccessible::NativeAttributes()
 {
-  nsCOMPtr<nsIPersistentProperties> attributes =
-    do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
+  RefPtr<nsPersistentProperties> attributes = new nsPersistentProperties();
 
   // "table-cell-index" attribute
   TableAccessible* table = Table();
   if (!table)
     return attributes.forget();
 
   nsAutoString stringIdx;
   stringIdx.AppendInt(table->CellIndexAt(mRow, ColIdx()));
--- a/docshell/base/LoadContext.cpp
+++ b/docshell/base/LoadContext.cpp
@@ -196,39 +196,32 @@ LoadContext::GetInterface(const nsIID& a
     *aResult = static_cast<nsILoadContext*>(this);
     NS_ADDREF_THIS();
     return NS_OK;
   }
 
   return NS_NOINTERFACE;
 }
 
-static nsresult
-CreateTestInstance(bool aPrivate, nsISupports *aOuter, REFNSIID aIID, void **aResult)
+static already_AddRefed<nsILoadContext>
+CreateInstance(bool aPrivate)
 {
-  // Shamelessly modified from NS_GENERIC_FACTORY_CONSTRUCTOR
-  *aResult = nullptr;
-
-  if (aOuter) {
-    return NS_ERROR_NO_AGGREGATION;
-  }
-
   OriginAttributes oa;
   oa.mPrivateBrowsingId = aPrivate ? 1 : 0;
 
-  RefPtr<LoadContext> lc = new LoadContext(oa);
+  nsCOMPtr<nsILoadContext> lc = new LoadContext(oa);
 
-  return lc->QueryInterface(aIID, aResult);
+  return lc.forget();
 }
 
-nsresult
-CreateTestLoadContext(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+already_AddRefed<nsILoadContext>
+CreateLoadContext()
 {
-  return CreateTestInstance(false, aOuter, aIID, aResult);
+  return CreateInstance(false);
 }
 
-nsresult
-CreatePrivateTestLoadContext(nsISupports *aOuter, REFNSIID aIID, void **aResult)
+already_AddRefed<nsILoadContext>
+CreatePrivateLoadContext()
 {
-  return CreateTestInstance(true, aOuter, aIID, aResult);
+  return CreateInstance(true);
 }
 
 } // namespace mozilla
--- a/docshell/base/LoadContext.h
+++ b/docshell/base/LoadContext.h
@@ -117,14 +117,14 @@ private:
   bool mUseRemoteTabs;
   bool mUseTrackingProtection;
   OriginAttributes mOriginAttributes;
 #ifdef DEBUG
   bool mIsNotNull;
 #endif
 };
 
-nsresult CreateTestLoadContext(nsISupports *aOuter, REFNSIID aIID, void **aResult);
-nsresult CreatePrivateTestLoadContext(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+already_AddRefed<nsILoadContext> CreateLoadContext();
+already_AddRefed<nsILoadContext> CreatePrivateLoadContext();
 
 } // namespace mozilla
 
 #endif // LoadContext_h
--- a/docshell/build/nsDocShellCID.h
+++ b/docshell/build/nsDocShellCID.h
@@ -71,21 +71,9 @@
  * An observer service topic that can be listened to to catch destruction
  * of chrome browsing areas (both toplevel ones and subframes).  The
  * subject of the notification will be the nsIWebNavigation being
  * destroyed.  At this time the additional data wstring is not defined
  * to be anything in particular.
  */
 #define NS_CHROME_WEBNAVIGATION_DESTROY "chrome-webnavigation-destroy"
 
-/**
- * A way to create nsILoadContexts from script
- */
-#define NS_LOADCONTEXT_CONTRACTID "@mozilla.org/loadcontext;1"
-#define NS_LOADCONTEXT_CID \
-    { 0xd0181d36, 0x19a2, 0x4347, \
-      { 0x8f, 0x00, 0x04, 0x13, 0xa0, 0x70, 0xaa, 0xdc } }
-#define NS_PRIVATELOADCONTEXT_CONTRACTID "@mozilla.org/privateloadcontext;1"
-#define NS_PRIVATELOADCONTEXT_CID \
-    { 0x01629810, 0xd8ae, 0x4455, \
-      { 0x86, 0xe8, 0x69, 0x68, 0x87, 0xd1, 0xf7, 0x8d } }
-
 #endif // nsDocShellCID_h__
--- a/docshell/build/nsDocShellModule.cpp
+++ b/docshell/build/nsDocShellModule.cpp
@@ -32,19 +32,16 @@
 #include "nsExternalURLHandlerService.h"
 #endif
 
 // session history
 #include "nsSHEntry.h"
 #include "nsSHEntryShared.h"
 #include "nsSHistory.h"
 
-// LoadContexts (used for testing)
-#include "LoadContext.h"
-
 using mozilla::dom::ContentHandlerService;
 
 static bool gInitialized = false;
 
 // The one time initialization for this module
 static nsresult
 Initialize()
 {
@@ -112,18 +109,16 @@ NS_DEFINE_NAMED_CID(NS_OSPERMISSIONREQUE
 #ifdef MOZ_ENABLE_DBUS
 NS_DEFINE_NAMED_CID(NS_DBUSHANDLERAPP_CID);
 #endif
 #if defined(MOZ_WIDGET_ANDROID)
 NS_DEFINE_NAMED_CID(NS_EXTERNALURLHANDLERSERVICE_CID);
 #endif
 NS_DEFINE_NAMED_CID(NS_SHENTRY_CID);
 NS_DEFINE_NAMED_CID(NS_CONTENTHANDLERSERVICE_CID);
-NS_DEFINE_NAMED_CID(NS_LOADCONTEXT_CID);
-NS_DEFINE_NAMED_CID(NS_PRIVATELOADCONTEXT_CID);
 
 const mozilla::Module::CIDEntry kDocShellCIDs[] = {
   { &kNS_DOCSHELL_CID, false, nullptr, nsDocShellConstructor },
   { &kNS_DEFAULTURIFIXUP_CID, false, nullptr, nsDefaultURIFixupConstructor },
   { &kNS_WEBNAVIGATION_INFO_CID, false, nullptr, nsWebNavigationInfoConstructor },
   { &kNS_ABOUT_REDIRECTOR_MODULE_CID, false, nullptr, nsAboutRedirector::Create },
   { &kNS_URI_LOADER_CID, false, nullptr, nsURILoaderConstructor },
   { &kNS_DOCUMENTLOADER_SERVICE_CID, false, nullptr, nsDocLoaderConstructor },
@@ -137,18 +132,16 @@ const mozilla::Module::CIDEntry kDocShel
   { &kNS_LOCALHANDLERAPP_CID, false, nullptr, PlatformLocalHandlerApp_tConstructor },
 #ifdef MOZ_ENABLE_DBUS
   { &kNS_DBUSHANDLERAPP_CID, false, nullptr, nsDBusHandlerAppConstructor },
 #endif
 #if defined(MOZ_WIDGET_ANDROID)
   { &kNS_EXTERNALURLHANDLERSERVICE_CID, false, nullptr, nsExternalURLHandlerServiceConstructor },
 #endif
   { &kNS_SHENTRY_CID, false, nullptr, nsSHEntryConstructor },
-  { &kNS_LOADCONTEXT_CID, false, nullptr, mozilla::CreateTestLoadContext },
-  { &kNS_PRIVATELOADCONTEXT_CID, false, nullptr, mozilla::CreatePrivateTestLoadContext },
   { nullptr }
 };
 
 const mozilla::Module::ContractIDEntry kDocShellContracts[] = {
   { "@mozilla.org/docshell;1", &kNS_DOCSHELL_CID },
   { NS_URIFIXUP_CONTRACTID, &kNS_DEFAULTURIFIXUP_CID },
   { NS_WEBNAVIGATION_INFO_CONTRACTID, &kNS_WEBNAVIGATION_INFO_CID },
   { NS_ABOUT_MODULE_CONTRACTID_PREFIX "about", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
@@ -192,18 +185,16 @@ const mozilla::Module::ContractIDEntry k
   { NS_LOCALHANDLERAPP_CONTRACTID, &kNS_LOCALHANDLERAPP_CID },
 #ifdef MOZ_ENABLE_DBUS
   { NS_DBUSHANDLERAPP_CONTRACTID, &kNS_DBUSHANDLERAPP_CID },
 #endif
 #if defined(MOZ_WIDGET_ANDROID)
   { NS_EXTERNALURLHANDLERSERVICE_CONTRACTID, &kNS_EXTERNALURLHANDLERSERVICE_CID },
 #endif
   { NS_SHENTRY_CONTRACTID, &kNS_SHENTRY_CID },
-  { NS_LOADCONTEXT_CONTRACTID, &kNS_LOADCONTEXT_CID },
-  { NS_PRIVATELOADCONTEXT_CONTRACTID, &kNS_PRIVATELOADCONTEXT_CID },
   { NS_OSPERMISSIONREQUEST_CONTRACTID, &kNS_OSPERMISSIONREQUEST_CID, mozilla::Module::MAIN_PROCESS_ONLY },
   { nullptr }
 };
 
 static const mozilla::Module kDocShellModule = {
   mozilla::Module::kVersion,
   kDocShellCIDs,
   kDocShellContracts,
new file mode 100644
--- /dev/null
+++ b/gfx/docs/OffMainThreadPainting.rst
@@ -0,0 +1,237 @@
+Off Main Thread Painting
+========================
+
+OMTP, or ‘off main thread painting’, is the component of Gecko that
+allows us to perform painting of web content off of the main thread.
+This gives us more time on the main thread for javascript, layout,
+display list building, and other tasks which allows us to increase our
+responsiveness.
+
+Take a look at this `blog
+post <https://mozillagfx.wordpress.com/2017/12/05/off-main-thread-painting/>`__
+for an introduction.
+
+Background
+----------
+
+Painting (or rasterization) is the last operation that happens in a
+layer transaction before we forward it to the compositor. At this point,
+all display items have been assigned to a layer and invalid regions have
+been calculated and assigned to each layer.
+
+The painted layer uses a content client to acquire a buffer for
+painting. The main purpose of the content client is to allow us to
+retain already painted content when we are scrolling a layer. We have
+two main strategies for this, rotated buffer and tiling.
+
+This is implemented with two class hierarchies. ``ContentClient`` for
+rotated buffer and ``TiledContentClient`` for tiling. Additionally we
+have two different painted layer implementations, ``ClientPaintedLayer``
+and ``ClientTiledPaintedLayer``.
+
+The main distinction between rotated buffer and tiling is the amount of
+graphics surfaces required. Rotated buffer utilizes just a single buffer
+for a frame but potentially requires painting into it multiple times.
+Tiling uses multiple buffers but doesn’t require painting into the
+buffers multiple times.
+
+Once the painted layer has a surface (or surfaces with tiling) to paint
+into, they are wrapped in a ``DrawTarget`` of some form and a callback
+to ``FrameLayerBuilder`` is called. This callback uses the assigned
+display items and invalid regions to trigger rasterization. Each
+``nsDisplayItem`` has their ``Paint`` method called with the provided
+``DrawTarget`` that represents the surface, and they paint into it.
+
+High level
+----------
+
+The key abstraction that allows us to paint off of the main thread is
+``DrawTargetCapture`` [1]_. ``DrawTargetCapture`` is a special
+``DrawTarget`` which records all draw commands for replaying to another
+draw target in the local process. This is similar to
+``DrawTargetRecording``, but only holds a reference to resources instead
+of copying them into the command stream. This allows the command stream
+to be much more lightweight than ``DrawTargetRecording``.
+
+OMTP works by instrumenting the content clients to use a capture target
+for all painting [2]_ [3]_ [4]_ [5]_. This capture draw target records all
+the operations that would normally be performed directly on the
+surface’s draw target. Once we have all of the commands, we send the
+capture and surface draw target to the ``PaintThread`` [6]_ where the
+commands are replayed onto the surface. Once the rasterization is done,
+we forward the layer transaction to the compositor.
+
+Tiling and parallel painting
+----------------------------
+
+We can make one additional improvement if we are using tiling as our
+content client backend.
+
+When we are tiling, the screen is subdivided into a grid of equally
+sized surfaces and draw commands are performed on the tiles they affect.
+Each tile is independent of the others, so we’re able to parallelize
+painting by using a worker thread pool and dispatching a task for each
+tile individually.
+
+This is commonly referred to as P-OMTP or parallel painting.
+
+Main thread rasterization
+-------------------------
+
+Even with OMTP it’s still possible for the main thread to perform
+rasterization. A common pattern for painting code is to create a
+temporary draw target, perform drawing with it, take a snapshot, and
+then draw the snapshot onto the main draw target. This is done for
+blurs, box shadows, text shadows, and with the basic layer manager
+fallback.
+
+If the temporary draw target is not a draw target capture, then this
+will perform rasterization on the main thread. This can be bad as it
+lowers our parallelism and can cause contention with content backends,
+like Direct2D, that use locking around shared resources.
+
+To work around this, we changed the main thread painting code to use a
+draw target capture for these operations and added a source surface
+capture [7]_ which only resolves the painting of the draw commands when
+needed on the paint thread.
+
+There are still possible cases we can perform main thread rasterization,
+but we try and address them when they come up.
+
+Out of memory issues
+--------------------
+
+The web is very complex, and so we can sometimes have a large amount of
+draw commands for a content paint. We’ve observed OOM errors for capture
+command lists that have grown to be 200MiB large.
+
+We initially tried to mitigate this by lowering the overhead of capture
+command lists. We do this by filtering commands that don’t actually
+change the draw target state and folding consecutive transform changes,
+but that was not always enough. So we added the ability for our draw
+target capture’s to flush their command lists to the surface draw target
+while we are capturing on the main thread [8]_.
+
+This is triggered by a configurable memory limit. Because this
+introduces a new source of main thread rasterization we try to balance
+setting this too low and suffering poor performance, or setting this too
+high and suffering crashes.
+
+Synchronization
+---------------
+
+OMTP is conceptually simple, but in practice it relies on subtle code to
+ensure thread safety. This was the most arguably the most difficult part
+of the project.
+
+There are roughly four areas that are critical.
+
+1. Compositor message ordering
+
+   Immediately after we queue the async paints to be asynchronously
+   completed, we have a problem. We need to forward the layer
+   transaction at some point, but the compositor cannot process the
+   transaction until all async paints have finished. If it did, it could
+   access unfinished painted content.
+
+   We obviously can’t block on the async paints completing as that would
+   beat the whole point of OMTP. We also can’t hold off on sending the
+   layer transaction to ``IPDL``, as we’d trigger race conditions for
+   messages sent after the layer transaction is built but before it is
+   forwarded. Reftest and other code assumes that messages sent after a
+   layer transaction to the compositor are processed after that layer
+   transaction is processed.
+
+   The solution is to forward the layer transaction to the compositor
+   over ``IPDL``, but flag the message channel to start postponing
+   messages [9]_. Then once all async paints have completed, we unflag
+   the message channel and all postponed messages are sent [10]_. This
+   allows us to keep our message ordering guarantees and not have to
+   worry about scheduling a runnable in the future.
+
+2. Texture clients
+
+   The backing store for content surfaces is managed by texture client.
+   While async paints are executing, it’s possible for shutdown or any
+   number of things to happen that could cause layer manager, all
+   layers, all content clients, and therefore all texture clients to be
+   destroyed. Therefore it’s important that we keep these texture
+   clients alive throughout async painting. Texture clients also manage
+   IPC resources and must be destroyed on the main thread, so we are
+   careful to do that [11]_.
+
+3. Double buffering
+
+   We currently double buffer our content painting - our content clients
+   only ever have zero or one texture that is available to be painted
+   into at any moment.
+
+   This implies that we cannot start async painting a layer tree while
+   previous async paints are still active as this would lead to awful
+   races. We also don’t support multiple nested sets of postponed IPC
+   messages to allow sending the first layer transaction to the
+   compositor, but not the second.
+
+   To prevent issues with this, we flush all active async paints before
+   we begin to paint a new layer transaction [12]_.
+
+   There was some initial debate about implementing triple buffering for
+   content painting, but we have not seen evidence it would help us
+   significantly.
+
+4. Moz2D thread safety
+
+   Finally, most Moz2D objects were not thread safe. We had to insert
+   special locking into draw target and source surface as they have a
+   special copy on write relationship that must be consistent even if
+   they are on different threads.
+
+   Some platform specific resources like fonts needed locking added in
+   order to be thread safe. We also did some work to make filter nodes
+   work with multiple threads executing them at the same time.
+
+Browser process
+---------------
+
+Currently only content processes are able to use OMTP.
+
+This restriction was added because of concern about message ordering
+between ``APZ`` and OMTP. It might be able to lifted in the future.
+
+Important bugs
+--------------
+
+1. `OMTP Meta <https://bugzilla.mozilla.org/show_bug.cgi?id=omtp>`__
+2. `Enable on
+   Windows <https://bugzilla.mozilla.org/show_bug.cgi?id=1403935>`__
+3. `Enable on
+   OSX <https://bugzilla.mozilla.org/show_bug.cgi?id=1422392>`__
+4. `Enable on
+   Linux <https://bugzilla.mozilla.org/show_bug.cgi?id=1432531>`__
+5. `Parallel
+   painting <https://bugzilla.mozilla.org/show_bug.cgi?id=1425056>`__
+
+Code links
+----------
+
+.. [1]  `DrawTargetCapture <https://searchfox.org/mozilla-central/rev/dd965445ec47fbf3cee566eff93b301666bda0e1/gfx/2d/DrawTargetCapture.h#22>`__
+.. [2]  `Creating DrawTargetCapture for rotated
+    buffer <https://searchfox.org/mozilla-central/rev/dd965445ec47fbf3cee566eff93b301666bda0e1/gfx/layers/client/ContentClient.cpp#185>`__
+.. [3]  `Dispatch DrawTargetCapture for rotated
+    buffer <https://searchfox.org/mozilla-central/rev/dd965445ec47fbf3cee566eff93b301666bda0e1/gfx/layers/client/ClientPaintedLayer.cpp#99>`__
+.. [4]  `Creating DrawTargetCapture for
+    tiling <https://searchfox.org/mozilla-central/rev/dd965445ec47fbf3cee566eff93b301666bda0e1/gfx/layers/client/TiledContentClient.cpp#714>`__
+.. [5]  `Dispatch DrawTargetCapture for
+    tiling <https://searchfox.org/mozilla-central/rev/dd965445ec47fbf3cee566eff93b301666bda0e1/gfx/layers/client/MultiTiledContentClient.cpp#288>`__
+.. [6]  `PaintThread <https://searchfox.org/mozilla-central/rev/dd965445ec47fbf3cee566eff93b301666bda0e1/gfx/layers/PaintThread.h#53>`__
+.. [7]  `SourceSurfaceCapture <https://searchfox.org/mozilla-central/rev/dd965445ec47fbf3cee566eff93b301666bda0e1/gfx/2d/SourceSurfaceCapture.h#19>`__
+.. [8] `Sync flushing draw
+    commands <https://searchfox.org/mozilla-central/rev/dd965445ec47fbf3cee566eff93b301666bda0e1/gfx/2d/DrawTargetCapture.h#165>`__
+.. [9]  `Postponing messages for
+    PCompositorBridge <https://searchfox.org/mozilla-central/rev/dd965445ec47fbf3cee566eff93b301666bda0e1/gfx/layers/ipc/CompositorBridgeChild.cpp#1319>`__
+.. [10]  `Releasing messages for
+    PCompositorBridge <https://searchfox.org/mozilla-central/rev/dd965445ec47fbf3cee566eff93b301666bda0e1/gfx/layers/ipc/CompositorBridgeChild.cpp#1303>`__
+.. [11] `Releasing texture clients on main
+    thread <https://searchfox.org/mozilla-central/rev/dd965445ec47fbf3cee566eff93b301666bda0e1/gfx/layers/ipc/CompositorBridgeChild.cpp#1170>`__
+.. [12] `Flushing async
+    paints <https://searchfox.org/mozilla-central/rev/dd965445ec47fbf3cee566eff93b301666bda0e1/gfx/layers/client/ClientLayerManager.cpp#289>`__
--- a/gfx/docs/index.rst
+++ b/gfx/docs/index.rst
@@ -7,11 +7,12 @@ Mozilla graphics architecture. The desig
 This `wiki page <https://wiki.mozilla.org/Platform/GFX>`__ contains
 information about graphics and the graphics team at Mozilla.
 
 .. toctree::
    :maxdepth: 1
 
    GraphicsOverview
    LayersHistory
+   OffMainThreadPainting
    AsyncPanZoom
    AdvancedLayers
    Silk
--- a/image/RasterImage.cpp
+++ b/image/RasterImage.cpp
@@ -45,16 +45,17 @@
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Tuple.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/gfx/Scale.h"
 
 #include "GeckoProfiler.h"
 #include "gfx2DGlue.h"
 #include "gfxPrefs.h"
+#include "nsProperties.h"
 #include <algorithm>
 
 namespace mozilla {
 
 using namespace gfx;
 using namespace layers;
 
 namespace image {
@@ -1051,20 +1052,17 @@ RasterImage::Get(const char* prop, const
   }
   return mProperties->Get(prop, iid, result);
 }
 
 NS_IMETHODIMP
 RasterImage::Set(const char* prop, nsISupports* value)
 {
   if (!mProperties) {
-    mProperties = do_CreateInstance("@mozilla.org/properties;1");
-  }
-  if (!mProperties) {
-    return NS_ERROR_OUT_OF_MEMORY;
+    mProperties = new nsProperties();
   }
   return mProperties->Set(prop, value);
 }
 
 NS_IMETHODIMP
 RasterImage::Has(const char* prop, bool* _retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
--- a/image/imgRequest.cpp
+++ b/image/imgRequest.cpp
@@ -32,16 +32,17 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsContentUtils.h"
 
 #include "plstr.h" // PL_strcasestr(...)
 #include "prtime.h" // for PR_Now
 #include "nsNetUtil.h"
 #include "nsIProtocolHandler.h"
 #include "imgIRequest.h"
+#include "nsProperties.h"
 
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla;
 using namespace mozilla::image;
 
 #define LOG_TEST(level) (MOZ_LOG_TEST(gImgLog, (level)))
@@ -103,17 +104,17 @@ imgRequest::Init(nsIURI *aURI,
   LOG_FUNC(gImgLog, "imgRequest::Init");
 
   MOZ_ASSERT(!mImage, "Multiple calls to init");
   MOZ_ASSERT(aURI, "No uri");
   MOZ_ASSERT(aFinalURI, "No final uri");
   MOZ_ASSERT(aRequest, "No request");
   MOZ_ASSERT(aChannel, "No channel");
 
-  mProperties = do_CreateInstance("@mozilla.org/properties;1");
+  mProperties = new nsProperties();
   mURI = aURI;
   mFinalURI = aFinalURI;
   mRequest = aRequest;
   mChannel = aChannel;
   mTimedChannel = do_QueryInterface(mChannel);
   mTriggeringPrincipal = aTriggeringPrincipal;
   mCORSMode = aCORSMode;
   mReferrerPolicy = aReferrerPolicy;
--- a/image/test/unit/test_private_channel.js
+++ b/image/test/unit/test_private_channel.js
@@ -10,18 +10,18 @@ load('image_load_helpers.js');
 
 var gHits = 0;
 
 var gIoService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
 var gPublicLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
 var gPrivateLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
 gPrivateLoader.QueryInterface(Ci.imgICache).respectPrivacyNotifications();
 
-var nonPrivateLoadContext = Cc["@mozilla.org/loadcontext;1"].createInstance(Ci.nsILoadContext);
-var privateLoadContext = Cc["@mozilla.org/privateloadcontext;1"].createInstance(Ci.nsILoadContext);
+var nonPrivateLoadContext = Cu.createLoadContext();
+var privateLoadContext = Cu.createPrivateLoadContext();
 
 function imageHandler(metadata, response) {
   gHits++;
   response.setHeader("Cache-Control", "max-age=10000", false);
   response.setStatusLine(metadata.httpVersion, 200, "OK");
   response.setHeader("Content-Type", "image/png", false);
   var body = "iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII=";
   response.bodyOutputStream.write(body, body.length);
--- a/js/xpconnect/idl/xpccomponents.idl
+++ b/js/xpconnect/idl/xpccomponents.idl
@@ -11,16 +11,18 @@
 
 interface xpcIJSWeakReference;
 interface nsIClassInfo;
 interface nsICommandParams;
 interface nsIComponentManager;
 interface nsICycleCollectorListener;
 interface nsIEditorSpellCheck;
 interface nsIFile;
+interface nsILoadContext;
+interface nsIPersistentProperties;
 interface nsIURI;
 interface nsIJSCID;
 interface nsIJSIID;
 interface nsIPrincipal;
 interface nsIStackFrame;
 webidl Element;
 
 /**
@@ -720,18 +722,24 @@ interface nsIXPCComponents_Utils : nsISu
     void recordReplayDirective(in long directive);
 
     /* Create a spellchecker object. */
     nsIEditorSpellCheck createSpellChecker();
 
     /* Create a commandline object. */
     nsISupports createCommandLine();
 
-    /* Create a command params object. */
-    nsICommandParams createCommandParams();
+    /* Create a loadcontext object. */
+    nsILoadContext createLoadContext();
+
+    /* Create a private loadcontext object. */
+    nsILoadContext createPrivateLoadContext();
+
+    /* Create a persistent property object. */
+    nsIPersistentProperties createPersistentProperties();
 };
 
 /**
 * Interface for the 'Components' object.
 *
 * The first interface contains things that are available to non-chrome XBL code
 * that runs in a scope with an ExpandedPrincipal. The second interface
 * includes members that are only exposed to chrome.
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -15,16 +15,17 @@
 #include "nsContentUtils.h"
 #include "nsCycleCollector.h"
 #include "jsfriendapi.h"
 #include "js/CharacterEncoding.h"
 #include "js/SavedFrameAPI.h"
 #include "js/StructuredClone.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
+#include "mozilla/LoadContext.h"
 #include "mozilla/Preferences.h"
 #include "nsJSEnvironment.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/URLPreloader.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMExceptionBinding.h"
 #include "mozilla/dom/BindingUtils.h"
@@ -38,17 +39,17 @@
 #include "nsIScriptError.h"
 #include "nsISimpleEnumerator.h"
 #include "nsPIDOMWindow.h"
 #include "nsGlobalWindow.h"
 #include "nsScriptError.h"
 #include "GeckoProfiler.h"
 #include "mozilla/EditorSpellCheck.h"
 #include "nsCommandLine.h"
-#include "nsCommandParams.h"
+#include "nsPersistentProperties.h"
 
 using namespace mozilla;
 using namespace JS;
 using namespace js;
 using namespace xpc;
 using mozilla::dom::Exception;
 
 /***************************************************************************/
@@ -3228,21 +3229,39 @@ nsXPCComponents_Utils::CreateCommandLine
 {
     NS_ENSURE_ARG_POINTER(aCommandLine);
     nsCOMPtr<nsISupports> commandLine = new nsCommandLine();
     commandLine.forget(aCommandLine);
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsXPCComponents_Utils::CreateCommandParams(nsICommandParams** aCommandParams)
+nsXPCComponents_Utils::CreateLoadContext(nsILoadContext** aLoadContext)
+{
+    NS_ENSURE_ARG_POINTER(aLoadContext);
+    nsCOMPtr<nsILoadContext> loadContext = ::CreateLoadContext();
+    loadContext.forget(aLoadContext);
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXPCComponents_Utils::CreatePrivateLoadContext(nsILoadContext** aLoadContext)
 {
-    NS_ENSURE_ARG_POINTER(aCommandParams);
-    nsCOMPtr<nsICommandParams> commandParams = new nsCommandParams();
-    commandParams.forget(aCommandParams);
+    NS_ENSURE_ARG_POINTER(aLoadContext);
+    nsCOMPtr<nsILoadContext> loadContext = ::CreatePrivateLoadContext();
+    loadContext.forget(aLoadContext);
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXPCComponents_Utils::CreatePersistentProperties(nsIPersistentProperties** aPersistentProperties)
+{
+    NS_ENSURE_ARG_POINTER(aPersistentProperties);
+    nsCOMPtr<nsIPersistentProperties> props = new nsPersistentProperties();
+    props.forget(aPersistentProperties);
     return NS_OK;
 }
 
 /***************************************************************************/
 /***************************************************************************/
 /***************************************************************************/
 
 
--- a/netwerk/base/nsNetUtil.cpp
+++ b/netwerk/base/nsNetUtil.cpp
@@ -39,17 +39,17 @@
 #include "nsIInputStreamPump.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsILoadContext.h"
 #include "nsIMIMEHeaderParam.h"
 #include "nsIMutable.h"
 #include "nsINode.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIOfflineCacheUpdate.h"
-#include "nsIPersistentProperties2.h"
+#include "nsPersistentProperties.h"
 #include "nsIPrivateBrowsingChannel.h"
 #include "nsIPropertyBag2.h"
 #include "nsIProtocolProxyService.h"
 #include "mozilla/net/RedirectChannelRegistrar.h"
 #include "nsIRequestObserverProxy.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsISensitiveInfoHiddenURI.h"
 #include "nsISimpleStreamListener.h"
@@ -2024,19 +2024,17 @@ NS_LoadPersistentPropertiesFromURISpec(n
                        nsContentUtils::GetSystemPrincipal(),
                        nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                        nsIContentPolicy::TYPE_OTHER);
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIInputStream> in;
     rv = channel->Open2(getter_AddRefs(in));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsCOMPtr<nsIPersistentProperties> properties =
-      do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
+    nsCOMPtr<nsIPersistentProperties> properties = new nsPersistentProperties();
     rv = properties->Load(in);
     NS_ENSURE_SUCCESS(rv, rv);
 
     properties.swap(*outResult);
     return NS_OK;
 }
 
 bool
--- a/netwerk/test/unit/test_bug826063.js
+++ b/netwerk/test/unit/test_bug826063.js
@@ -11,19 +11,16 @@ ChromeUtils.import("resource://gre/modul
 
 
 var URIs = [
   "http://example.org",
   "https://example.org",
   "ftp://example.org"
   ];
 
-let LoadContext = Components.Constructor("@mozilla.org/loadcontext;1");
-let PrivateLoadContext = Components.Constructor("@mozilla.org/privateloadcontext;1");
-
 function* getChannels() {
   for (let u of URIs) {
     yield NetUtil.newChannel({
       uri: u,
       loadUsingSystemPrincipal: true
     });
   }
 }
@@ -65,29 +62,29 @@ add_test(function test_setPrivate_regula
   }
   run_next_test();
 });
 
 /**
  * Load context mandates private mode
  */
 add_test(function test_LoadContextPrivate() {
-  let ctx = new PrivateLoadContext();
+  let ctx = Cu.createPrivateLoadContext();
   for (let c of getChannels()) {
     c.notificationCallbacks = ctx;
     checkPrivate(c, true);
   }
   run_next_test();
 });
 
 /**
  * Load context mandates regular mode
  */
 add_test(function test_LoadContextRegular() {
-  let ctx = new LoadContext();
+  let ctx = Cu.createLoadContext();
   for (let c of getChannels()) {
     c.notificationCallbacks = ctx;
     checkPrivate(c, false);
   }
   run_next_test();
 });
 
 
--- a/netwerk/test/unit/test_cacheflags.js
+++ b/netwerk/test/unit/test_cacheflags.js
@@ -12,17 +12,17 @@ var httpsBase = "http://localhost:4445";
 var shortexpPath = "/shortexp" + suffix;
 var longexpPath = "/longexp/" + suffix;
 var longexp2Path = "/longexp/2/" + suffix;
 var nocachePath = "/nocache" + suffix;
 var nostorePath = "/nostore" + suffix;
 var test410Path = "/test410" + suffix;
 var test404Path = "/test404" + suffix;
 
-var PrivateBrowsingLoadContext = Cc["@mozilla.org/privateloadcontext;1"].createInstance(Ci.nsILoadContext);
+var PrivateBrowsingLoadContext = Cu.createPrivateLoadContext();
 
 function make_channel(url, flags, usePrivateBrowsing) {
   var securityFlags = Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
 
   var uri = Services.io.newURI(url);
   var principal = Services.scriptSecurityManager.createCodebasePrincipal(uri,
     { privateBrowsingId : usePrivateBrowsing ? 1 : 0 });
 
--- a/toolkit/components/antitracking/test/browser/browser_backgroundImageAssertion.js
+++ b/toolkit/components/antitracking/test/browser/browser_backgroundImageAssertion.js
@@ -1,16 +1,17 @@
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 add_task(async function() {
   info("Starting subResources test");
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
     ["browser.contentblocking.enabled", true],
+    ["browser.fastblock.enabled", false],
     ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
     ["privacy.trackingprotection.enabled", false],
     ["privacy.trackingprotection.pbmode.enabled", false],
     ["privacy.trackingprotection.annotate_channels", true],
   ]});
 
   await UrlClassifierTestUtils.addTestTrackers();
 
--- a/toolkit/components/antitracking/test/browser/browser_existingCookiesForSubresources.js
+++ b/toolkit/components/antitracking/test/browser/browser_existingCookiesForSubresources.js
@@ -1,15 +1,16 @@
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 add_task(async function() {
   info("Starting subResources test");
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
+    ["browser.fastblock.enabled", false],
     ["privacy.trackingprotection.enabled", false],
     ["privacy.trackingprotection.pbmode.enabled", false],
     ["privacy.trackingprotection.annotate_channels", true],
   ]});
 
   await UrlClassifierTestUtils.addTestTrackers();
 
   info("Creating a new tab");
--- a/toolkit/components/antitracking/test/browser/browser_onBeforeRequestNotificationForTrackingResources.js
+++ b/toolkit/components/antitracking/test/browser/browser_onBeforeRequestNotificationForTrackingResources.js
@@ -48,16 +48,17 @@ add_task(async function() {
 });
 
 add_task(async function() {
   info("Starting subResources test");
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
     ["browser.contentblocking.enabled", true],
+    ["browser.fastblock.enabled", false],
     ["privacy.trackingprotection.enabled", true],
     // the test doesn't open a private window, so we don't care about this pref's value
     ["privacy.trackingprotection.pbmode.enabled", false],
     // tracking annotations aren't needed in this test, only TP is needed
     ["privacy.trackingprotection.annotate_channels", false],
     // prevent the content blocking on-boarding UI to start mid-way through the test!
     [ContentBlocking.prefIntroCount, ContentBlocking.MAX_INTROS],
   ]});
--- a/toolkit/components/antitracking/test/browser/browser_onModifyRequestNotificationForTrackingResources.js
+++ b/toolkit/components/antitracking/test/browser/browser_onModifyRequestNotificationForTrackingResources.js
@@ -43,16 +43,17 @@ async function onModifyRequest() {
 }
 
 add_task(async function() {
   info("Starting subResources test");
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
     ["browser.contentblocking.enabled", true],
+    ["browser.fastblock.enabled", false],
     ["privacy.trackingprotection.enabled", true],
     // the test doesn't open a private window, so we don't care about this pref's value
     ["privacy.trackingprotection.pbmode.enabled", false],
     // tracking annotations aren't needed in this test, only TP is needed
     ["privacy.trackingprotection.annotate_channels", false],
     // prevent the content blocking on-boarding UI to start mid-way through the test!
     [ContentBlocking.prefIntroCount, ContentBlocking.MAX_INTROS],
   ]});
--- a/toolkit/components/antitracking/test/browser/browser_script.js
+++ b/toolkit/components/antitracking/test/browser/browser_script.js
@@ -1,16 +1,17 @@
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 add_task(async function() {
   info("Starting subResources test");
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
     ["browser.contentblocking.enabled", true],
+    ["browser.fastblock.enabled", false],
     ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
     ["privacy.trackingprotection.enabled", false],
     ["privacy.trackingprotection.pbmode.enabled", false],
     ["privacy.trackingprotection.annotate_channels", true],
   ]});
 
   await UrlClassifierTestUtils.addTestTrackers();
 
--- a/toolkit/components/antitracking/test/browser/browser_storageAccessWithHeuristics.js
+++ b/toolkit/components/antitracking/test/browser/browser_storageAccessWithHeuristics.js
@@ -4,16 +4,17 @@ add_task(async function() {
   info("Starting subResources test");
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
     ["dom.storage_access.enabled", true],
     ["browser.contentblocking.enabled", true],
     ["browser.contentblocking.ui.enabled", true],
     ["browser.contentblocking.rejecttrackers.ui.enabled", true],
+    ["browser.fastblock.enabled", false],
     ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
     ["privacy.trackingprotection.enabled", false],
     ["privacy.trackingprotection.pbmode.enabled", false],
     ["privacy.trackingprotection.annotate_channels", true],
   ]});
 
   await UrlClassifierTestUtils.addTestTrackers();
 });
--- a/toolkit/components/antitracking/test/browser/browser_subResources.js
+++ b/toolkit/components/antitracking/test/browser/browser_subResources.js
@@ -1,16 +1,17 @@
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 add_task(async function() {
   info("Starting subResources test");
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
     ["browser.contentblocking.enabled", true],
+    ["browser.fastblock.enabled", false],
     ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
     ["privacy.trackingprotection.enabled", false],
     ["privacy.trackingprotection.pbmode.enabled", false],
     ["privacy.trackingprotection.annotate_channels", true],
   ]});
 
   await UrlClassifierTestUtils.addTestTrackers();
 
--- a/toolkit/components/contentprefs/ContentPrefServiceParent.jsm
+++ b/toolkit/components/contentprefs/ContentPrefServiceParent.jsm
@@ -7,20 +7,18 @@
 
 var EXPORTED_SYMBOLS = [ "ContentPrefServiceParent" ];
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 ChromeUtils.defineModuleGetter(this, "_methodsCallableFromChild",
                                "resource://gre/modules/ContentPrefUtils.jsm");
 
-let loadContext = Cc["@mozilla.org/loadcontext;1"].
-                    createInstance(Ci.nsILoadContext);
-let privateLoadContext = Cc["@mozilla.org/privateloadcontext;1"].
-                           createInstance(Ci.nsILoadContext);
+let loadContext = Cu.createLoadContext();
+let privateLoadContext = Cu.createPrivateLoadContext();
 
 function contextArg(context) {
   return (context && context.usePrivateBrowsing) ?
            privateLoadContext :
            loadContext;
 }
 
 var ContentPrefServiceParent = {
--- a/toolkit/components/contentprefs/tests/mochitest/test_remoteContentPrefs.html
+++ b/toolkit/components/contentprefs/tests/mochitest/test_remoteContentPrefs.html
@@ -8,20 +8,19 @@
   <script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 
   <script type="application/javascript">
     "use strict";
 
-    let loadContext = SpecialPowers.Cc["@mozilla.org/loadcontext;1"].
-                        createInstance(SpecialPowers.Ci.nsILoadContext);
-    let privateLoadContext = SpecialPowers.Cc["@mozilla.org/privateloadcontext;1"].
-                        createInstance(SpecialPowers.Ci.nsILoadContext);
+    let Cu = SpecialPowers.Cu;
+    let loadContext = Cu.createLoadContext();
+    let privateLoadContext = Cu.createPrivateLoadContext();
 
     SimpleTest.waitForExplicitFinish();
 
     const childFrameURL =
       "data:text/html,<!DOCTYPE HTML><html><body></body></html>";
 
     function childFrameScript(isFramePrivate) {
       "use strict";
@@ -186,18 +185,17 @@
           },
           onContentPrefRemoved(group, name, isPrivate) {
             observed.reject("got unexpected notification");
           },
         };
 
         cps.addObserverForName("test", prefObserver);
 
-        let privateLoadContext = Cc["@mozilla.org/privateloadcontext;1"].
-                            createInstance(Ci.nsILoadContext);
+        let privateLoadContext = Cu.createPrivateLoadContext();
         cps.set("http://mochi.test", "test", 42, privateLoadContext);
         let event = await observed.promise;
         tester.is(event.name, "test", "got the right event");
         tester.is(event.isPrivate, true, "the event was for an isPrivate pref");
 
         mm.sendAsyncMessage("testRemoteContentPrefs:getPref",
                             { group: "http://mochi.test", name: "test" });
 
--- a/toolkit/components/contentprefs/tests/unit_cps2/head.js
+++ b/toolkit/components/contentprefs/tests/unit_cps2/head.js
@@ -1,18 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
-let loadContext = Cc["@mozilla.org/loadcontext;1"].
-                    createInstance(Ci.nsILoadContext);
-let privateLoadContext = Cc["@mozilla.org/privateloadcontext;1"].
-                           createInstance(Ci.nsILoadContext);
+let loadContext = Cu.createLoadContext();
+let privateLoadContext = Cu.createPrivateLoadContext();
 
 // There has to be a profile directory before the CPS service is gotten.
 do_get_profile();
 let cps = Cc["@mozilla.org/content-pref/service;1"].
           getService(Ci.nsIContentPrefService2);
 
 function makeCallback(resolve, callbacks, success = null) {
   callbacks = callbacks || {};
--- a/toolkit/mozapps/downloads/DownloadLastDir.jsm
+++ b/toolkit/mozapps/downloads/DownloadLastDir.jsm
@@ -27,20 +27,18 @@
 const LAST_DIR_PREF = "browser.download.lastDir";
 const SAVE_PER_SITE_PREF = LAST_DIR_PREF + ".savePerSite";
 const nsIFile = Ci.nsIFile;
 
 var EXPORTED_SYMBOLS = [ "DownloadLastDir" ];
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
-let nonPrivateLoadContext = Cc["@mozilla.org/loadcontext;1"].
-                              createInstance(Ci.nsILoadContext);
-let privateLoadContext = Cc["@mozilla.org/privateloadcontext;1"].
-                              createInstance(Ci.nsILoadContext);
+let nonPrivateLoadContext = Cu.createLoadContext();
+let privateLoadContext = Cu.createPrivateLoadContext();
 
 var observer = {
   QueryInterface: ChromeUtils.generateQI(["nsIObserver",
                                           "nsISupportsWeakReference"]),
 
   observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "last-pb-context-exited":
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -50,17 +50,17 @@
 #include "prnetdb.h"
 #include "prprf.h"
 #include "prproces.h"
 #include "prenv.h"
 #include "prtime.h"
 
 #include "nsIAppShellService.h"
 #include "nsIAppStartup.h"
-#include "nsIAppStartupNotifier.h"
+#include "nsAppStartupNotifier.h"
 #include "nsIMutableArray.h"
 #include "nsICategoryManager.h"
 #include "nsIChromeRegistry.h"
 #include "nsCommandLine.h"
 #include "nsIComponentManager.h"
 #include "nsIComponentRegistrar.h"
 #include "nsIConsoleService.h"
 #include "nsIContentHandler.h"
@@ -4623,23 +4623,17 @@ XREMain::XRE_mainRun()
       return NS_ERROR_FAILURE;
     }
 #endif
 
   // Initialize user preferences before notifying startup observers so they're
   // ready in time for early consumers, such as the component loader.
   mDirProvider.InitializeUserPrefs();
 
-  {
-    nsCOMPtr<nsIObserver> startupNotifier
-      (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
-    NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
-
-    startupNotifier->Observe(nullptr, APPSTARTUP_TOPIC, nullptr);
-  }
+  nsAppStartupNotifier::NotifyObservers(APPSTARTUP_TOPIC);
 
   nsCOMPtr<nsIAppStartup> appStartup
     (do_GetService(NS_APPSTARTUP_CONTRACTID));
   NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE);
 
   mDirProvider.DoStartup();
 
   // As FilePreferences need the profile directory, we must initialize right here.
--- a/toolkit/xre/nsAppStartupNotifier.cpp
+++ b/toolkit/xre/nsAppStartupNotifier.cpp
@@ -7,25 +7,18 @@
 #include "nsString.h"
 #include "nsIServiceManager.h"
 #include "nsICategoryManager.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsAppStartupNotifier.h"
 #include "nsISimpleEnumerator.h"
 
-NS_IMPL_ISUPPORTS(nsAppStartupNotifier, nsIObserver)
-
-nsAppStartupNotifier::nsAppStartupNotifier()
-{
-}
-
-nsAppStartupNotifier::~nsAppStartupNotifier() = default;
-
-NS_IMETHODIMP nsAppStartupNotifier::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData)
+/* static */ nsresult
+nsAppStartupNotifier::NotifyObservers(const char* aTopic)
 {
     NS_ENSURE_ARG(aTopic);
     nsresult rv;
 
     // now initialize all startup listeners
     nsCOMPtr<nsICategoryManager> categoryManager =
                     do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/toolkit/xre/nsAppStartupNotifier.h
+++ b/toolkit/xre/nsAppStartupNotifier.h
@@ -3,28 +3,16 @@
  * 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 nsAppStartupNotifier_h___
 #define nsAppStartupNotifier_h___
 
 #include "nsIAppStartupNotifier.h"
 
-// {1F59B001-02C9-11d5-AE76-CC92F7DB9E03}
-#define NS_APPSTARTUPNOTIFIER_CID \
-   { 0x1f59b001, 0x2c9, 0x11d5, { 0xae, 0x76, 0xcc, 0x92, 0xf7, 0xdb, 0x9e, 0x3 } }
-
-class nsAppStartupNotifier : public nsIObserver
+class nsAppStartupNotifier final
 {
 public:
-    NS_DEFINE_STATIC_CID_ACCESSOR( NS_APPSTARTUPNOTIFIER_CID )
-
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSIOBSERVER
-
-    nsAppStartupNotifier();
-
-protected:
-    virtual ~nsAppStartupNotifier();
+  static nsresult NotifyObservers(const char* aTopic);
 };
 
 #endif /* nsAppStartupNotifier_h___ */
 
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -11,17 +11,17 @@
 #include <stdlib.h>
 #if defined(MOZ_WIDGET_GTK)
 #include <glib.h>
 #endif
 
 #include "prenv.h"
 
 #include "nsIAppShell.h"
-#include "nsIAppStartupNotifier.h"
+#include "nsAppStartupNotifier.h"
 #include "nsIDirectoryService.h"
 #include "nsIFile.h"
 #include "nsIToolkitChromeRegistry.h"
 #include "nsIToolkitProfile.h"
 
 #ifdef XP_WIN
 #include <process.h>
 #include <shobjidl.h>
@@ -197,22 +197,17 @@ XRE_InitEmbedding2(nsIFile *aLibXULDirec
     return rv;
 
   // We do not need to autoregister components here. The CheckCompatibility()
   // bits in nsAppRunner.cpp check for an invalidation flag in
   // compatibility.ini.
   // If the app wants to autoregister every time (for instance, if it's debug),
   // it can do so after we return from this function.
 
-  nsCOMPtr<nsIObserver> startupNotifier
-    (do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID));
-  if (!startupNotifier)
-    return NS_ERROR_FAILURE;
-
-  startupNotifier->Observe(nullptr, APPSTARTUP_TOPIC, nullptr);
+  nsAppStartupNotifier::NotifyObservers(APPSTARTUP_TOPIC);
 
   return NS_OK;
 }
 
 void
 XRE_NotifyProfile()
 {
   NS_ASSERTION(gDirServiceProvider, "XRE_InitEmbedding was not called!");
--- a/toolkit/xre/nsEmbeddingModule.cpp
+++ b/toolkit/xre/nsEmbeddingModule.cpp
@@ -1,30 +1,28 @@
 /* -*- 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 "mozilla/ModuleUtils.h"
 #include "nsDialogParamBlock.h"
 #include "nsWindowWatcher.h"
-#include "nsAppStartupNotifier.h"
 #include "nsFind.h"
 #include "nsWebBrowserPersist.h"
 #include "nsNetCID.h"
 #include "nsEmbedCID.h"
 
 #ifdef NS_PRINTING
 #include "nsPrintingPromptService.h"
 #include "nsPrintingProxy.h"
 #endif
 
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsWindowWatcher, Init)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppStartupNotifier)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFind)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsWebBrowserPersist)
 
 #ifdef MOZ_XUL
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDialogParamBlock)
 #ifdef NS_PRINTING
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsPrintingPromptService,
                                          nsPrintingPromptService::GetSingleton)
@@ -38,17 +36,16 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR
 #ifdef MOZ_XUL
 NS_DEFINE_NAMED_CID(NS_DIALOGPARAMBLOCK_CID);
 #ifdef NS_PRINTING
 NS_DEFINE_NAMED_CID(NS_PRINTINGPROMPTSERVICE_CID);
 #endif
 #endif
 NS_DEFINE_NAMED_CID(NS_WINDOWWATCHER_CID);
 NS_DEFINE_NAMED_CID(NS_FIND_CID);
-NS_DEFINE_NAMED_CID(NS_APPSTARTUPNOTIFIER_CID);
 NS_DEFINE_NAMED_CID(NS_WEBBROWSERPERSIST_CID);
 
 static const mozilla::Module::CIDEntry kEmbeddingCIDs[] = {
 #ifdef MOZ_XUL
     { &kNS_DIALOGPARAMBLOCK_CID, false, nullptr, nsDialogParamBlockConstructor },
 #ifdef NS_PRINTING
 
 #ifdef PROXY_PRINTING
@@ -58,31 +55,29 @@ static const mozilla::Module::CIDEntry k
       mozilla::Module::CONTENT_PROCESS_ONLY },
 #else
     { &kNS_PRINTINGPROMPTSERVICE_CID, false, nullptr, nsPrintingPromptServiceConstructor },
 #endif
 #endif
 #endif
     { &kNS_WINDOWWATCHER_CID, false, nullptr, nsWindowWatcherConstructor },
     { &kNS_FIND_CID, false, nullptr, nsFindConstructor },
-    { &kNS_APPSTARTUPNOTIFIER_CID, false, nullptr, nsAppStartupNotifierConstructor },
     { &kNS_WEBBROWSERPERSIST_CID, false, nullptr, nsWebBrowserPersistConstructor },
     { nullptr }
 };
 
 static const mozilla::Module::ContractIDEntry kEmbeddingContracts[] = {
 #ifdef MOZ_XUL
     { NS_DIALOGPARAMBLOCK_CONTRACTID, &kNS_DIALOGPARAMBLOCK_CID },
 #ifdef NS_PRINTING
     { NS_PRINTINGPROMPTSERVICE_CONTRACTID, &kNS_PRINTINGPROMPTSERVICE_CID },
 #endif
 #endif
     { NS_WINDOWWATCHER_CONTRACTID, &kNS_WINDOWWATCHER_CID },
     { NS_FIND_CONTRACTID, &kNS_FIND_CID },
-    { NS_APPSTARTUPNOTIFIER_CONTRACTID, &kNS_APPSTARTUPNOTIFIER_CID },
     { NS_WEBBROWSERPERSIST_CONTRACTID, &kNS_WEBBROWSERPERSIST_CID },
     { nullptr }
 };
 
 static const mozilla::Module kEmbeddingModule = {
     mozilla::Module::kVersion,
     kEmbeddingCIDs,
     kEmbeddingContracts
--- a/toolkit/xre/nsIAppStartupNotifier.h
+++ b/toolkit/xre/nsIAppStartupNotifier.h
@@ -1,18 +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/. */
 
 #ifndef nsIAppStartupNotifier_h___
 #define nsIAppStartupNotifier_h___
 
-#include "nsIObserver.h"
-
 /*
  Some components need to be run at the startup of mozilla or embedding - to
  start new services etc.
 
  This interface provides a generic way to start up arbitrary components
  without requiring them to hack into main1() (or into NS_InitEmbedding) as
  it's currently being done for services such as wallet, command line handlers
  etc.
@@ -37,18 +35,16 @@
  we create an instance of the AppStartupNotifier component (which
  implements nsIObserver) and invoke its Observe() method.
 
  Observe()  will enumerate the components registered into the
  APPSTARTUP_CATEGORY and notify them that startup has begun
  and release them.
 */
 
-#define NS_APPSTARTUPNOTIFIER_CONTRACTID "@mozilla.org/embedcomp/appstartup-notifier;1"
-
 #define APPSTARTUP_CATEGORY "app-startup"
 #define APPSTARTUP_TOPIC    "app-startup"
 
 
 /*
  Please note that there's not a new interface in this file.
  We're just leveraging nsIObserver instead of creating a
  new one
--- a/xpcom/build/XPCOMInit.cpp
+++ b/xpcom/build/XPCOMInit.cpp
@@ -23,18 +23,16 @@
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/dom/VideoDecoderManagerChild.h"
 
 #include "prlink.h"
 
 #include "nsCycleCollector.h"
 #include "nsObserverList.h"
 #include "nsObserverService.h"
-#include "nsProperties.h"
-#include "nsPersistentProperties.h"
 #include "nsScriptableInputStream.h"
 #include "nsBinaryStream.h"
 #include "nsStorageStream.h"
 #include "nsPipe.h"
 #include "nsScriptableBase64Encoder.h"
 
 #include "nsMemoryImpl.h"
 #include "nsDebugImpl.h"
@@ -206,18 +204,16 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryI
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsStorageStream)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsVersionComparatorImpl)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsScriptableBase64Encoder)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsVariantCC)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHashPropertyBagCC)
 
-NS_GENERIC_AGGREGATED_CONSTRUCTOR(nsProperties)
-
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsUUIDGenerator, Init)
 
 #ifdef MOZ_WIDGET_COCOA
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacUtilsImpl)
 #endif
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemInfo, Init)
 
@@ -254,18 +250,16 @@ NS_DEFINE_NAMED_CID(NS_CHROMEREGISTRY_CI
 NS_DEFINE_NAMED_CID(NS_CHROMEPROTOCOLHANDLER_CID);
 
 NS_DEFINE_NAMED_CID(NS_SECURITY_CONSOLE_MESSAGE_CID);
 
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsChromeRegistry,
                                          nsChromeRegistry::GetSingleton)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsChromeProtocolHandler)
 
-#define NS_PERSISTENTPROPERTIES_CID NS_IPERSISTENTPROPERTIES_CID /* sigh */
-
 static already_AddRefed<nsIFactory>
 CreateINIParserFactory(const mozilla::Module& aModule,
                        const mozilla::Module::CIDEntry& aEntry)
 {
   nsCOMPtr<nsIFactory> f = new nsINIParserFactory();
   return f.forget();
 }
 
--- a/xpcom/build/XPCOMModule.inc
+++ b/xpcom/build/XPCOMModule.inc
@@ -7,20 +7,16 @@
     COMPONENT(SCRIPTABLEINPUTSTREAM, nsScriptableInputStream::Create)
     COMPONENT(BINARYINPUTSTREAM, nsBinaryInputStreamConstructor)
     COMPONENT(BINARYOUTPUTSTREAM, nsBinaryOutputStreamConstructor)
     COMPONENT(STORAGESTREAM, nsStorageStreamConstructor)
     COMPONENT(VERSIONCOMPARATOR, nsVersionComparatorImplConstructor)
     COMPONENT(SCRIPTABLEBASE64ENCODER, nsScriptableBase64EncoderConstructor)
     COMPONENT(PIPE, nsPipeConstructor)
 
-    COMPONENT(PROPERTIES, nsPropertiesConstructor)
-
-    COMPONENT(PERSISTENTPROPERTIES, nsPersistentProperties::Create)
-
     COMPONENT(ARRAY, nsArrayBase::XPCOMConstructor)
     COMPONENT(CONSOLESERVICE, nsConsoleServiceConstructor)
     COMPONENT_M(OBSERVERSERVICE, nsObserverService::Create, Module::ALLOW_IN_GPU_PROCESS)
 
     COMPONENT_M(TIMER, nsTimerConstructor, Module::ALLOW_IN_GPU_PROCESS)
 
 #define COMPONENT_SUPPORTS(TYPE, Type)                                         \
   COMPONENT(SUPPORTS_##TYPE, nsSupports##Type##Constructor)
--- a/xpcom/ds/moz.build
+++ b/xpcom/ds/moz.build
@@ -56,17 +56,19 @@ EXPORTS += [
     'nsEnumeratorUtils.h',
     'nsExpirationTracker.h',
     'nsGkAtoms.h',
     'nsHashKeys.h',
     'nsHashPropertyBag.h',
     'nsInterfaceHashtable.h',
     'nsJSThingHashtable.h',
     'nsMathUtils.h',
+    'nsPersistentProperties.h',
     'nsPointerHashKeys.h',
+    'nsProperties.h',
     'nsQuickSort.h',
     'nsRefPtrHashtable.h',
     'nsSimpleEnumerator.h',
     'nsStaticAtomUtils.h',
     'nsStaticNameTable.h',
     'nsStringEnumerator.h',
     'nsSupportsPrimitives.h',
     'nsTArray-inl.h',
--- a/xpcom/ds/nsIPersistentProperties2.idl
+++ b/xpcom/ds/nsIPersistentProperties2.idl
@@ -53,18 +53,8 @@ interface nsIPersistentProperties : nsIP
    */
   AString setStringProperty(in AUTF8String key, in AString value);
 
 %{C++
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const = 0;
 %}
 };
 
-
-%{C++
-
-#define NS_IPERSISTENTPROPERTIES_CID \
-{ 0x2245e573, 0x9464, 0x11d2, \
-  { 0x9b, 0x8b, 0x0, 0x80, 0x5f, 0x8a, 0x16, 0xd9 } }
-
-#define NS_PERSISTENTPROPERTIES_CONTRACTID "@mozilla.org/persistent-properties;1"
-
-%}
--- a/xpcom/ds/nsPersistentProperties.cpp
+++ b/xpcom/ds/nsPersistentProperties.cpp
@@ -454,27 +454,16 @@ nsPersistentProperties::SizeOfIncludingT
 {
   // The memory used by mTable is accounted for in mArena.
   size_t n = 0;
   n += mArena.SizeOfExcludingThis(aMallocSizeOf);
   n += mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
   return aMallocSizeOf(this) + n;
 }
 
-nsresult
-nsPersistentProperties::Create(nsISupports* aOuter, REFNSIID aIID,
-                               void** aResult)
-{
-  if (aOuter) {
-    return NS_ERROR_NO_AGGREGATION;
-  }
-  RefPtr<nsPersistentProperties> props = new nsPersistentProperties();
-  return props->QueryInterface(aIID, aResult);
-}
-
 NS_IMPL_ISUPPORTS(nsPersistentProperties, nsIPersistentProperties, nsIProperties)
 
 NS_IMETHODIMP
 nsPersistentProperties::Load(nsIInputStream* aIn)
 {
   nsresult rv = NS_NewUnicharInputStream(aIn, getter_AddRefs(mIn));
 
   if (rv != NS_OK) {
--- a/xpcom/ds/nsPersistentProperties.h
+++ b/xpcom/ds/nsPersistentProperties.h
@@ -20,19 +20,16 @@ class nsPersistentProperties final : pub
 {
 public:
   nsPersistentProperties();
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIPROPERTIES
   NS_DECL_NSIPERSISTENTPROPERTIES
 
-  static MOZ_MUST_USE nsresult
-  Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);
-
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
 
 private:
   ~nsPersistentProperties();
 
 protected:
   nsCOMPtr<nsIUnicharInputStream> mIn;
 
--- a/xpcom/ds/nsProperties.h
+++ b/xpcom/ds/nsProperties.h
@@ -8,32 +8,24 @@
 #define nsProperties_h___
 
 #include "nsIProperties.h"
 #include "nsInterfaceHashtable.h"
 #include "nsHashKeys.h"
 #include "nsAgg.h"
 #include "mozilla/Attributes.h"
 
-#define NS_PROPERTIES_CID                            \
-{ /* 4de2bc90-b1bf-11d3-93b6-00104ba0fd40 */         \
-    0x4de2bc90,                                      \
-    0xb1bf,                                          \
-    0x11d3,                                          \
-    {0x93, 0xb6, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
-}
-
 typedef nsInterfaceHashtable<nsCharPtrHashKey,
                              nsISupports> nsProperties_HashBase;
 
 class nsProperties final
   : public nsIProperties
   , public nsProperties_HashBase
 {
 public:
   NS_DECL_AGGREGATED
   NS_DECL_NSIPROPERTIES
 
-  explicit nsProperties(nsISupports *aOuter) { NS_INIT_AGGREGATED(aOuter); }
+  nsProperties() { NS_INIT_AGGREGATED(nullptr); }
   ~nsProperties() {}
 };
 
 #endif /* nsProperties_h___ */
--- a/xpcom/tests/unit/test_bug121341.js
+++ b/xpcom/tests/unit/test_bug121341.js
@@ -4,18 +4,17 @@ ChromeUtils.import("resource://gre/modul
 function run_test() {
   var dataFile = do_get_file("data/bug121341.properties");
   var channel = NetUtil.newChannel({
     uri: Services.io.newFileURI(dataFile, null, null),
     loadUsingSystemPrincipal: true
   });
   var inp = channel.open2();
 
-  var properties = Cc["@mozilla.org/persistent-properties;1"].
-                   createInstance(Ci.nsIPersistentProperties);
+  var properties = Cu.createPersistentProperties();
   properties.load(inp);
 
   var value;
 
   value = properties.getStringProperty("1");
   Assert.equal(value, "abc");
 
   value = properties.getStringProperty("2");
@@ -51,16 +50,15 @@ function run_test() {
   dataFile = do_get_file("data/bug121341-2.properties");
 
   var channel2 = NetUtil.newChannel({
     uri: Services.io.newFileURI(dataFile, null, null),
     loadUsingSystemPrincipal: true
   });
   inp = channel2.open2();
 
-  var properties2 = Cc["@mozilla.org/persistent-properties;1"].
-                    createInstance(Ci.nsIPersistentProperties);
+  var properties2 = Cu.createPersistentProperties();
   try {
     properties2.load(inp);
     do_throw("load() didn't fail");
   } catch (e) {
   }
 }