merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 06 Jul 2017 11:18:05 +0200
changeset 367593 018b3829d0a7f6944a5ae1489f3a64c9e2893909
parent 367528 6cab68456fae75270cb6e014f32ce99c394d6d54 (current diff)
parent 367592 16fb069369c932c5fef1d13020283a1eb0fd0ae2 (diff)
child 367594 4bd7db49d22847111dff9c1dd63ed573903faa5b
child 367625 e3d06ac5d1d7a64f213c59b4c93723bee3dddbda
child 367659 530b9cd1f9635702612eb16db37b79338a826bdd
push id32137
push usercbook@mozilla.com
push dateThu, 06 Jul 2017 09:18:21 +0000
treeherdermozilla-central@018b3829d0a7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone56.0a1
first release with
nightly win32
018b3829d0a7 / 56.0a1 / 20170706030206 / files
nightly win64
018b3829d0a7 / 56.0a1 / 20170706030206 / files
nightly linux32
nightly linux64
nightly mac
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
dom/ipc/ContentChild.cpp
dom/ipc/TabChild.cpp
dom/plugins/ipc/PluginAsyncSurrogate.cpp
dom/plugins/ipc/PluginAsyncSurrogate.h
dom/plugins/ipc/PluginDataResolver.h
toolkit/components/telemetry/TelemetrySession.jsm
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -1409,16 +1409,32 @@ Accessible::SetCurValue(double aValue)
 
   return NS_SUCCEEDED(
     mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_valuenow, strValue, true));
 }
 
 role
 Accessible::ARIATransformRole(role aRole)
 {
+  // Beginning with ARIA 1.1, user agents are expected to use the native host
+  // language role of the element when the region role is used without a name.
+  // https://rawgit.com/w3c/aria/master/core-aam/core-aam.html#role-map-region
+  //
+  // XXX: While the name computation algorithm can be non-trivial in the general
+  // case, it should not be especially bad here: If the author hasn't used the
+  // region role, this calculation won't occur. And the region role's name
+  // calculation rule excludes name from content. That said, this use case is
+  // another example of why we should consider caching the accessible name. See:
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=1378235.
+  if (aRole == roles::REGION) {
+    nsAutoString name;
+    Name(name);
+    return name.IsEmpty() ? NativeRole() : aRole;
+  }
+
   // XXX: these unfortunate exceptions don't fit into the ARIA table. This is
   // where the accessible role depends on both the role and ARIA state.
   if (aRole == roles::PUSHBUTTON) {
     if (nsAccUtils::HasDefinedARIAToken(mContent, nsGkAtoms::aria_pressed)) {
       // For simplicity, any existing pressed attribute except "" or "undefined"
       // indicates a toggle.
       return roles::TOGGLE_BUTTON;
     }
--- a/accessible/ipc/win/PlatformChild.cpp
+++ b/accessible/ipc/win/PlatformChild.cpp
@@ -1,18 +1,18 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 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/a11y/Compatibility.h"
 #include "mozilla/a11y/PlatformChild.h"
 #include "mozilla/mscom/EnsureMTA.h"
 #include "mozilla/mscom/InterceptorLog.h"
-#include "mozilla/WindowsVersion.h"
 
 #include "Accessible2.h"
 #include "Accessible2_2.h"
 #include "AccessibleHypertext2.h"
 #include "AccessibleTableCell.h"
 
 #include "AccessibleHypertext2_i.c"
 
@@ -44,30 +44,17 @@ static const mozilla::mscom::ArrayData s
 // we intend to instantiate them. Therefore RegisterProxy() must be called
 // via EnsureMTA.
 PlatformChild::PlatformChild()
   : mAccTypelib(mozilla::mscom::RegisterTypelib(L"oleacc.dll",
         mozilla::mscom::RegistrationFlags::eUseSystemDirectory))
   , mMiscTypelib(mozilla::mscom::RegisterTypelib(L"Accessible.tlb"))
   , mSdnTypelib(mozilla::mscom::RegisterTypelib(L"AccessibleMarshal.dll"))
 {
-  // The manifest for 32-bit Windows is embedded with resource ID 32.
-  // The manifest for 64-bit Windows is embedded with resource ID 64.
-  // Beginning with Windows 10 Creators Update, 32-bit builds use the 64-bit
-  // manifest.
-  WORD actCtxResourceId;
-#if defined(HAVE_64BIT_BUILD)
-  actCtxResourceId = 64;
-#else
-  if (IsWin10CreatorsUpdateOrLater()) {
-    actCtxResourceId = 64;
-  } else {
-    actCtxResourceId = 32;
-  }
-#endif
+  WORD actCtxResourceId = Compatibility::GetActCtxResourceId();
 
   mozilla::mscom::MTADeletePtr<mozilla::mscom::ActivationContextRegion> tmpActCtxMTA;
   mozilla::mscom::EnsureMTA([actCtxResourceId, &tmpActCtxMTA]() -> void {
     tmpActCtxMTA.reset(new mozilla::mscom::ActivationContextRegion(actCtxResourceId));
   });
   mActCtxMTA = Move(tmpActCtxMTA);
 
   mozilla::mscom::InterceptorLog::Init();
--- a/accessible/ipc/win/handler/AccessibleHandler.cpp
+++ b/accessible/ipc/win/handler/AccessibleHandler.cpp
@@ -217,27 +217,22 @@ AccessibleHandler::ReadHandlerPayload(IS
   if (!deserializer.Read(&mCachedData, &IA2Payload_Decode)) {
     return E_FAIL;
   }
 
   if (!mCachedData.mGeckoBackChannel) {
     return S_OK;
   }
 
-  long pid = static_cast<long>(::GetCurrentProcessId());
-
-  RefPtr<IHandlerControl> ctl;
-  HRESULT hr = gControlFactory.CreateInstance(nullptr, IID_IHandlerControl,
-                                              getter_AddRefs(ctl));
-  if (SUCCEEDED(hr)) {
-    hr = mCachedData.mGeckoBackChannel->put_HandlerControl(pid, ctl);
-    MOZ_ASSERT(SUCCEEDED(hr));
+  RefPtr<AccessibleHandlerControl> ctl(gControlFactory.GetOrCreateSingleton());
+  if (!ctl) {
+    return E_OUTOFMEMORY;
   }
 
-  return hr;
+  return ctl->Register(WrapNotNull(mCachedData.mGeckoBackChannel));
 }
 
 REFIID
 AccessibleHandler::MarshalAs(REFIID aIid)
 {
   static_assert(&NEWEST_IA2_IID == &IID_IAccessible2_3,
                 "You have modified NEWEST_IA2_IID. This code needs updating.");
   if (aIid == IID_IAccessible2_3 || aIid == IID_IAccessible2_2 ||
--- a/accessible/ipc/win/handler/AccessibleHandlerControl.cpp
+++ b/accessible/ipc/win/handler/AccessibleHandlerControl.cpp
@@ -127,17 +127,18 @@ AccessibleHandlerControl::Create(Accessi
   }
 
   RefPtr<AccessibleHandlerControl> ctl(new AccessibleHandlerControl());
   ctl.forget(aOutObject);
   return S_OK;
 }
 
 AccessibleHandlerControl::AccessibleHandlerControl()
-  : mCacheGen(0)
+  : mIsRegistered(false)
+  , mCacheGen(0)
   , mIA2Proxy(mscom::RegisterProxy(L"ia2marshal.dll"))
   , mHandlerProxy(mscom::RegisterProxy())
 {
   MOZ_ASSERT(mIA2Proxy);
 }
 
 IMPL_IUNKNOWN1(AccessibleHandlerControl, IHandlerControl)
 
@@ -184,10 +185,24 @@ AccessibleHandlerControl::GetHandlerType
   if (!mHandlerProxy) {
     return E_UNEXPECTED;
   }
 
   return mHandlerProxy->GetTypeInfoForGuid(CLSID_AccessibleHandler,
                                            aOutTypeInfo);
 }
 
+HRESULT
+AccessibleHandlerControl::Register(NotNull<IGeckoBackChannel*> aGecko)
+{
+  if (mIsRegistered) {
+    return S_OK;
+  }
+
+  long pid = static_cast<long>(::GetCurrentProcessId());
+  HRESULT hr = aGecko->put_HandlerControl(pid, this);
+  mIsRegistered = SUCCEEDED(hr);
+  MOZ_ASSERT(mIsRegistered);
+  return hr;
+}
+
 } // namespace a11y
 } // namespace mozilla
--- a/accessible/ipc/win/handler/AccessibleHandlerControl.h
+++ b/accessible/ipc/win/handler/AccessibleHandlerControl.h
@@ -66,20 +66,23 @@ public:
     return mCacheGen;
   }
 
   HRESULT GetNewText(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutNewText);
   HRESULT GetOldText(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutOldText);
 
   HRESULT GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo);
 
+  HRESULT Register(NotNull<IGeckoBackChannel*> aGecko);
+
 private:
   AccessibleHandlerControl();
   ~AccessibleHandlerControl() = default;
 
+  bool mIsRegistered;
   uint32_t mCacheGen;
   detail::TextChange mTextChange;
   UniquePtr<mscom::RegisteredProxy> mIA2Proxy;
   UniquePtr<mscom::RegisteredProxy> mHandlerProxy;
 };
 
 extern mscom::SingletonFactory<AccessibleHandlerControl> gControlFactory;
 
--- a/accessible/mac/mozAccessible.mm
+++ b/accessible/mac/mozAccessible.mm
@@ -793,17 +793,17 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
       return @"AXApplicationLog";
     if (roleAtom == nsGkAtoms::marquee)
       return @"AXApplicationMarquee";
     if (roleAtom == nsGkAtoms::math)
       return @"AXDocumentMath";
     if (roleAtom == nsGkAtoms::note_)
       return @"AXDocumentNote";
     if (roleAtom == nsGkAtoms::region)
-      return @"AXLandmarkRegion";
+      return mRole == roles::REGION ? @"AXLandmarkRegion" : nil;
     if (roleAtom == nsGkAtoms::status)
       return @"AXApplicationStatus";
     if (roleAtom == nsGkAtoms::tabpanel)
       return @"AXTabPanel";
     if (roleAtom == nsGkAtoms::timer)
       return @"AXApplicationTimer";
     if (roleAtom == nsGkAtoms::tooltip)
       return @"AXUserInterfaceTooltip";
--- a/accessible/tests/mochitest/role/test_aria.html
+++ b/accessible/tests/mochitest/role/test_aria.html
@@ -49,17 +49,21 @@
       testRole("aria_menuitem", ROLE_MENUITEM);
       testRole("aria_menuitemcheckbox", ROLE_CHECK_MENU_ITEM);
       testRole("aria_menuitemradio", ROLE_RADIO_MENU_ITEM);
       testRole("aria_note", ROLE_NOTE);
       testRole("aria_presentation", ROLE_TEXT); // weak role
       testRole("aria_progressbar", ROLE_PROGRESSBAR);
       testRole("aria_radio", ROLE_RADIOBUTTON);
       testRole("aria_radiogroup", ROLE_RADIO_GROUP);
-      testRole("aria_region", ROLE_REGION);
+      testRole("aria_region_no_name", ROLE_TEXT);
+      testRole("aria_region_has_label", ROLE_REGION);
+      testRole("aria_region_has_labelledby", ROLE_REGION);
+      testRole("aria_region_has_title", ROLE_REGION);
+      testRole("aria_region_empty_name", ROLE_TEXT);
       testRole("aria_row", ROLE_ROW);
       testRole("aria_rowheader", ROLE_ROWHEADER);
       testRole("aria_scrollbar", ROLE_SCROLLBAR);
       testRole("aria_searchbox", ROLE_ENTRY);
       testRole("aria_separator", ROLE_SEPARATOR);
       testRole("aria_slider", ROLE_SLIDER);
       testRole("aria_spinbutton", ROLE_SPINBUTTON);
       testRole("aria_status", ROLE_STATUSBAR);
@@ -233,17 +237,21 @@
   <span id="aria_menuitem" role="menuitem"/>
   <span id="aria_menuitemcheckbox" role="menuitemcheckbox"/>
   <span id="aria_menuitemradio" role="menuitemradio"/>
   <span id="aria_note" role="note"/>
   <span id="aria_presentation" role="presentation" tabindex="0"/>
   <span id="aria_progressbar" role="progressbar"/>
   <span id="aria_radio" role="radio"/>
   <span id="aria_radiogroup" role="radiogroup"/>
-  <span id="aria_region" role="region"/>
+  <span id="aria_region_no_name" role="region"/>
+  <span id="aria_region_has_label" role="region" aria-label="label"/>
+  <span id="aria_region_has_labelledby" role="region" aria-labelledby="label"/><span id="label" aria-label="label">
+  <span id="aria_region_has_title" role="region" title="title"/>
+  <span id="aria_region_empty_name" role="region" aria-label="" title="" aria-labelledby="empty"/><span id="empty"/>
   <span id="aria_row" role="row"/>
   <span id="aria_rowheader" role="rowheader"/>
   <span id="aria_scrollbar" role="scrollbar"/>
   <span id="aria_searchbox" role="textbox"/>
   <span id="aria_separator" role="separator"/>
   <span id="aria_slider" role="slider"/>
   <span id="aria_spinbutton" role="spinbutton"/>
   <span id="aria_status" role="status"/>
--- a/accessible/windows/msaa/Compatibility.cpp
+++ b/accessible/windows/msaa/Compatibility.cpp
@@ -1,22 +1,27 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 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 "Compatibility.h"
 
+#include "mozilla/WindowsVersion.h"
+#include "nsExceptionHandler.h"
+#include "nsUnicharUtils.h"
 #include "nsWindowsDllInterceptor.h"
 #include "nsWinUtils.h"
 #include "Statistics.h"
 
 #include "mozilla/Preferences.h"
 
+#include <shlobj.h>
+
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 /**
  * Return true if module version is lesser than the given version.
  */
 bool
 IsModuleVersionLessThan(HMODULE aModuleHandle, DWORD aMajor, DWORD aMinor)
@@ -198,8 +203,183 @@ Compatibility::Init()
     // SEH handlers.
     if (!sVectoredExceptionHandler) {
       sVectoredExceptionHandler =
         AddVectoredExceptionHandler(TRUE, &DetectInSendMessageExCompat);
     }
   }
 }
 
+#if !defined(HAVE_64BIT_BUILD)
+
+static bool
+ReadCOMRegDefaultString(const nsString& aRegPath, nsAString& aOutBuf)
+{
+  aOutBuf.Truncate();
+
+  // Get the required size and type of the registry value.
+  // We expect either REG_SZ or REG_EXPAND_SZ.
+  DWORD type;
+  DWORD bufLen = 0;
+  LONG result = ::RegGetValue(HKEY_CLASSES_ROOT, aRegPath.get(),
+                              nullptr, RRF_RT_ANY, &type, nullptr, &bufLen);
+  if (result != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ)) {
+    return false;
+  }
+
+  // Now obtain the value
+  DWORD flags = type == REG_SZ ? RRF_RT_REG_SZ : RRF_RT_REG_EXPAND_SZ;
+
+  aOutBuf.SetLength((bufLen + 1) / sizeof(char16_t));
+
+  result = ::RegGetValue(HKEY_CLASSES_ROOT, aRegPath.get(), nullptr,
+                         flags, nullptr, aOutBuf.BeginWriting(), &bufLen);
+  if (result != ERROR_SUCCESS) {
+    aOutBuf.Truncate();
+    return false;
+  }
+
+  // Truncate terminator
+  aOutBuf.Truncate((bufLen + 1) / sizeof(char16_t) - 1);
+  return true;
+}
+
+static bool
+IsSystemOleAcc(nsCOMPtr<nsIFile>& aFile)
+{
+  // Use FOLDERID_SystemX86 so that Windows doesn't give us a redirected
+  // system32 if we're a 32-bit process running on a 64-bit OS. This is
+  // necessary because the values that we are reading from the registry
+  // are not redirected; they reference SysWOW64 directly.
+  PWSTR systemPath = nullptr;
+  HRESULT hr = ::SHGetKnownFolderPath(FOLDERID_SystemX86, 0, nullptr,
+                                      &systemPath);
+  if (FAILED(hr)) {
+    return false;
+  }
+
+  nsCOMPtr<nsIFile> oleAcc;
+  nsresult rv = NS_NewLocalFile(nsDependentString(systemPath), false,
+                                getter_AddRefs(oleAcc));
+
+  ::CoTaskMemFree(systemPath);
+  systemPath = nullptr;
+
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+
+  rv = oleAcc->Append(NS_LITERAL_STRING("oleacc.dll"));
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+
+  bool isEqual;
+  rv = oleAcc->Equals(aFile, &isEqual);
+  return NS_SUCCEEDED(rv) && isEqual;
+}
+
+static bool
+IsTypelibPreferred()
+{
+  // If IAccessible's Proxy/Stub CLSID is kUniversalMarshalerClsid, then any
+  // external a11y clients are expecting to use a typelib.
+  NS_NAMED_LITERAL_STRING(kUniversalMarshalerClsid,
+      "{00020424-0000-0000-C000-000000000046}");
+
+  NS_NAMED_LITERAL_STRING(kIAccessiblePSClsidPath,
+      "Interface\\{618736E0-3C3D-11CF-810C-00AA00389B71}\\ProxyStubClsid32");
+
+  nsAutoString psClsid;
+  if (!ReadCOMRegDefaultString(kIAccessiblePSClsidPath, psClsid)) {
+    return false;
+  }
+
+  return psClsid.Equals(kUniversalMarshalerClsid,
+                        nsCaseInsensitiveStringComparator());
+}
+
+static bool
+IsIAccessibleTypelibRegistered()
+{
+  // The system default IAccessible typelib is always registered with version
+  // 1.1, under the neutral locale (LCID 0).
+  NS_NAMED_LITERAL_STRING(kIAccessibleTypelibRegPath,
+    "TypeLib\\{1EA4DBF0-3C3B-11CF-810C-00AA00389B71}\\1.1\\0\\win32");
+
+  nsAutoString typelibPath;
+  if (!ReadCOMRegDefaultString(kIAccessibleTypelibRegPath, typelibPath)) {
+    return false;
+  }
+
+  nsCOMPtr<nsIFile> libTestFile;
+  nsresult rv = NS_NewLocalFile(typelibPath, false, getter_AddRefs(libTestFile));
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+
+  return IsSystemOleAcc(libTestFile);
+}
+
+static bool
+IsIAccessiblePSRegistered()
+{
+  NS_NAMED_LITERAL_STRING(kIAccessiblePSRegPath,
+    "CLSID\\{03022430-ABC4-11D0-BDE2-00AA001A1953}\\InProcServer32");
+
+  nsAutoString proxyStubPath;
+  if (!ReadCOMRegDefaultString(kIAccessiblePSRegPath, proxyStubPath)) {
+    return false;
+  }
+
+  nsCOMPtr<nsIFile> libTestFile;
+  nsresult rv = NS_NewLocalFile(proxyStubPath, false, getter_AddRefs(libTestFile));
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+
+  return IsSystemOleAcc(libTestFile);
+}
+
+static bool
+UseIAccessibleProxyStub()
+{
+  // If a typelib is preferred then external clients are expecting to use
+  // typelib marshaling, so we should use that whenever available.
+  if (IsTypelibPreferred() && IsIAccessibleTypelibRegistered()) {
+    return false;
+  }
+
+  // Otherwise we try the proxy/stub
+  if (IsIAccessiblePSRegistered()) {
+    return true;
+  }
+
+  // If we reach this point then something is seriously wrong with the
+  // IAccessible configuration in the computer's registry. Let's annotate this
+  // so that we can easily determine this condition during crash analysis.
+  CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("IAccessibleConfig"),
+                                     NS_LITERAL_CSTRING("NoSystemTypeLibOrPS"));
+  return false;
+}
+
+#endif // !defined(HAVE_64BIT_BUILD)
+
+uint16_t
+Compatibility::GetActCtxResourceId()
+{
+#if defined(HAVE_64BIT_BUILD)
+  // The manifest for 64-bit Windows is embedded with resource ID 64.
+  return 64;
+#else
+  // The manifest for 32-bit Windows is embedded with resource ID 32.
+  // Beginning with Windows 10 Creators Update, 32-bit builds always use the
+  // 64-bit manifest. Older builds of Windows may or may not require the 64-bit
+  // manifest: UseIAccessibleProxyStub() determines the course of action.
+  if (mozilla::IsWin10CreatorsUpdateOrLater() ||
+      UseIAccessibleProxyStub()) {
+    return 64;
+  }
+
+  return 32;
+#endif // defined(HAVE_64BIT_BUILD)
+}
+
--- a/accessible/windows/msaa/Compatibility.h
+++ b/accessible/windows/msaa/Compatibility.h
@@ -34,16 +34,22 @@ public:
    */
   static bool IsWE() { return !!(sConsumers & WE); }
 
   /**
    * Return true if Dolphin mode is enabled.
    */
   static bool IsDolphin() { return !!(sConsumers & DOLPHIN); }
 
+  /**
+   * @return ID of a11y manifest resource to be passed to
+   * mscom::ActivationContext
+   */
+  static uint16_t GetActCtxResourceId();
+
 private:
   Compatibility();
   Compatibility(const Compatibility&);
   Compatibility& operator = (const Compatibility&);
 
   /**
    * Initialize compatibility mode. Called by platform (see Platform.h) during
    * accessibility initialization.
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -5117,17 +5117,17 @@ nsBrowserAccess.prototype = {
     let browser = win.gBrowser.getBrowserForTab(tab);
 
     if (needToFocusWin || (!loadInBackground && aIsExternal))
       win.focus();
 
     return browser;
   },
 
-  openURI(aURI, aOpener, aWhere, aFlags) {
+  openURI(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
     // This function should only ever be called if we're opening a URI
     // from a non-remote browser window (via nsContentTreeOwner).
     if (aOpener && Cu.isCrossProcessWrapper(aOpener)) {
       Cu.reportError("nsBrowserAccess.openURI was passed a CPOW for aOpener. " +
                      "openURI should only ever be called from non-remote browsers.");
       throw Cr.NS_ERROR_FAILURE;
     }
 
@@ -5149,21 +5149,19 @@ nsBrowserAccess.prototype = {
       if (isExternal &&
           gPrefService.prefHasUserValue("browser.link.open_newwindow.override.external"))
         aWhere = gPrefService.getIntPref("browser.link.open_newwindow.override.external");
       else
         aWhere = gPrefService.getIntPref("browser.link.open_newwindow");
     }
 
     let referrer = aOpener ? makeURI(aOpener.location.href) : null;
-    let triggeringPrincipal = null;
     let referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_UNSET;
     if (aOpener && aOpener.document) {
       referrerPolicy = aOpener.document.referrerPolicy;
-      triggeringPrincipal = aOpener.document.nodePrincipal;
     }
     let isPrivate = aOpener
                   ? PrivateBrowsingUtils.isContentWindowPrivate(aOpener)
                   : PrivateBrowsingUtils.isWindowPrivate(window);
 
     switch (aWhere) {
       case Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW :
         // FIXME: Bug 408379. So how come this doesn't send the
@@ -5187,28 +5185,28 @@ nsBrowserAccess.prototype = {
         let forceNotRemote = !!aOpener;
         let userContextId = aOpener && aOpener.document
                               ? aOpener.document.nodePrincipal.originAttributes.userContextId
                               : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
         let openerWindow = (aFlags & Ci.nsIBrowserDOMWindow.OPEN_NO_OPENER) ? null : aOpener;
         let browser = this._openURIInNewTab(aURI, referrer, referrerPolicy,
                                             isPrivate, isExternal,
                                             forceNotRemote, userContextId,
-                                            openerWindow, triggeringPrincipal);
+                                            openerWindow, aTriggeringPrincipal);
         if (browser)
           newWindow = browser.contentWindow;
         break;
       default : // OPEN_CURRENTWINDOW or an illegal value
         newWindow = window.content;
         if (aURI) {
           let loadflags = isExternal ?
                             Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL :
                             Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
           gBrowser.loadURIWithFlags(aURI.spec, {
-                                    triggeringPrincipal,
+                                    aTriggeringPrincipal,
                                     flags: loadflags,
                                     referrerURI: referrer,
                                     referrerPolicy,
                                     });
         }
         if (!gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground"))
           window.focus();
     }
--- a/browser/base/content/test/general/browser_bug520538.js
+++ b/browser/base/content/test/general/browser_bug520538.js
@@ -1,15 +1,16 @@
 function test() {
   var tabCount = gBrowser.tabs.length;
   gBrowser.selectedBrowser.focus();
   window.browserDOMWindow.openURI(makeURI("about:blank"),
                                   null,
                                   Ci.nsIBrowserDOMWindow.OPEN_NEWTAB,
-                                  Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
+                                  Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL,
+                                  Services.scriptSecurityManager.getSystemPrincipal());
   is(gBrowser.tabs.length, tabCount + 1,
      "'--new-tab about:blank' opens a new tab");
   is(gBrowser.selectedTab, gBrowser.tabs[tabCount],
      "'--new-tab about:blank' selects the new tab");
   is(document.activeElement, gURLBar.inputField,
      "'--new-tab about:blank' focuses the location bar");
   gBrowser.removeCurrentTab();
 }
--- a/browser/base/content/test/general/browser_bug537474.js
+++ b/browser/base/content/test/general/browser_bug537474.js
@@ -1,7 +1,8 @@
 add_task(async function() {
   let browserLoadedPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
   window.browserDOMWindow.openURI(makeURI("about:"), null,
-                                  Ci.nsIBrowserDOMWindow.OPEN_CURRENTWINDOW, null)
+                                  Ci.nsIBrowserDOMWindow.OPEN_CURRENTWINDOW, null,
+                                  Services.scriptSecurityManager.getSystemPrincipal())
   await browserLoadedPromise;
   is(gBrowser.currentURI.spec, "about:", "page loads in the current content window");
 });
--- a/browser/base/content/test/urlbar/browser_bug562649.js
+++ b/browser/base/content/test/urlbar/browser_bug562649.js
@@ -1,14 +1,15 @@
 function test() {
   const URI = "data:text/plain,bug562649";
   window.browserDOMWindow.openURI(makeURI(URI),
                                   null,
                                   Ci.nsIBrowserDOMWindow.OPEN_NEWTAB,
-                                  Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
+                                  Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL,
+                                  Services.scriptSecurityManager.getSystemPrincipal());
 
   is(gBrowser.userTypedValue, URI, "userTypedValue matches test URI");
   is(gURLBar.value, URI, "location bar value matches test URI");
 
   gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   gBrowser.removeCurrentTab({ skipPermitUnload: true });
   is(gBrowser.userTypedValue, URI, "userTypedValue matches test URI after switching tabs");
   is(gURLBar.value, URI, "location bar value matches test URI after switching tabs");
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -338,17 +338,18 @@ nsBrowserContentHandler.prototype = {
       }
     } catch (e) {
       Components.utils.reportError(e);
     }
 
     try {
       while ((uriparam = cmdLine.handleFlagWithParam("new-tab", false))) {
         let uri = resolveURIInternal(cmdLine, uriparam);
-        handURIToExistingBrowser(uri, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine);
+        handURIToExistingBrowser(uri, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine, false,
+                                 Services.scriptSecurityManager.getSystemPrincipal());
         cmdLine.preventDefault = true;
       }
     } catch (e) {
       Components.utils.reportError(e);
     }
 
     var chromeParam = cmdLine.handleFlagWithParam("chrome", false);
     if (chromeParam) {
@@ -386,17 +387,18 @@ nsBrowserContentHandler.prototype = {
     }
     if (cmdLine.handleFlag("silent", false))
       cmdLine.preventDefault = true;
 
     try {
       var privateWindowParam = cmdLine.handleFlagWithParam("private-window", false);
       if (privateWindowParam) {
         let resolvedURI = resolveURIInternal(cmdLine, privateWindowParam);
-        handURIToExistingBrowser(resolvedURI, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine, true);
+        handURIToExistingBrowser(resolvedURI, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine, true,
+                                 Services.scriptSecurityManager.getSystemPrincipal());
         cmdLine.preventDefault = true;
       }
     } catch (e) {
       if (e.result != Components.results.NS_ERROR_INVALID_ARG) {
         throw e;
       }
       // NS_ERROR_INVALID_ARG is thrown when flag exists, but has no param.
       if (cmdLine.handleFlag("private-window", false)) {
@@ -602,18 +604,18 @@ nsBrowserContentHandler.prototype = {
       if (!webNavInfo.isTypeSupported(contentType, null)) {
         throw NS_ERROR_WONT_HANDLE_CONTENT;
       }
     } catch (e) {
       throw NS_ERROR_WONT_HANDLE_CONTENT;
     }
 
     request.QueryInterface(nsIChannel);
-    handURIToExistingBrowser(request.URI,
-      nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW, null);
+    handURIToExistingBrowser(request.URI, nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW, null, false,
+                             request.loadInfo.triggeringPrincipal);
     request.cancel(NS_BINDING_ABORTED);
   },
 
   /* nsICommandLineValidator */
   validate: function bch_validate(cmdLine) {
     // Other handlers may use osint so only handle the osint flag if the url
     // flag is also present and the command line is valid.
     var osintFlagIdx = cmdLine.findFlag("osint", false);
@@ -637,17 +639,17 @@ nsBrowserContentHandler.prototype = {
         throw NS_ERROR_ABORT;
       }
       cmdLine.handleFlag("osint", false)
     }
   },
 };
 var gBrowserContentHandler = new nsBrowserContentHandler();
 
-function handURIToExistingBrowser(uri, location, cmdLine, forcePrivate) {
+function handURIToExistingBrowser(uri, location, cmdLine, forcePrivate, triggeringPrincipal) {
   if (!shouldLoadURI(uri))
     return;
 
   // Unless using a private window is forced, open external links in private
   // windows only if we're in perma-private mode.
   var allowPrivate = forcePrivate || PrivateBrowsingUtils.permanentPrivateBrowsing;
   var navWin = RecentWindow.getMostRecentBrowserWindow({private: allowPrivate});
   if (!navWin) {
@@ -662,17 +664,17 @@ function handURIToExistingBrowser(uri, l
 
   var navNav = navWin.QueryInterface(nsIInterfaceRequestor)
                      .getInterface(nsIWebNavigation);
   var rootItem = navNav.QueryInterface(nsIDocShellTreeItem).rootTreeItem;
   var rootWin = rootItem.QueryInterface(nsIInterfaceRequestor)
                         .getInterface(nsIDOMWindow);
   var bwin = rootWin.QueryInterface(nsIDOMChromeWindow).browserDOMWindow;
   bwin.openURI(uri, null, location,
-               nsIBrowserDOMWindow.OPEN_EXTERNAL);
+               nsIBrowserDOMWindow.OPEN_EXTERNAL, triggeringPrincipal);
 }
 
 function nsDefaultCommandLineHandler() {
 }
 
 nsDefaultCommandLineHandler.prototype = {
   classID: Components.ID("{47cd0651-b1be-4a0f-b5c4-10e5a573ef71}"),
 
@@ -737,17 +739,18 @@ nsDefaultCommandLineHandler.prototype = 
     }
 
     if (urilist.length) {
       if (cmdLine.state != nsICommandLine.STATE_INITIAL_LAUNCH &&
           urilist.length == 1) {
         // Try to find an existing window and load our URI into the
         // current tab, new tab, or new window as prefs determine.
         try {
-          handURIToExistingBrowser(urilist[0], nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW, cmdLine);
+          handURIToExistingBrowser(urilist[0], nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW, cmdLine, false,
+                                   Services.scriptSecurityManager.getSystemPrincipal());
           return;
         } catch (e) {
         }
       }
 
       var URLlist = urilist.filter(shouldLoadURI).map(u => u.spec);
       if (URLlist.length) {
         openWindow(null, gBrowserContentHandler.chromeURL, "_blank",
--- a/devtools/client/responsive.html/browser/tunnel.js
+++ b/devtools/client/responsive.html/browser/tunnel.js
@@ -236,23 +236,28 @@ function tunnelToInnerBrowser(outer, inn
       //   * Specific target names (everything treated as _blank)
       //   * Window features
       //   * window.opener
       // These things are deferred for now, since content which does depend on them seems
       // outside the main focus of RDM.
       let { detail } = event;
       event.preventDefault();
       let uri = Services.io.newURI(detail.url);
+      let sourceNode = event.dataTransfer.mozSourceNode;
+      let triggeringPrincipal = sourceNode
+        ? sourceNode.nodePrincipal
+        : Services.scriptSecurityManager.getSystemPrincipal();
       // This API is used mainly because it's near the path used for <a target/> with
       // regular browser tabs (which calls `openURIInFrame`).  The more elaborate APIs
       // that support openers, window features, etc. didn't seem callable from JS and / or
       // this event doesn't give enough info to use them.
       browserWindow.browserDOMWindow
         .openURI(uri, null, Ci.nsIBrowserDOMWindow.OPEN_NEWTAB,
-                 Ci.nsIBrowserDOMWindow.OPEN_NEW);
+                 Ci.nsIBrowserDOMWindow.OPEN_NEW,
+                 triggeringPrincipal);
     },
 
     stop() {
       let tab = gBrowser.getTabForBrowser(outer);
       let filteredProgressListener = gBrowser._tabFilters.get(tab);
 
       // The browser's state has changed over time while the tunnel was active.  Push the
       // the current state down to the inner browser, so that it follows the content in
--- a/dom/base/nsOpenURIInFrameParams.cpp
+++ b/dom/base/nsOpenURIInFrameParams.cpp
@@ -36,15 +36,30 @@ NS_IMETHODIMP
 nsOpenURIInFrameParams::GetIsPrivate(bool* aIsPrivate)
 {
   NS_ENSURE_ARG_POINTER(aIsPrivate);
   *aIsPrivate = mOpenerOriginAttributes.mPrivateBrowsingId > 0;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsOpenURIInFrameParams::GetTriggeringPrincipal(nsIPrincipal** aTriggeringPrincipal)
+{
+  NS_ADDREF(*aTriggeringPrincipal = mTriggeringPrincipal);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsOpenURIInFrameParams::SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal)
+{
+  NS_ENSURE_TRUE(aTriggeringPrincipal, NS_ERROR_INVALID_ARG);
+  mTriggeringPrincipal = aTriggeringPrincipal;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsOpenURIInFrameParams::GetOpenerOriginAttributes(JSContext* aCx,
                                                   JS::MutableHandle<JS::Value> aValue)
 {
   bool ok = ToJSValue(aCx, mOpenerOriginAttributes, aValue);
   NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
   return NS_OK;
 }
--- a/dom/base/nsOpenURIInFrameParams.h
+++ b/dom/base/nsOpenURIInFrameParams.h
@@ -20,9 +20,10 @@ public:
 
   explicit nsOpenURIInFrameParams(const mozilla::OriginAttributes& aOriginAttributes);
 
 private:
   ~nsOpenURIInFrameParams();
 
   mozilla::OriginAttributes mOpenerOriginAttributes;
   nsString mReferrer;
+  nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
 };
--- a/dom/interfaces/base/nsIBrowserDOMWindow.idl
+++ b/dom/interfaces/base/nsIBrowserDOMWindow.idl
@@ -4,22 +4,24 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface mozIDOMWindowProxy;
 interface nsIDOMWindow;
 interface nsIURI;
 interface nsIFrameLoaderOwner;
+interface nsIPrincipal;
 
 [scriptable, uuid(e774db14-79ac-4156-a7a3-aa3fd0a22c10)]
 interface nsIOpenURIInFrameParams : nsISupports
 {
   attribute DOMString referrer;
   readonly attribute boolean isPrivate;
+  attribute nsIPrincipal triggeringPrincipal;
 
   [implicit_jscontext]
   readonly attribute jsval openerOriginAttributes;
 };
 
 [scriptable, uuid(9d17f3dd-672b-451e-afd2-b1115df780d5)]
 
 /**
@@ -92,21 +94,22 @@ interface nsIBrowserDOMWindow : nsISuppo
    * @param aURI the URI to open. null is allowed.  If null is passed in, no
    *             load will be done, though the window the load would have
    *             happened in will be returned.
    * @param aWhere see possible values described above.
    * @param aOpener window requesting the open (can be null).
    * @param aFlags flags which control the behavior of the load. The
    *               OPEN_EXTERNAL/OPEN_NEW flag is only used when
    *               aWhere == OPEN_DEFAULTWINDOW.
+   * @param aTriggeringPrincipal the principal that triggered the load of aURI
    * @return the window into which the URI was opened.
   */
   mozIDOMWindowProxy
   openURI(in nsIURI aURI, in mozIDOMWindowProxy aOpener,
-          in short aWhere, in long aFlags);
+          in short aWhere, in long aFlags, in nsIPrincipal aTriggeringPrincipal);
 
   /**
    * As above, but return the nsIFrameLoaderOwner for the new window.
    *
    * Additional Parameters:
    * @param aNextTabParentId The TabParent to associate the window with
    * @param aName The name to give the window opened in the new tab.
    * @return The nsIFrameLoaderOwner for the newly opened window.
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -67,16 +67,17 @@
 #include "mozilla/widget/ScreenManager.h"
 #include "mozilla/widget/WidgetMessageUtils.h"
 #include "nsBaseDragService.h"
 #include "mozilla/media/MediaChild.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/WebBrowserPersistDocumentChild.h"
 #include "imgLoader.h"
 #include "GMPServiceChild.h"
+#include "NullPrincipal.h"
 
 #ifdef MOZ_GECKO_PROFILER
 #include "ChildProfilerController.h"
 #endif
 
 #if defined(MOZ_CONTENT_SANDBOX)
 #include "mozilla/SandboxSettings.h"
 #if defined(XP_WIN)
@@ -685,25 +686,29 @@ ContentChild::ProvideWindow(mozIDOMWindo
   return ProvideWindowCommon(nullptr, aParent, false, aChromeFlags,
                              aCalledFromJS, aPositionSpecified,
                              aSizeSpecified, aURI, aName, aFeatures,
                              aForceNoOpener, aWindowIsNew, aReturn);
 }
 
 static nsresult
 GetWindowParamsFromParent(mozIDOMWindowProxy* aParent,
-                          nsACString& aBaseURIString, float* aFullZoom)
+                          nsACString& aBaseURIString, float* aFullZoom,
+                          nsIPrincipal** aTriggeringPrincipal)
 {
   *aFullZoom = 1.0f;
   auto* opener = nsPIDOMWindowOuter::From(aParent);
   if (!opener) {
+    nsCOMPtr<nsIPrincipal> nullPrincipal = NullPrincipal::Create();
+    NS_ADDREF(*aTriggeringPrincipal = nullPrincipal);
     return NS_OK;
   }
 
   nsCOMPtr<nsIDocument> doc = opener->GetDoc();
+  NS_ADDREF(*aTriggeringPrincipal = doc->NodePrincipal());
   nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
   if (!baseURI) {
     NS_ERROR("nsIDocument didn't return a base URI");
     return NS_ERROR_FAILURE;
   }
 
   baseURI->GetSpec(aBaseURIString);
 
@@ -773,33 +778,36 @@ ContentChild::ProvideWindowCommon(TabChi
     }
   }
 
   // If we're in a content process and we have noopener set, there's no reason
   // to load in our process, so let's load it elsewhere!
   if (loadInDifferentProcess) {
     nsAutoCString baseURIString;
     float fullZoom;
-    rv = GetWindowParamsFromParent(aParent, baseURIString, &fullZoom);
+    nsCOMPtr<nsIPrincipal> triggeringPrincipal;
+    rv = GetWindowParamsFromParent(aParent, baseURIString, &fullZoom,
+                                   getter_AddRefs(triggeringPrincipal));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     URIParams uriToLoad;
     SerializeURI(aURI, uriToLoad);
     Unused << SendCreateWindowInDifferentProcess(aTabOpener,
                                                  aChromeFlags,
                                                  aCalledFromJS,
                                                  aPositionSpecified,
                                                  aSizeSpecified,
                                                  uriToLoad,
                                                  features,
                                                  baseURIString,
                                                  fullZoom,
-                                                 name);
+                                                 name,
+                                                 Principal(triggeringPrincipal));
 
     // We return NS_ERROR_ABORT, so that the caller knows that we've abandoned
     // the window open as far as it is concerned.
     return NS_ERROR_ABORT;
   }
 
   if (aTabOpener) {
     PopupIPCTabContext context;
@@ -885,28 +893,31 @@ ContentChild::ProvideWindowCommon(TabChi
     // NOTE: BrowserFrameOpenWindowPromise is the same type as
     // CreateWindowPromise, and this code depends on that fact.
     windowCreated =
       newChild->SendBrowserFrameOpenWindow(aTabOpener, renderFrame, NS_ConvertUTF8toUTF16(url),
                                            name, NS_ConvertUTF8toUTF16(features));
   } else {
     nsAutoCString baseURIString;
     float fullZoom;
-    rv = GetWindowParamsFromParent(aParent, baseURIString, &fullZoom);
+    nsCOMPtr<nsIPrincipal> triggeringPrincipal;
+    rv = GetWindowParamsFromParent(aParent, baseURIString, &fullZoom,
+                                   getter_AddRefs(triggeringPrincipal));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     windowCreated =
       SendCreateWindow(aTabOpener, newChild, renderFrame,
                        aChromeFlags, aCalledFromJS, aPositionSpecified,
                        aSizeSpecified,
                        features,
                        baseURIString,
-                       fullZoom);
+                       fullZoom,
+                       Principal(triggeringPrincipal));
   }
 
   // Await the promise being resolved. When the promise is resolved, we'll set
   // the `ready` local variable, which will cause us to exit our nested event
   // loop.
   //
   // NOTE: We need to run this callback on the StableStateEventTarget because we
   // need to resolve our runnable and exit from the nested event loop before
@@ -2744,39 +2755,16 @@ ContentChild::DeallocPOfflineCacheUpdate
 {
   OfflineCacheUpdateChild* offlineCacheUpdate =
     static_cast<OfflineCacheUpdateChild*>(actor);
   NS_RELEASE(offlineCacheUpdate);
   return true;
 }
 
 mozilla::ipc::IPCResult
-ContentChild::RecvLoadPluginResult(const uint32_t& aPluginId,
-                                   const bool& aResult)
-{
-  nsresult rv;
-  Endpoint<PPluginModuleParent> endpoint;
-  bool finalResult = aResult &&
-                     SendConnectPluginBridge(aPluginId, &rv, &endpoint) &&
-                     NS_SUCCEEDED(rv);
-  plugins::PluginModuleContentParent::OnLoadPluginResult(aPluginId,
-                                                         finalResult,
-                                                         Move(endpoint));
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
-ContentChild::RecvAssociatePluginId(const uint32_t& aPluginId,
-                                    const base::ProcessId& aProcessId)
-{
-  plugins::PluginModuleContentParent::AssociatePluginId(aPluginId, aProcessId);
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
 ContentChild::RecvDomainSetChanged(const uint32_t& aSetType,
                                    const uint32_t& aChangeType,
                                    const OptionalURIParams& aDomain)
 {
   if (aChangeType == ACTIVATE_POLICY) {
     if (mPolicy) {
       return IPC_OK();
     }
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -433,22 +433,16 @@ public:
   void AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS);
 
   void RemoveIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS);
 
   virtual mozilla::ipc::IPCResult RecvNotifyIdleObserver(const uint64_t& aObserver,
                                                          const nsCString& aTopic,
                                                          const nsString& aData) override;
 
-  virtual mozilla::ipc::IPCResult RecvAssociatePluginId(const uint32_t& aPluginId,
-                                                        const base::ProcessId& aProcessId) override;
-
-  virtual mozilla::ipc::IPCResult RecvLoadPluginResult(const uint32_t& aPluginId,
-                                                       const bool& aResult) override;
-
   virtual mozilla::ipc::IPCResult RecvUpdateWindow(const uintptr_t& aChildId) override;
 
   virtual mozilla::ipc::IPCResult RecvDomainSetChanged(const uint32_t& aSetType,
                                                        const uint32_t& aChangeType,
                                                        const OptionalURIParams& aDomain) override;
 
   virtual mozilla::ipc::IPCResult RecvShutdown() override;
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1099,18 +1099,17 @@ ContentParent::RecvCreateGMPService()
 
 mozilla::ipc::IPCResult
 ContentParent::RecvLoadPlugin(const uint32_t& aPluginId,
                               nsresult* aRv,
                               uint32_t* aRunID,
                               Endpoint<PPluginModuleParent>* aEndpoint)
 {
   *aRv = NS_OK;
-  if (!mozilla::plugins::SetupBridge(aPluginId, this, false, aRv, aRunID,
-                                     aEndpoint)) {
+  if (!mozilla::plugins::SetupBridge(aPluginId, this, aRv, aRunID, aEndpoint)) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 ContentParent::RecvUngrabPointer(const uint32_t& aTime)
 {
@@ -1136,17 +1135,17 @@ ContentParent::RecvConnectPluginBridge(c
                                        nsresult* aRv,
                                        Endpoint<PPluginModuleParent>* aEndpoint)
 {
   *aRv = NS_OK;
   // We don't need to get the run ID for the plugin, since we already got it
   // in the first call to SetupBridge in RecvLoadPlugin, so we pass in a dummy
   // pointer and just throw it away.
   uint32_t dummy = 0;
-  if (!mozilla::plugins::SetupBridge(aPluginId, this, true, aRv, &dummy, aEndpoint)) {
+  if (!mozilla::plugins::SetupBridge(aPluginId, this, aRv, &dummy, aEndpoint)) {
     return IPC_FAIL(this, "SetupBridge failed");
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 ContentParent::RecvGetBlocklistState(const uint32_t& aPluginId,
                                      uint32_t* aState)
@@ -4499,17 +4498,18 @@ ContentParent::CommonCreateWindow(PBrows
                                   nsIURI* aURIToLoad,
                                   const nsCString& aFeatures,
                                   const nsCString& aBaseURI,
                                   const float& aFullZoom,
                                   uint64_t aNextTabParentId,
                                   const nsString& aName,
                                   nsresult& aResult,
                                   nsCOMPtr<nsITabParent>& aNewTabParent,
-                                  bool* aWindowIsNew)
+                                  bool* aWindowIsNew,
+                                  nsIPrincipal* aTriggeringPrincipal)
 
 {
   // The content process should never be in charge of computing whether or
   // not a window should be private or remote - the parent will do that.
   const uint32_t badFlags = nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW |
                             nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW |
                             nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME |
                             nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
@@ -4577,16 +4577,18 @@ ContentParent::CommonCreateWindow(PBrows
     if (NS_WARN_IF(!browserDOMWin)) {
       aResult = NS_ERROR_ABORT;
       return IPC_OK();
     }
 
     nsCOMPtr<nsIOpenURIInFrameParams> params =
       new nsOpenURIInFrameParams(openerOriginAttributes);
     params->SetReferrer(NS_ConvertUTF8toUTF16(aBaseURI));
+    MOZ_ASSERT(aTriggeringPrincipal, "need a valid triggeringPrincipal");
+    params->SetTriggeringPrincipal(aTriggeringPrincipal);
 
     nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
     aResult = browserDOMWin->OpenURIInFrame(aURIToLoad, params, openLocation,
                                             nsIBrowserDOMWindow::OPEN_NEW,
                                             aNextTabParentId, aName,
                                             getter_AddRefs(frameLoaderOwner));
     if (NS_SUCCEEDED(aResult) && frameLoaderOwner) {
       RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
@@ -4642,16 +4644,17 @@ ContentParent::CommonCreateWindow(PBrows
     if (NS_WARN_IF(!newBrowserDOMWin)) {
       aResult = NS_ERROR_ABORT;
       return IPC_OK();
     }
     nsCOMPtr<mozIDOMWindowProxy> win;
     aResult = newBrowserDOMWin->OpenURI(aURIToLoad, openerWindow,
                                         nsIBrowserDOMWindow::OPEN_CURRENTWINDOW,
                                         nsIBrowserDOMWindow::OPEN_NEW,
+                                        aTriggeringPrincipal,
                                         getter_AddRefs(win));
   }
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
@@ -4659,16 +4662,17 @@ ContentParent::RecvCreateWindow(PBrowser
                                 PRenderFrameParent* aRenderFrame,
                                 const uint32_t& aChromeFlags,
                                 const bool& aCalledFromJS,
                                 const bool& aPositionSpecified,
                                 const bool& aSizeSpecified,
                                 const nsCString& aFeatures,
                                 const nsCString& aBaseURI,
                                 const float& aFullZoom,
+                                const IPC::Principal& aTriggeringPrincipal,
                                 CreateWindowResolver&& aResolve)
 {
   nsresult rv = NS_OK;
   CreatedWindowInfo cwi;
 
   // We always expect to open a new window here. If we don't, it's an error.
   cwi.windowOpened() = true;
   cwi.layersId() = 0;
@@ -4703,17 +4707,18 @@ ContentParent::RecvCreateWindow(PBrowser
   sNextTabParents.Put(nextTabParentId, newTab);
 
   nsCOMPtr<nsITabParent> newRemoteTab;
   mozilla::ipc::IPCResult ipcResult =
     CommonCreateWindow(aThisTab, /* aSetOpener = */ true, aChromeFlags,
                        aCalledFromJS, aPositionSpecified, aSizeSpecified,
                        nullptr, aFeatures, aBaseURI, aFullZoom,
                        nextTabParentId, NullString(), rv,
-                       newRemoteTab, &cwi.windowOpened());
+                       newRemoteTab, &cwi.windowOpened(),
+                       aTriggeringPrincipal);
   if (!ipcResult) {
     return ipcResult;
   }
 
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return IPC_OK();
   }
 
@@ -4746,28 +4751,29 @@ ContentParent::RecvCreateWindowInDiffere
   const uint32_t& aChromeFlags,
   const bool& aCalledFromJS,
   const bool& aPositionSpecified,
   const bool& aSizeSpecified,
   const URIParams& aURIToLoad,
   const nsCString& aFeatures,
   const nsCString& aBaseURI,
   const float& aFullZoom,
-  const nsString& aName)
+  const nsString& aName,
+  const IPC::Principal& aTriggeringPrincipal)
 {
   nsCOMPtr<nsITabParent> newRemoteTab;
   bool windowIsNew;
   nsCOMPtr<nsIURI> uriToLoad = DeserializeURI(aURIToLoad);
   nsresult rv;
   mozilla::ipc::IPCResult ipcResult =
     CommonCreateWindow(aThisTab, /* aSetOpener = */ false, aChromeFlags,
                        aCalledFromJS, aPositionSpecified, aSizeSpecified,
                        uriToLoad, aFeatures, aBaseURI, aFullZoom,
                        /* aNextTabParentId = */ 0, aName, rv,
-                       newRemoteTab, &windowIsNew);
+                       newRemoteTab, &windowIsNew, aTriggeringPrincipal);
   if (!ipcResult) {
     return ipcResult;
   }
 
   if (NS_FAILED(rv)) {
     NS_WARNING("Call to CommonCreateWindow failed.");
   }
 
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -531,29 +531,31 @@ public:
                    layout::PRenderFrameParent* aRenderFrame,
                    const uint32_t& aChromeFlags,
                    const bool& aCalledFromJS,
                    const bool& aPositionSpecified,
                    const bool& aSizeSpecified,
                    const nsCString& aFeatures,
                    const nsCString& aBaseURI,
                    const float& aFullZoom,
+                   const IPC::Principal& aTriggeringPrincipal,
                    CreateWindowResolver&& aResolve) override;
 
   virtual mozilla::ipc::IPCResult RecvCreateWindowInDifferentProcess(
     PBrowserParent* aThisTab,
     const uint32_t& aChromeFlags,
     const bool& aCalledFromJS,
     const bool& aPositionSpecified,
     const bool& aSizeSpecified,
     const URIParams& aURIToLoad,
     const nsCString& aFeatures,
     const nsCString& aBaseURI,
     const float& aFullZoom,
-    const nsString& aName) override;
+    const nsString& aName,
+    const IPC::Principal& aTriggeringPrincipal) override;
 
   static bool AllocateLayerTreeId(TabParent* aTabParent, uint64_t* aId);
 
   static void
   BroadcastBlobURLRegistration(const nsACString& aURI,
                                BlobImpl* aBlobImpl,
                                nsIPrincipal* aPrincipal,
                                ContentParent* aIgnoreThisCP = nullptr);
@@ -704,17 +706,18 @@ private:
                      nsIURI* aURIToLoad,
                      const nsCString& aFeatures,
                      const nsCString& aBaseURI,
                      const float& aFullZoom,
                      uint64_t aNextTabParentId,
                      const nsString& aName,
                      nsresult& aResult,
                      nsCOMPtr<nsITabParent>& aNewTabParent,
-                     bool* aWindowIsNew);
+                     bool* aWindowIsNew,
+                     nsIPrincipal* aTriggeringPrincipal);
 
   FORWARD_SHMEM_ALLOCATOR_TO(PContentParent)
 
   explicit ContentParent(int32_t aPluginID)
     : ContentParent(nullptr, EmptyString(), aPluginID)
   {}
   ContentParent(ContentParent* aOpener,
                 const nsAString& aRemoteType)
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -484,29 +484,16 @@ child:
     async LoadAndRegisterSheet(URIParams uri, uint32_t type);
     async UnregisterSheet(URIParams uri, uint32_t type);
 
     /**
      * Notify idle observers in the child
      */
     async NotifyIdleObserver(uint64_t observerId, nsCString topic, nsString str);
 
-    /**
-     * Called during plugin initialization to map a plugin id to a child process
-     * id.
-     */
-    async AssociatePluginId(uint32_t aPluginId, ProcessId aProcessId);
-
-    /**
-     * This call is used by async plugin initialization to notify the
-     * PluginModuleContentParent that the PluginModuleChromeParent's async
-     * init has completed.
-     */
-    async LoadPluginResult(uint32_t aPluginId, bool aResult);
-
     async InvokeDragSession(IPCDataTransfer[] transfers, uint32_t action);
 
     async EndDragSession(bool aDoneDrag, bool aUserCancelled,
                          LayoutDeviceIntPoint aDragEndPoint,
                          uint32_t aKeyModifiers);
 
     async DomainSetChanged(uint32_t aSetType, uint32_t aChangeType, OptionalURIParams aDomain);
 
@@ -986,30 +973,32 @@ parent:
                        PBrowser aNewTab,
                        PRenderFrame aRenderFrame,
                        uint32_t aChromeFlags,
                        bool aCalledFromJS,
                        bool aPositionSpecified,
                        bool aSizeSpecified,
                        nsCString aFeatures,
                        nsCString aBaseURI,
-                       float aFullZoom)
+                       float aFullZoom,
+                       Principal aTriggeringPrincipal)
         returns (CreatedWindowInfo window);
 
     async CreateWindowInDifferentProcess(
       PBrowser aThisTab,
       uint32_t aChromeFlags,
       bool aCalledFromJS,
       bool aPositionSpecified,
       bool aSizeSpecified,
       URIParams aURIToLoad,
       nsCString aFeatures,
       nsCString aBaseURI,
       float aFullZoom,
-      nsString aName);
+      nsString aName,
+      Principal aTriggeringPrincipal);
 
     sync GetAndroidSystemInfo()
         returns (AndroidSystemInfo info);
 
     /**
      * Tells the parent to ungrab the pointer on the default display.
      *
      * This is for GTK platforms where we have to ensure the pointer ungrab happens in the
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -3439,17 +3439,17 @@ TabChildSHistoryListener::OnRequestCross
   if (!tabChild) {
     return NS_ERROR_FAILURE;
   }
 
   return tabChild->SendRequestCrossBrowserNavigation(aIndex) ?
            NS_OK : NS_ERROR_FAILURE;
 }
 
-TabChildGlobal::TabChildGlobal(TabChildBase* aTabChild)
+TabChildGlobal::TabChildGlobal(TabChild* aTabChild)
 : mTabChild(aTabChild)
 {
   SetIsNotDOMBinding();
 }
 
 TabChildGlobal::~TabChildGlobal()
 {
 }
@@ -3541,8 +3541,37 @@ TabChildGlobal::GetPrincipal()
 }
 
 JSObject*
 TabChildGlobal::GetGlobalJSObject()
 {
   NS_ENSURE_TRUE(mTabChild, nullptr);
   return mTabChild->GetGlobal();
 }
+
+nsresult
+TabChildGlobal::Dispatch(const char* aName,
+                         TaskCategory aCategory,
+                         already_AddRefed<nsIRunnable>&& aRunnable)
+{
+  if (mTabChild && mTabChild->TabGroup()) {
+    return mTabChild->TabGroup()->Dispatch(aName, aCategory, Move(aRunnable));
+  }
+  return DispatcherTrait::Dispatch(aName, aCategory, Move(aRunnable));
+}
+
+nsISerialEventTarget*
+TabChildGlobal::EventTargetFor(TaskCategory aCategory) const
+{
+  if (mTabChild && mTabChild->TabGroup()) {
+    return mTabChild->TabGroup()->EventTargetFor(aCategory);
+  }
+  return DispatcherTrait::EventTargetFor(aCategory);
+}
+
+AbstractThread*
+TabChildGlobal::AbstractMainThreadFor(TaskCategory aCategory)
+{
+  if (mTabChild && mTabChild->TabGroup()) {
+    return mTabChild->TabGroup()->AbstractMainThreadFor(aCategory);
+  }
+  return DispatcherTrait::AbstractMainThreadFor(aCategory);
+}
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -40,18 +40,20 @@
 #include "AudioChannelService.h"
 #include "PuppetWidget.h"
 #include "mozilla/layers/GeckoContentController.h"
 #include "nsISHistoryListener.h"
 #include "nsIPartialSHistoryListener.h"
 
 class nsIDOMWindowUtils;
 class nsIHttpChannel;
+class nsISerialEventTarget;
 
 namespace mozilla {
+class AbstractThread;
 namespace layout {
 class RenderFrameChild;
 } // namespace layout
 
 namespace layers {
 class APZChild;
 class APZEventState;
 class AsyncDragMetrics;
@@ -64,26 +66,25 @@ struct AutoCacheNativeKeyCommands;
 } // namespace widget
 
 namespace dom {
 
 class TabChild;
 class TabGroup;
 class ClonedMessageData;
 class CoalescedWheelData;
-class TabChildBase;
 
 class TabChildGlobal : public DOMEventTargetHelper,
                        public nsIContentFrameMessageManager,
                        public nsIScriptObjectPrincipal,
                        public nsIGlobalObject,
                        public nsSupportsWeakReference
 {
 public:
-  explicit TabChildGlobal(TabChildBase* aTabChild);
+  explicit TabChildGlobal(TabChild* aTabChild);
   void Init();
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TabChildGlobal, DOMEventTargetHelper)
   NS_FORWARD_SAFE_NSIMESSAGELISTENERMANAGER(mMessageManager)
   NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
   NS_FORWARD_SAFE_NSIMESSAGEMANAGERGLOBAL(mMessageManager)
   NS_IMETHOD SendSyncMessage(const nsAString& aMessageName,
                              JS::Handle<JS::Value> aObject,
@@ -144,18 +145,29 @@ public:
   virtual nsIPrincipal* GetPrincipal() override;
   virtual JSObject* GetGlobalJSObject() override;
 
   virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override
   {
     MOZ_CRASH("TabChildGlobal doesn't use DOM bindings!");
   }
 
+  // Dispatch a runnable related to the global.
+  virtual nsresult Dispatch(const char* aName,
+                            mozilla::TaskCategory aCategory,
+                            already_AddRefed<nsIRunnable>&& aRunnable) override;
+
+  virtual nsISerialEventTarget*
+  EventTargetFor(mozilla::TaskCategory aCategory) const override;
+
+  virtual AbstractThread*
+  AbstractMainThreadFor(mozilla::TaskCategory aCategory) override;
+
   nsCOMPtr<nsIContentFrameMessageManager> mMessageManager;
-  RefPtr<TabChildBase> mTabChild;
+  RefPtr<TabChild> mTabChild;
 
 protected:
   ~TabChildGlobal();
 };
 
 class ContentListener final : public nsIDOMEventListener
 {
 public:
--- a/dom/media/eme/mediadrm/MediaDrmCDMProxy.h
+++ b/dom/media/eme/mediadrm/MediaDrmCDMProxy.h
@@ -23,17 +23,17 @@
 using namespace mozilla::java;
 
 namespace mozilla {
 
 class MediaDrmCDMCallbackProxy;
 class MediaDrmCDMProxy : public CDMProxy {
 public:
 
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDrmCDMProxy)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDrmCDMProxy, override)
 
   MediaDrmCDMProxy(dom::MediaKeys* aKeys,
                    const nsAString& aKeySystem,
                    bool aDistinctiveIdentifierRequired,
                    bool aPersistentStateRequired,
                    nsIEventTarget* aMainThread);
 
   void Init(PromiseId aPromiseId,
--- a/dom/payments/PaymentRequest.cpp
+++ b/dom/payments/PaymentRequest.cpp
@@ -585,34 +585,46 @@ PaymentRequest::UpdateShippingAddress(co
                                         aPostalCode, aSortingCode, aLanguageCode,
                                         aOrganization, aRecipient, aPhone);
 
   // Fire shippingaddresschange event
   return DispatchUpdateEvent(NS_LITERAL_STRING("shippingaddresschange"));
 }
 
 void
+PaymentRequest::SetShippingOption(const nsAString& aShippingOption)
+{
+  mShippingOption = aShippingOption;
+}
+
+void
 PaymentRequest::GetShippingOption(nsAString& aRetVal) const
 {
   aRetVal = mShippingOption;
 }
 
 nsresult
 PaymentRequest::UpdateShippingOption(const nsAString& aShippingOption)
 {
   mShippingOption = aShippingOption;
 
   // Fire shippingaddresschange event
   return DispatchUpdateEvent(NS_LITERAL_STRING("shippingoptionchange"));
 }
 
+void
+PaymentRequest::SetShippingType(const Nullable<PaymentShippingType>& aShippingType)
+{
+  mShippingType = aShippingType;
+}
+
 Nullable<PaymentShippingType>
 PaymentRequest::GetShippingType() const
 {
-  return nullptr;
+  return mShippingType;
 }
 
 PaymentRequest::~PaymentRequest()
 {
 }
 
 JSObject*
 PaymentRequest::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
--- a/dom/payments/PaymentRequest.h
+++ b/dom/payments/PaymentRequest.h
@@ -101,22 +101,25 @@ public:
                                  const nsAString& aDependentLocality,
                                  const nsAString& aPostalCode,
                                  const nsAString& aSortingCode,
                                  const nsAString& aLanguageCode,
                                  const nsAString& aOrganization,
                                  const nsAString& aRecipient,
                                  const nsAString& aPhone);
 
+
+  void SetShippingOption(const nsAString& aShippingOption);
   void GetShippingOption(nsAString& aRetVal) const;
   nsresult UpdateShippingOption(const nsAString& aShippingOption);
 
   nsresult UpdatePayment(const PaymentDetailsUpdate& aDetails);
   void AbortUpdate(nsresult aRv);
 
+  void SetShippingType(const Nullable<PaymentShippingType>& aShippingType);
   Nullable<PaymentShippingType> GetShippingType() const;
 
   IMPL_EVENT_HANDLER(shippingaddresschange);
   IMPL_EVENT_HANDLER(shippingoptionchange);
 
 protected:
   ~PaymentRequest();
 
@@ -138,16 +141,18 @@ protected:
   RefPtr<Promise> mAbortPromise;
   // Resolve mAcceptPromise with mResponse if user accepts the request.
   RefPtr<PaymentResponse> mResponse;
   // It is populated when the user provides a shipping address.
   RefPtr<PaymentAddress> mShippingAddress;
   // It is populated when the user chooses a shipping option.
   nsString mShippingOption;
 
+  Nullable<PaymentShippingType> mShippingType;
+
   // "true" when there is a pending updateWith() call to update the payment request
   // and "false" otherwise.
   bool mUpdating;
   // The error is set in AbortUpdate(). The value is NS_OK by default.
   nsresult mUpdateError;
 
   enum {
     eUnknown,
--- a/dom/payments/PaymentRequestManager.cpp
+++ b/dom/payments/PaymentRequestManager.cpp
@@ -98,26 +98,27 @@ ConvertShippingOption(const PaymentShipp
   ConvertCurrencyAmount(aOption.mAmount, amount);
   aIPCOption = IPCPaymentShippingOption(aOption.mId, aOption.mLabel, amount, aOption.mSelected);
 }
 
 nsresult
 ConvertDetailsBase(const PaymentDetailsBase& aDetails,
                    nsTArray<IPCPaymentItem>& aDisplayItems,
                    nsTArray<IPCPaymentShippingOption>& aShippingOptions,
-                   nsTArray<IPCPaymentDetailsModifier>& aModifiers)
+                   nsTArray<IPCPaymentDetailsModifier>& aModifiers,
+                   bool aResetShippingOptions)
 {
   if (aDetails.mDisplayItems.WasPassed()) {
     for (const PaymentItem& item : aDetails.mDisplayItems.Value()) {
       IPCPaymentItem displayItem;
       ConvertItem(item, displayItem);
       aDisplayItems.AppendElement(displayItem);
     }
   }
-  if (aDetails.mShippingOptions.WasPassed()) {
+  if (aDetails.mShippingOptions.WasPassed() && !aResetShippingOptions) {
     for (const PaymentShippingOption& option : aDetails.mShippingOptions.Value()) {
       IPCPaymentShippingOption shippingOption;
       ConvertShippingOption(option, shippingOption);
       aShippingOptions.AppendElement(shippingOption);
     }
   }
   if (aDetails.mModifiers.WasPassed()) {
     for (const PaymentDetailsModifier& modifier : aDetails.mModifiers.Value()) {
@@ -129,23 +130,24 @@ ConvertDetailsBase(const PaymentDetailsB
       aModifiers.AppendElement(detailsModifier);
     }
   }
   return NS_OK;
 }
 
 nsresult
 ConvertDetailsInit(const PaymentDetailsInit& aDetails,
-                   IPCPaymentDetails& aIPCDetails)
+                   IPCPaymentDetails& aIPCDetails,
+                   bool aResetShippingOptions)
 {
   // Convert PaymentDetailsBase members
   nsTArray<IPCPaymentItem> displayItems;
   nsTArray<IPCPaymentShippingOption> shippingOptions;
   nsTArray<IPCPaymentDetailsModifier> modifiers;
-  nsresult rv = ConvertDetailsBase(aDetails, displayItems, shippingOptions, modifiers);
+  nsresult rv = ConvertDetailsBase(aDetails, displayItems, shippingOptions, modifiers, aResetShippingOptions);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // Convert |id|
   nsString id(EmptyString());
   if (aDetails.mId.WasPassed()) {
     id = aDetails.mId.Value();
@@ -170,17 +172,20 @@ ConvertDetailsInit(const PaymentDetailsI
 nsresult
 ConvertDetailsUpdate(const PaymentDetailsUpdate& aDetails,
                      IPCPaymentDetails& aIPCDetails)
 {
   // Convert PaymentDetailsBase members
   nsTArray<IPCPaymentItem> displayItems;
   nsTArray<IPCPaymentShippingOption> shippingOptions;
   nsTArray<IPCPaymentDetailsModifier> modifiers;
-  nsresult rv = ConvertDetailsBase(aDetails, displayItems, shippingOptions, modifiers);
+  // [TODO] Populate a boolean flag as aResetShippingOptions based on the
+  // result of processing details.shippingOptions in UpdatePayment method.
+  nsresult rv = ConvertDetailsBase(
+    aDetails, displayItems, shippingOptions, modifiers, false);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // Convert required |total|
   IPCPaymentItem total;
   ConvertItem(aDetails.mTotal, total);
 
@@ -347,46 +352,58 @@ PaymentRequestManager::GetPaymentRequest
     if (request->Equals(aRequestId)) {
       RefPtr<PaymentRequest> paymentRequest = request;
       return paymentRequest.forget();
     }
   }
   return nullptr;
 }
 
+void
+GetSelectedShippingOption(const PaymentDetailsInit& aDetails,
+                          nsAString& aOption,
+                          bool* aResetOptions)
+{
+  SetDOMStringToNull(aOption);
+  if (!aDetails.mShippingOptions.WasPassed()) {
+    return;
+  }
+
+  nsTArray<nsString> seenIDs;
+  const Sequence<PaymentShippingOption>& shippingOptions =
+    aDetails.mShippingOptions.Value();
+  for (const PaymentShippingOption& shippingOption : shippingOptions) {
+    // If there are duplicate IDs present in the shippingOptions, reset aOption
+    // to null and set resetOptions flag to reset details.shippingOptions later
+    // when converting to IPC structure.
+    if (seenIDs.Contains(shippingOption.mId)) {
+      SetDOMStringToNull(aOption);
+      *aResetOptions = true;
+      return;
+    }
+    seenIDs.AppendElement(shippingOption.mId);
+
+    // set aOption to last selected option's ID
+    if (shippingOption.mSelected) {
+      aOption = shippingOption.mId;
+    }
+  }
+}
+
 nsresult
 PaymentRequestManager::CreatePayment(nsPIDOMWindowInner* aWindow,
                                      const Sequence<PaymentMethodData>& aMethodData,
                                      const PaymentDetailsInit& aDetails,
                                      const PaymentOptions& aOptions,
                                      PaymentRequest** aRequest)
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_ARG_POINTER(aRequest);
   *aRequest = nullptr;
-
   nsresult rv;
-  nsTArray<IPCPaymentMethodData> methodData;
-  for (const PaymentMethodData& data : aMethodData) {
-    IPCPaymentMethodData ipcMethodData;
-    rv = ConvertMethodData(data, ipcMethodData);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    methodData.AppendElement(ipcMethodData);
-  }
-
-  IPCPaymentDetails details;
-  rv = ConvertDetailsInit(aDetails, details);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  IPCPaymentOptions options;
-  ConvertOptions(aOptions, options);
 
   RefPtr<PaymentRequest> request = PaymentRequest::CreatePaymentRequest(aWindow, rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   /*
    *  Set request's |mId| to details.id if details.id exists.
@@ -395,18 +412,58 @@ PaymentRequestManager::CreatePayment(nsP
   nsAutoString requestId;
   if (aDetails.mId.WasPassed() && !aDetails.mId.Value().IsEmpty()) {
     requestId = aDetails.mId.Value();
   } else {
     request->GetInternalId(requestId);
   }
   request->SetId(requestId);
 
+  /*
+   *  Set request's mShippingOption to last selected option's ID if
+   *  details.shippingOptions exists and IDs of all options are unique.
+   *  Otherwise, set mShippingOption to null and set the resetShippingOptions
+   *  flag to reset details.shippingOptions to an empty array later when
+   *  converting details to IPC structure.
+   */
+  nsAutoString shippingOption;
+  bool resetShippingOptions = false;
+  GetSelectedShippingOption(aDetails, shippingOption, &resetShippingOptions);
+  request->SetShippingOption(shippingOption);
+
+  /*
+   * Set request's |mShippingType| if shipping is required.
+   */
+  if (aOptions.mRequestShipping) {
+    request->SetShippingType(
+        Nullable<PaymentShippingType>(aOptions.mShippingType));
+  }
+
   nsAutoString internalId;
   request->GetInternalId(internalId);
+
+  nsTArray<IPCPaymentMethodData> methodData;
+  for (const PaymentMethodData& data : aMethodData) {
+    IPCPaymentMethodData ipcMethodData;
+    rv = ConvertMethodData(data, ipcMethodData);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+    methodData.AppendElement(ipcMethodData);
+  }
+
+  IPCPaymentDetails details;
+  rv = ConvertDetailsInit(aDetails, details, resetShippingOptions);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  IPCPaymentOptions options;
+  ConvertOptions(aOptions, options);
+
   IPCPaymentCreateActionRequest action(internalId,
                                        methodData,
                                        details,
                                        options);
 
   rv = SendRequestPayment(request, action, true);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
@@ -484,16 +541,22 @@ nsresult
 PaymentRequestManager::UpdatePayment(const nsAString& aRequestId,
                                      const PaymentDetailsUpdate& aDetails)
 {
   RefPtr<PaymentRequest> request = GetPaymentRequestById(aRequestId);
   if (!request) {
     return NS_ERROR_UNEXPECTED;
   }
 
+  // [TODO] Process details.shippingOptions if presented.
+  //        1) Check if there are duplicate IDs in details.shippingOptions,
+  //           if so, reset details.shippingOptions to an empty sequence.
+  //        2) Set request's selectedShippingOption to the ID of last selected
+  //           option.
+
   IPCPaymentDetails details;
   nsresult rv = ConvertDetailsUpdate(aDetails, details);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   nsAutoString requestId(aRequestId);
   IPCPaymentUpdateActionRequest action(requestId, details);
--- a/dom/payments/test/ConstructorChromeScript.js
+++ b/dom/payments/test/ConstructorChromeScript.js
@@ -222,16 +222,77 @@ function checkComplexRequest(payRequest)
   if (!paymentOptions.requestShipping) {
     emitTestFail("requestShipping option should be true.");
   }
   if (paymentOptions.shippingType != "shipping") {
     emitTestFail("shippingType option should be 'shipping'.")
   }
 }
 
+function checkDuplicateShippingOptionsRequest(payRequest) {
+  if (payRequest.paymentMethods.length != 1) {
+    emitTestFail("paymentMethods' length should be 1.");
+  }
+
+  const methodData = payRequest.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
+  if (!methodData) {
+    emitTestFail("Fail to get payment methodData.");
+  }
+  let supportedMethod = methodData.supportedMethods;
+  if (supportedMethod != "basic-card") {
+    emitTestFail("supported method should be 'basic-card'.");
+  }
+  // checking the passed PaymentDetails parameter
+  const details = payRequest.paymentDetails;
+  if (details.id != "duplicate shipping options details" ) {
+    emitTestFail("details.id should be 'duplicate shipping options details'.");
+  }
+  if (details.totalItem.label != "Total") {
+    emitTestFail("total item's label should be 'Total'.");
+  }
+  if (details.totalItem.amount.currency != "USD") {
+    emitTestFail("total item's currency should be 'USD'.");
+  }
+  if (details.totalItem.amount.value != "1.00") {
+    emitTestFail("total item's value should be '1.00'.");
+  }
+
+  if (details.displayItems) {
+    emitTestFail("details.displayItems should be undefined.");
+  }
+  if (details.modifiers) {
+    emitTestFail("details.displayItems should be undefined.");
+  }
+  const shippingOptions = details.shippingOptions;
+  if (!shippingOptions) {
+    emitTestFail("details.shippingOptions should not be undefined.");
+  }
+  if (shippingOptions.length != 0) {
+    emitTestFail("shippingOptions' length should be 0.");
+  }
+
+  // checking the default generated PaymentOptions parameter
+  const paymentOptions = payRequest.paymentOptions;
+  if (paymentOptions.requestPayerName) {
+    emitTestFail("requestPayerName option should be false.");
+  }
+  if (paymentOptions.requestPayerEmail) {
+    emitTestFail("requestPayerEmail option should be false.");
+  }
+  if (paymentOptions.requestPayerPhone) {
+    emitTestFail("requestPayerPhone option should be false.");
+  }
+  if (paymentOptions.requestShipping) {
+    emitTestFail("requestShipping option should be false.");
+  }
+  if (paymentOptions.shippingType != "shipping") {
+    emitTestFail("shippingType option should be 'shipping'.")
+  }
+}
+
 function checkSimplestRequestHandler() {
   const paymentEnum = paymentSrv.enumerate();
   if (!paymentEnum.hasMoreElements()) {
     emitTestFail("PaymentRequestService should have at least one payment request.");
   }
   while (paymentEnum.hasMoreElements()) {
     let payRequest = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
     if (!payRequest) {
@@ -256,37 +317,57 @@ function checkComplexRequestHandler() {
       break;
     }
     checkComplexRequest(payRequest);
   }
   paymentSrv.cleanup();
   sendAsyncMessage("check-complete");
 }
 
+function checkDuplicateShippingOptionsRequestHandler() {
+  const paymentEnum = paymentSrv.enumerate();
+  if (!paymentEnum.hasMoreElements()) {
+    emitTestFail("PaymentRequestService should have at least one payment request.");
+  }
+  while (paymentEnum.hasMoreElements()) {
+    let payRequest = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
+    if (!payRequest) {
+      emitTestFail("Fail to get existing payment request.");
+      break;
+    }
+    checkDuplicateShippingOptionsRequest(payRequest);
+  }
+  paymentSrv.cleanup();
+  sendAsyncMessage("check-complete");
+}
+
 function checkMultipleRequestsHandler () {
   const paymentEnum = paymentSrv.enumerate();
   if (!paymentEnum.hasMoreElements()) {
     emitTestFail("PaymentRequestService should have at least one payment request.");
   }
   while (paymentEnum.hasMoreElements()) {
     let payRequest = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
     if (!payRequest) {
       emitTestFail("Fail to get existing payment request.");
       break;
     }
-    if (payRequest.paymentDetails.id != "payment details") {
+    if (payRequest.paymentDetails.id == "payment details") {
+      checkComplexRequest(payRequest);
+    } else if (payRequest.paymentDetails.id == "duplicate shipping options details") {
+      checkDuplicateShippingOptionsRequest(payRequest);
+    } else {
       checkSimplestRequest(payRequest);
-    } else {
-      checkComplexRequest(payRequest);
     }
   }
   paymentSrv.cleanup();
   sendAsyncMessage("check-complete");
 }
 
 addMessageListener("check-simplest-request", checkSimplestRequestHandler);
 addMessageListener("check-complex-request", checkComplexRequestHandler);
+addMessageListener("check-duplicate-shipping-options-request", checkDuplicateShippingOptionsRequestHandler);
 addMessageListener("check-multiple-requests", checkMultipleRequestsHandler);
 
 addMessageListener("teardown", function() {
   paymentSrv.cleanup();
   sendAsyncMessage("teardown-complete");
 });
--- a/dom/payments/test/browser_multiple_construction.js
+++ b/dom/payments/test/browser_multiple_construction.js
@@ -17,16 +17,18 @@ add_task(async function() {
       ok(paymentEnum.hasMoreElements(), "PaymentRequestService should have at least one payment request.");
       while (paymentEnum.hasMoreElements()) {
         let payment = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
         ok(payment, "Fail to get existing payment request.");
         if (payment.paymentDetails.id == "complex details") {
           checkComplexPayment(payment);
         } else if (payment.paymentDetails.id == "simple details") {
           checkSimplePayment(payment);
+        } else if (payment.paymentDetails.id == "duplicate shipping options details") {
+          checkDupShippingOptionsPayment(payment);
         } else {
           ok(false, "Unknown payment.");
         }
       }
       Services.prefs.setBoolPref("dom.payments.request.enabled", false);
     }
   );
 });
--- a/dom/payments/test/head.js
+++ b/dom/payments/test/head.js
@@ -96,14 +96,42 @@ function checkComplexPayment(aPayment) {
   const paymentOptions = aPayment.paymentOptions;
   ok(paymentOptions.requestPayerName, "payerName option should be true");
   ok(paymentOptions.requestPayerEmail, "payerEmail option should be true");
   ok(paymentOptions.requestPayerPhone, "payerPhone option should be true");
   ok(paymentOptions.requestShipping, "requestShipping option should be true");
   is(paymentOptions.shippingType, "shipping", "shippingType option should be 'shipping'");
 }
 
+function checkDupShippingOptionsPayment(aPayment) {
+  // checking the passed PaymentMethods parameter
+  is(aPayment.paymentMethods.length, 1, "paymentMethods' length should be 1.");
+
+  const methodData = aPayment.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
+  ok(methodData, "Fail to get payment methodData.");
+  is(methodData.supportedMethods, "MyPay", "modifier's supported method name should be 'MyPay'.");
+  is(methodData.data, "", "method data should be empty");
+
+  // checking the passed PaymentDetails parameter
+  const details = aPayment.paymentDetails;
+  is(details.id, "duplicate shipping options details", "details.id should be 'duplicate shipping options details'.");
+  is(details.totalItem.label, "Donation", "total item's label should be 'Donation'.");
+  is(details.totalItem.amount.currency, "USD", "total item's currency should be 'USD'.");
+  is(details.totalItem.amount.value, "55.00", "total item's value should be '55.00'.");
+
+  const shippingOptions = details.shippingOptions;
+  is(shippingOptions.length, 0, "shippingOptions' length should be 0.");
+
+  // checking the passed PaymentOptions parameter
+  const paymentOptions = aPayment.paymentOptions;
+  ok(paymentOptions.requestPayerName, "payerName option should be true");
+  ok(paymentOptions.requestPayerEmail, "payerEmail option should be true");
+  ok(paymentOptions.requestPayerPhone, "payerPhone option should be true");
+  ok(paymentOptions.requestShipping, "requestShipping option should be true");
+  is(paymentOptions.shippingType, "shipping", "shippingType option should be 'shipping'");
+}
+
 function cleanup() {
   const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
   if (paymentSrv) {
     paymentSrv.cleanup();
   }
 }
--- a/dom/payments/test/multiple_payment_request.html
+++ b/dom/payments/test/multiple_payment_request.html
@@ -61,24 +61,49 @@
     const simpleDetails = {
       id: "simple details",
       total: {
         label: "Donation",
         amount: { currency: "USD", value: "55.00" }
       },
     };
 
+    const dupShippingOptionsDetails = {
+      id: "duplicate shipping options details",
+      total: {
+        label: "Donation",
+        amount: { currency: "USD", value: "55.00" }
+      },
+      shippingOptions: [
+        {
+          id: "dupShipping",
+          label: "NormalShipping",
+          amount: { currency: "USD", value: "10.00", },
+          selected: true,
+        },
+        {
+          id: "dupShipping",
+          label: "FastShipping",
+          amount: { currency: "USD", value: "30.00", },
+          selected: false,
+        },
+      ],
+    };
+
     const options = {
       requestPayerName: true,
       requestPayerEmail: true,
       requestPayerPhone: true,
       requestShipping: true,
       shippingType: "shipping",
     };
 
     const paymentRequest1 = new PaymentRequest(supportedInstruments,
                                                complexDetails,
                                                options);
     const paymentRequest2 = new PaymentRequest(supportedInstruments,
                                                simpleDetails);
+    const paymentRequest3 = new PaymentRequest(supportedInstruments,
+                                               dupShippingOptionsDetails,
+                                               options);
     </script>
   </body>
 </html>
--- a/dom/payments/test/test_constructor.html
+++ b/dom/payments/test/test_constructor.html
@@ -116,16 +116,47 @@ https://bugzilla.mozilla.org/show_bug.cg
   const complexOptions = {
     requestPayerName: true,
     requestPayerEmail: true,
     requestPayerPhone: true,
     requestShipping: true,
     shippingType: "shipping"
   };
 
+  const duplicateShippingOptionsDetails = {
+    id: "duplicate shipping options details",
+    total: {
+      label: "Total",
+      amount: {
+        currency: "USD",
+        value: "1.00"
+      }
+    },
+    shippingOptions: [
+      {
+        id: "dupShipping",
+        label: "NormalShipping",
+        amount: {
+          currency: "USD",
+          value: "10.00"
+        },
+        selected: true,
+      },
+      {
+        id: "dupShipping",
+        label: "FastShipping",
+        amount: {
+          currency: "USD",
+          value: "30.00"
+        },
+        selected: false,
+      },
+    ],
+  };
+
 
   function testWithSimplestParameters() {
     return new Promise((resolve, reject) => {
       const payRequest = new PaymentRequest(simplestMethods, simplestDetails);
       ok(payRequest, "PaymentRequest should be created");
       gScript.addMessageListener("check-complete", function checkCompleteHandler() {
         gScript.removeMessageListener("check-complete", checkCompleteHandler);
         resolve();
@@ -141,22 +172,36 @@ https://bugzilla.mozilla.org/show_bug.cg
       gScript.addMessageListener("check-complete", function checkCompleteHandler() {
         gScript.removeMessageListener("check-complete", checkCompleteHandler);
         resolve();
       });
       gScript.sendAsyncMessage("check-complex-request");
     });
   }
 
+  function testWithDuplicateShippingOptionsParameters() {
+    return new Promise((resolve, reject) => {
+      const payRequest = new PaymentRequest(simplestMethods, duplicateShippingOptionsDetails);
+      ok(payRequest, "PaymentRequest should be created");
+      gScript.addMessageListener("check-complete", function checkCompleteHandler() {
+        gScript.removeMessageListener("check-complete", checkCompleteHandler);
+        resolve();
+      });
+      gScript.sendAsyncMessage("check-duplicate-shipping-options-request");
+    });
+  }
+
   function testMultipleRequests() {
     return new Promise((resolve, reject) => {
       const payRequest1 = new PaymentRequest(complexMethods, complexDetails, complexOptions);
       const payRequest2 = new PaymentRequest(simplestMethods, simplestDetails);
+      const payRequest3 = new PaymentRequest(simplestMethods, duplicateShippingOptionsDetails);
       ok(payRequest1, "PaymentRequest with complex parameters should be created");
       ok(payRequest2, "PaymentRequest with simplest parameters should be created");
+      ok(payRequest3, "PaymentRequest with duplicate shipping options parameters should be created");
       gScript.addMessageListener("check-complete", function checkCompleteHandler() {
         gScript.removeMessageListener("check-complete", checkCompleteHandler);
         resolve();
       });
       gScript.sendAsyncMessage("check-multiple-requests");
     });
   }
 
@@ -168,16 +213,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       SimpleTest.finish();
     });
     gScript.sendAsyncMessage("teardown");
   }
 
   function runTests() {
     testWithSimplestParameters()
     .then(testWithComplexParameters)
+    .then(testWithDuplicateShippingOptionsParameters)
     .then(testMultipleRequests)
     .then(teardown)
     .catch( e => {
       ok(false, "Unexpected error: " + e.name);
       SimpleTest.finish();
     });
   }
 
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -1,9 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 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 "base/basictypes.h"
 
 #include "jsfriendapi.h"
 #include "jswrapper.h"
@@ -24,20 +25,16 @@
 #include "nsIDOMElement.h"
 #include "nsIContent.h"
 #include "nsPluginInstanceOwner.h"
 #include "nsWrapperCacheInlines.h"
 #include "js/GCHashTable.h"
 #include "js/TracingAPI.h"
 #include "mozilla/HashFunctions.h"
 #include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/plugins/PluginAsyncSurrogate.h"
-
-using mozilla::plugins::AsyncNPObject;
-using mozilla::plugins::PluginAsyncSurrogate;
 
 #define NPRUNTIME_JSCLASS_NAME "NPObject JS wrapper class"
 
 using namespace mozilla::plugins::parent;
 using namespace mozilla;
 
 #include "mozilla/plugins/PluginScriptableObjectParent.h"
 using mozilla::plugins::PluginScriptableObjectParent;
@@ -104,34 +101,20 @@ static PLDHashTable* sNPObjWrappers;
 static int32_t sWrapperCount;
 
 static bool sCallbackIsRegistered = false;
 
 static nsTArray<NPObject*>* sDelayedReleases;
 
 namespace {
 
-inline void
-CastNPObject(NPObject *aObj, PluginScriptableObjectParent*& aActor,
-             PluginAsyncSurrogate*& aSurrogate)
-{
-  aActor = nullptr;
-  aSurrogate = nullptr;
-  if (aObj->_class == PluginScriptableObjectParent::GetClass()) {
-    aActor = static_cast<ParentNPObject*>(aObj)->parent;
-  } else if (aObj->_class == PluginAsyncSurrogate::GetClass()) {
-    aSurrogate = static_cast<AsyncNPObject*>(aObj)->mSurrogate;
-  }
-}
-
 inline bool
 NPObjectIsOutOfProcessProxy(NPObject *obj)
 {
-  return obj->_class == PluginScriptableObjectParent::GetClass() ||
-         obj->_class == PluginAsyncSurrogate::GetClass();
+  return obj->_class == PluginScriptableObjectParent::GetClass();
 }
 
 } // namespace
 
 // Helper class that suppresses any JS exceptions that were thrown while
 // the plugin executed JS, if the nsJSObjWrapper has a destroy pending.
 // Note that this class is the product (vestige?) of a long evolution in how
 // error reporting worked, and hence the mIsDestroyPending check, and hence this
@@ -1092,27 +1075,16 @@ NPObject *
 nsJSObjWrapper::GetNewOrUsed(NPP npp, JS::Handle<JSObject*> obj)
 {
   if (!npp) {
     NS_ERROR("Null NPP passed to nsJSObjWrapper::GetNewOrUsed()!");
 
     return nullptr;
   }
 
-  // If we're running out-of-process and initializing asynchronously, and if
-  // the plugin has been asked to destroy itself during initialization,
-  // don't return any new NPObjects.
-  nsNPAPIPluginInstance* inst = static_cast<nsNPAPIPluginInstance*>(npp->ndata);
-  if (inst->GetPlugin()->GetLibrary()->IsOOP()) {
-    PluginAsyncSurrogate* surrogate = PluginAsyncSurrogate::Cast(npp);
-    if (surrogate && surrogate->IsDestroyPending()) {
-      return nullptr;
-    }
-  }
-
   // No need to enter the right compartment here as we only get the
   // class and private from the JSObject, neither of which cares about
   // compartments.
 
   if (nsNPObjWrapper::IsWrapper(obj)) {
     // obj is one of our own, its private data is the NPObject we're
     // looking for.
 
@@ -1399,32 +1371,25 @@ NPObjWrapper_GetProperty(JSContext *cx, 
   bool hasProperty, hasMethod;
 
   NPVariant npv;
   VOID_TO_NPVARIANT(npv);
 
   NPIdentifier identifier = JSIdToNPIdentifier(id);
 
   if (NPObjectIsOutOfProcessProxy(npobj)) {
-    PluginScriptableObjectParent* actor = nullptr;
-    PluginAsyncSurrogate* surrogate = nullptr;
-    CastNPObject(npobj, actor, surrogate);
-
-    // actor and surrogate may be null if the plugin crashed.
-    if (!actor && !surrogate)
+    PluginScriptableObjectParent* actor =
+      static_cast<ParentNPObject*>(npobj)->parent;
+
+    // actor may be null if the plugin crashed.
+    if (!actor)
       return false;
 
-    bool success = false;
-    if (surrogate) {
-      success = surrogate->GetPropertyHelper(npobj, identifier, &hasProperty,
-                                             &hasMethod, &npv);
-    } else if (actor) {
-      success = actor->GetPropertyHelper(identifier, &hasProperty, &hasMethod,
-                                         &npv);
-    }
+    bool success = actor->GetPropertyHelper(identifier, &hasProperty,
+                                            &hasMethod, &npv);
 
     if (!ReportExceptionIfPending(cx)) {
       if (success)
         _releasevariantvalue(&npv);
       return false;
     }
 
     if (success) {
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -48,17 +48,16 @@
 #include "nsIObjectLoadingContent.h"
 #include "nsIWritablePropertyBag2.h"
 #include "nsICategoryManager.h"
 #include "nsPluginStreamListenerPeer.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/FakePluginTagInitBinding.h"
 #include "mozilla/LoadInfo.h"
-#include "mozilla/plugins/PluginAsyncSurrogate.h"
 #include "mozilla/plugins/PluginBridge.h"
 #include "mozilla/plugins/PluginTypes.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ipc/URIUtils.h"
 
 #include "nsEnumeratorUtils.h"
 #include "nsXPCOM.h"
 #include "nsXPCOMCID.h"
@@ -114,17 +113,16 @@
 #endif
 
 #include "npapi.h"
 
 using namespace mozilla;
 using mozilla::TimeStamp;
 using mozilla::plugins::FakePluginTag;
 using mozilla::plugins::PluginTag;
-using mozilla::plugins::PluginAsyncSurrogate;
 using mozilla::dom::FakePluginTagInit;
 using mozilla::dom::FakePluginMimeEntry;
 
 // Null out a strong ref to a linked list iteratively to avoid
 // exhausting the stack (bug 486349).
 #define NS_ITERATIVE_UNREF_LIST(type_, list_, mNext_)                \
   {                                                                  \
     while (list_) {                                                  \
@@ -753,27 +751,25 @@ nsPluginHost::InstantiatePluginInstance(
     return NS_ERROR_FAILURE;
   }
 
   rv = SetUpPluginInstance(aMimeType, aURL, instanceOwner);
   if (NS_FAILED(rv)) {
     instanceOwner->Destroy();
     return NS_ERROR_FAILURE;
   }
-  const bool isAsyncInit = (rv == NS_PLUGIN_INIT_PENDING);
 
   RefPtr<nsNPAPIPluginInstance> instance;
   rv = instanceOwner->GetInstance(getter_AddRefs(instance));
   if (NS_FAILED(rv)) {
     instanceOwner->Destroy();
     return rv;
   }
 
-  // Async init plugins will initiate their own widget creation.
-  if (!isAsyncInit && instance) {
+  if (instance) {
     CreateWidget(instanceOwner);
   }
 
   // At this point we consider instantiation to be successful. Do not return an error.
   instanceOwner.forget(aOwner);
 
 #ifdef PLUGIN_LOGGING
   nsAutoCString urlSpec2;
@@ -2378,17 +2374,16 @@ nsPluginHost::SetPluginsInContent(uint32
                                                tag.filename().get(),
                                                "", // aFullPath
                                                tag.version().get(),
                                                nsTArray<nsCString>(tag.mimeTypes()),
                                                nsTArray<nsCString>(tag.mimeDescriptions()),
                                                nsTArray<nsCString>(tag.extensions()),
                                                tag.isJavaPlugin(),
                                                tag.isFlashPlugin(),
-                                               tag.supportsAsyncInit(),
                                                tag.supportsAsyncRender(),
                                                tag.lastModifiedTime(),
                                                tag.isFromExtension(),
                                                tag.sandboxLevel());
       AddPluginTag(pluginTag);
     }
 
     for (const auto& tag : aFakePlugins) {
@@ -2619,17 +2614,16 @@ nsPluginHost::SendPluginsToContent()
     pluginTags.AppendElement(PluginTag(tag->mId,
                                        tag->Name(),
                                        tag->Description(),
                                        tag->MimeTypes(),
                                        tag->MimeDescriptions(),
                                        tag->Extensions(),
                                        tag->mIsJavaPlugin,
                                        tag->mIsFlashPlugin,
-                                       tag->mSupportsAsyncInit,
                                        tag->mSupportsAsyncRender,
                                        tag->FileName(),
                                        tag->Version(),
                                        tag->mLastModifiedTime,
                                        tag->IsFromExtension(),
                                        tag->mSandboxLevel));
   }
   nsTArray<dom::ContentParent*> parents;
@@ -4018,22 +4012,16 @@ mozilla::LinkedList<nsPluginDestroyRunna
 mozilla::LinkedList<PluginDestructionGuard> PluginDestructionGuard::sList;
 
 PluginDestructionGuard::PluginDestructionGuard(nsNPAPIPluginInstance *aInstance)
   : mInstance(aInstance)
 {
   Init();
 }
 
-PluginDestructionGuard::PluginDestructionGuard(PluginAsyncSurrogate *aSurrogate)
-  : mInstance(static_cast<nsNPAPIPluginInstance*>(aSurrogate->GetNPP()->ndata))
-{
-  InitAsync();
-}
-
 PluginDestructionGuard::PluginDestructionGuard(NPP npp)
   : mInstance(npp ? static_cast<nsNPAPIPluginInstance*>(npp->ndata) : nullptr)
 {
   Init();
 }
 
 PluginDestructionGuard::~PluginDestructionGuard()
 {
--- a/dom/plugins/base/nsPluginHost.h
+++ b/dom/plugins/base/nsPluginHost.h
@@ -30,17 +30,16 @@
 #ifdef XP_WIN
 #include <minwindef.h>
 #include "nsIWindowsRegKey.h"
 #endif
 
 namespace mozilla {
 namespace plugins {
 class FakePluginTag;
-class PluginAsyncSurrogate;
 class PluginTag;
 } // namespace plugins
 } // namespace mozilla
 
 class nsNPAPIPlugin;
 class nsIFile;
 class nsIChannel;
 class nsPluginNativeWindow;
@@ -420,43 +419,31 @@ private:
   // two different CIDs for some reason...
   static nsPluginHost* sInst;
 };
 
 class PluginDestructionGuard : public mozilla::LinkedListElement<PluginDestructionGuard>
 {
 public:
   explicit PluginDestructionGuard(nsNPAPIPluginInstance *aInstance);
-  explicit PluginDestructionGuard(mozilla::plugins::PluginAsyncSurrogate *aSurrogate);
   explicit PluginDestructionGuard(NPP npp);
 
   ~PluginDestructionGuard();
 
   static bool DelayDestroy(nsNPAPIPluginInstance *aInstance);
 
 protected:
   void Init()
   {
     NS_ASSERTION(NS_IsMainThread(), "Should be on the main thread");
 
     mDelayedDestroy = false;
 
     sList.insertBack(this);
   }
 
-  void InitAsync()
-  {
-    NS_ASSERTION(NS_IsMainThread(), "Should be on the main thread");
-
-    mDelayedDestroy = false;
-
-    // Instances with active surrogates must be inserted *in front of* sList so
-    // that they appear to be at the bottom of the stack
-    sList.insertFront(this);
-  }
-
   RefPtr<nsNPAPIPluginInstance> mInstance;
   bool mDelayedDestroy;
 
   static mozilla::LinkedList<PluginDestructionGuard> sList;
 };
 
 #endif // nsPluginHost_h_
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1663,55 +1663,16 @@ void nsPluginInstanceOwner::ExitFullScre
   if (sFullScreenInstance && sFullScreenInstance->mInstance &&
       env->IsSameObject(view, (jobject)sFullScreenInstance->mInstance->GetJavaSurface())) {
     sFullScreenInstance->ExitFullScreen();
   }
 }
 
 #endif
 
-void
-nsPluginInstanceOwner::NotifyHostAsyncInitFailed()
-{
-  nsCOMPtr<nsIObjectLoadingContent> content = do_QueryReferent(mContent);
-  content->StopPluginInstance();
-}
-
-void
-nsPluginInstanceOwner::NotifyHostCreateWidget()
-{
-  mPluginHost->CreateWidget(this);
-#ifdef XP_MACOSX
-  FixUpPluginWindow(ePluginPaintEnable);
-#else
-  if (mPluginFrame) {
-    mPluginFrame->InvalidateFrame();
-  } else {
-    CallSetWindow();
-  }
-#endif
-}
-
-void
-nsPluginInstanceOwner::NotifyDestroyPending()
-{
-  if (!mInstance) {
-    return;
-  }
-  bool isOOP = false;
-  if (NS_FAILED(mInstance->GetIsOOP(&isOOP)) || !isOOP) {
-    return;
-  }
-  NPP npp = nullptr;
-  if (NS_FAILED(mInstance->GetNPP(&npp)) || !npp) {
-    return;
-  }
-  PluginAsyncSurrogate::NotifyDestroyPending(npp);
-}
-
 nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
 {
 #ifdef MOZ_WIDGET_ANDROID
   if (mInstance) {
     ANPEvent event;
     event.inSize = sizeof(ANPEvent);
     event.eventType = kLifecycle_ANPEventType;
 
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -264,20 +264,16 @@ public:
 
   void RequestFullScreen();
   void ExitFullScreen();
 
   // Called from nsAppShell when we removed the fullscreen view.
   static void ExitFullScreen(jobject view);
 #endif
 
-  void NotifyHostAsyncInitFailed();
-  void NotifyHostCreateWidget();
-  void NotifyDestroyPending();
-
   bool GetCompositionString(uint32_t aIndex, nsTArray<uint8_t>* aString,
                             int32_t* aLength);
   bool SetCandidateWindow(
            const mozilla::widget::CandidateWindowPosition& aPosition);
   bool RequestCommitOrCancel(bool aCommitted);
 
   // See nsIKeyEventInPluginCallback
   virtual void HandledWindowedPluginKeyEvent(
--- a/dom/plugins/base/nsPluginTags.cpp
+++ b/dom/plugins/base/nsPluginTags.cpp
@@ -228,17 +228,16 @@ nsPluginTag::nsPluginTag(nsPluginInfo* a
   : nsIInternalPluginTag(aPluginInfo->fName, aPluginInfo->fDescription,
                          aPluginInfo->fFileName, aPluginInfo->fVersion),
     mId(sNextId++),
     mContentProcessRunningCount(0),
     mHadLocalInstance(false),
     mLibrary(nullptr),
     mIsJavaPlugin(false),
     mIsFlashPlugin(false),
-    mSupportsAsyncInit(false),
     mSupportsAsyncRender(false),
     mFullPath(aPluginInfo->fFullPath),
     mLastModifiedTime(aLastModifiedTime),
     mSandboxLevel(0),
     mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
     mCachedBlocklistStateValid(false),
     mIsFromExtension(fromExtension)
 {
@@ -265,17 +264,16 @@ nsPluginTag::nsPluginTag(const char* aNa
                          bool aArgsAreUTF8)
   : nsIInternalPluginTag(aName, aDescription, aFileName, aVersion),
     mId(sNextId++),
     mContentProcessRunningCount(0),
     mHadLocalInstance(false),
     mLibrary(nullptr),
     mIsJavaPlugin(false),
     mIsFlashPlugin(false),
-    mSupportsAsyncInit(false),
     mSupportsAsyncRender(false),
     mFullPath(aFullPath),
     mLastModifiedTime(aLastModifiedTime),
     mSandboxLevel(0),
     mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
     mCachedBlocklistStateValid(false),
     mIsFromExtension(fromExtension)
 {
@@ -293,29 +291,27 @@ nsPluginTag::nsPluginTag(uint32_t aId,
                          const char* aFileName,
                          const char* aFullPath,
                          const char* aVersion,
                          nsTArray<nsCString> aMimeTypes,
                          nsTArray<nsCString> aMimeDescriptions,
                          nsTArray<nsCString> aExtensions,
                          bool aIsJavaPlugin,
                          bool aIsFlashPlugin,
-                         bool aSupportsAsyncInit,
                          bool aSupportsAsyncRender,
                          int64_t aLastModifiedTime,
                          bool aFromExtension,
                          int32_t aSandboxLevel)
   : nsIInternalPluginTag(aName, aDescription, aFileName, aVersion, aMimeTypes,
                          aMimeDescriptions, aExtensions),
     mId(aId),
     mContentProcessRunningCount(0),
     mLibrary(nullptr),
     mIsJavaPlugin(aIsJavaPlugin),
     mIsFlashPlugin(aIsFlashPlugin),
-    mSupportsAsyncInit(aSupportsAsyncInit),
     mSupportsAsyncRender(aSupportsAsyncRender),
     mLastModifiedTime(aLastModifiedTime),
     mSandboxLevel(aSandboxLevel),
     mNiceFileName(),
     mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
     mCachedBlocklistStateValid(false),
     mIsFromExtension(aFromExtension)
 {
@@ -351,35 +347,27 @@ void nsPluginTag::InitMime(const char* c
     if (!nsPluginHost::IsTypeWhitelisted(mimeType.get())) {
       continue;
     }
 
     // Look for certain special plugins.
     switch (nsPluginHost::GetSpecialType(mimeType)) {
       case nsPluginHost::eSpecialType_Java:
         mIsJavaPlugin = true;
-        mSupportsAsyncInit = true;
         break;
       case nsPluginHost::eSpecialType_Flash:
         // VLC sometimes claims to implement the Flash MIME type, and we want
         // to allow users to control that separately from Adobe Flash.
         if (Name().EqualsLiteral("Shockwave Flash")) {
           mIsFlashPlugin = true;
-          mSupportsAsyncInit = true;
         }
         break;
       case nsPluginHost::eSpecialType_Test:
-        mSupportsAsyncInit = true;
-        break;
       case nsPluginHost::eSpecialType_None:
       default:
-#ifndef RELEASE_OR_BETA
-        // Allow async init for all plugins on Nightly and Aurora
-        mSupportsAsyncInit = true;
-#endif
         break;
     }
 
     // Fill in our MIME type array.
     mMimeTypes.AppendElement(mimeType);
 
     // Now fill in the MIME descriptions.
     if (aMimeDescriptions && aMimeDescriptions[i]) {
--- a/dom/plugins/base/nsPluginTags.h
+++ b/dom/plugins/base/nsPluginTags.h
@@ -127,17 +127,16 @@ public:
               const char* aFileName,
               const char* aFullPath,
               const char* aVersion,
               nsTArray<nsCString> aMimeTypes,
               nsTArray<nsCString> aMimeDescriptions,
               nsTArray<nsCString> aExtensions,
               bool aIsJavaPlugin,
               bool aIsFlashPlugin,
-              bool aSupportsAsyncInit,
               bool aSupportsAsyncRender,
               int64_t aLastModifiedTime,
               bool aFromExtension,
               int32_t aSandboxLevel);
 
   void TryUnloadPlugin(bool inShutdown);
 
   // plugin is enabled and not blocklisted
@@ -164,17 +163,16 @@ public:
 
   // True if we've ever created an instance of this plugin in the current process.
   bool          mHadLocalInstance;
 
   PRLibrary     *mLibrary;
   RefPtr<nsNPAPIPlugin> mPlugin;
   bool          mIsJavaPlugin;
   bool          mIsFlashPlugin;
-  bool          mSupportsAsyncInit;
   bool          mSupportsAsyncRender;
   nsCString     mFullPath; // UTF-8
   int64_t       mLastModifiedTime;
   nsCOMPtr<nsITimer> mUnloadTimer;
   int32_t       mSandboxLevel;
 
   void          InvalidateBlocklistState();
 
--- a/dom/plugins/ipc/BrowserStreamParent.cpp
+++ b/dom/plugins/ipc/BrowserStreamParent.cpp
@@ -1,16 +1,15 @@
 /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
 /* 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 "BrowserStreamParent.h"
-#include "PluginAsyncSurrogate.h"
 #include "PluginInstanceParent.h"
 #include "nsNPAPIPlugin.h"
 
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Unused.h"
 
 // How much data are we willing to send across the wire
 // in one chunk?
@@ -18,17 +17,16 @@ static const int32_t kSendDataChunk = 0x
 
 namespace mozilla {
 namespace plugins {
 
 BrowserStreamParent::BrowserStreamParent(PluginInstanceParent* npp,
                                          NPStream* stream)
   : mNPP(npp)
   , mStream(stream)
-  , mDeferredDestroyReason(NPRES_DONE)
   , mState(INITIALIZING)
 {
   mStream->pdata = static_cast<AStream*>(this);
   nsNPAPIStreamWrapper* wrapper =
     reinterpret_cast<nsNPAPIStreamWrapper*>(mStream->ndata);
   if (wrapper) {
     mStreamListener = wrapper->GetStreamListener();
   }
@@ -41,51 +39,16 @@ BrowserStreamParent::~BrowserStreamParen
 
 void
 BrowserStreamParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   // Implement me! Bug 1005159
 }
 
 mozilla::ipc::IPCResult
-BrowserStreamParent::RecvAsyncNPP_NewStreamResult(const NPError& rv,
-                                                  const uint16_t& stype)
-{
-  PLUGIN_LOG_DEBUG_FUNCTION;
-  PluginAsyncSurrogate* surrogate = mNPP->GetAsyncSurrogate();
-  MOZ_ASSERT(surrogate);
-  surrogate->AsyncCallArriving();
-  if (mState == DEFERRING_DESTROY) {
-    // We've been asked to destroy ourselves before init was complete.
-    mState = DYING;
-    Unused << SendNPP_DestroyStream(mDeferredDestroyReason);
-    return IPC_OK();
-  }
-
-  NPError error = rv;
-  if (error == NPERR_NO_ERROR) {
-    if (!mStreamListener) {
-      return IPC_FAIL_NO_REASON(this);
-    }
-    if (mStreamListener->SetStreamType(stype)) {
-      mState = ALIVE;
-    } else {
-      error = NPERR_GENERIC_ERROR;
-    }
-  }
-
-  if (error != NPERR_NO_ERROR) {
-    surrogate->DestroyAsyncStream(mStream);
-    Unused << PBrowserStreamParent::Send__delete__(this);
-  }
-
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
 BrowserStreamParent::AnswerNPN_RequestRead(const IPCByteRanges& ranges,
                                            NPError* result)
 {
   PLUGIN_LOG_DEBUG_FUNCTION;
 
   switch (mState) {
   case INITIALIZING:
     NS_ERROR("Requesting a read before initialization has completed");
@@ -144,17 +107,16 @@ BrowserStreamParent::RecvNPN_DestroyStre
 void
 BrowserStreamParent::NPP_DestroyStream(NPReason reason)
 {
   NS_ASSERTION(ALIVE == mState || INITIALIZING == mState,
                "NPP_DestroyStream called twice?");
   bool stillInitializing = INITIALIZING == mState;
   if (stillInitializing) {
     mState = DEFERRING_DESTROY;
-    mDeferredDestroyReason = reason;
   } else {
     mState = DYING;
     Unused << SendNPP_DestroyStream(reason);
   }
 }
 
 mozilla::ipc::IPCResult
 BrowserStreamParent::RecvStreamDestroyed()
--- a/dom/plugins/ipc/BrowserStreamParent.h
+++ b/dom/plugins/ipc/BrowserStreamParent.h
@@ -25,20 +25,16 @@ public:
   BrowserStreamParent(PluginInstanceParent* npp,
                       NPStream* stream);
   virtual ~BrowserStreamParent();
 
   virtual bool IsBrowserStream() override { return true; }
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
-  virtual mozilla::ipc::IPCResult RecvAsyncNPP_NewStreamResult(
-    const NPError& rv,
-    const uint16_t& stype) override;
-
   virtual mozilla::ipc::IPCResult AnswerNPN_RequestRead(const IPCByteRanges& ranges,
                                                         NPError* result) override;
 
   virtual mozilla::ipc::IPCResult RecvNPN_DestroyStream(const NPReason& reason) override;
 
   virtual mozilla::ipc::IPCResult RecvStreamDestroyed() override;
 
   int32_t WriteReady();
@@ -56,17 +52,16 @@ public:
 
 private:
   using PBrowserStreamParent::SendNPP_DestroyStream;
 
   PluginInstanceParent* mNPP;
   NPStream* mStream;
   nsCOMPtr<nsISupports> mStreamPeer;
   RefPtr<nsNPAPIPluginStreamListener> mStreamListener;
-  NPReason mDeferredDestroyReason;
 
   enum {
     INITIALIZING,
     DEFERRING_DESTROY,
     ALIVE,
     DYING,
     DELETING
   } mState;
--- a/dom/plugins/ipc/PBrowserStream.ipdl
+++ b/dom/plugins/ipc/PBrowserStream.ipdl
@@ -31,17 +31,16 @@ child:
   /**
    * NPP_DestroyStream may race with other messages: the child acknowledges
    * the message with StreamDestroyed before this actor is deleted.
    */
   async NPP_DestroyStream(NPReason reason);
   async __delete__();
 
 parent:
-  async AsyncNPP_NewStreamResult(NPError rv, uint16_t stype);
   intr NPN_RequestRead(IPCByteRanges ranges)
     returns (NPError result);
   async NPN_DestroyStream(NPReason reason);
   async StreamDestroyed();
 
 /*
   TODO: turn on state machine.
 
--- a/dom/plugins/ipc/PPluginInstance.ipdl
+++ b/dom/plugins/ipc/PPluginInstance.ipdl
@@ -249,19 +249,16 @@ parent:
     returns (NPError result);
 
   intr NPN_ConvertPoint(double sourceX, bool ignoreDestX, double sourceY, bool ignoreDestY, NPCoordinateSpace sourceSpace,
                        NPCoordinateSpace destSpace)
     returns (double destX, double destY, bool result);
 
   async RedrawPlugin();
 
-  // Notifies the parent of its NPP_New result code.
-  async AsyncNPP_NewResult(NPError aResult);
-
   // Sends a native window to be adopted by the native window that would be
   // returned by NPN_GetValue_NPNVnetscapeWindow. Only used on Windows.
   async SetNetscapeWindowAsParent(NativeWindowHandle childWindow);
 
   sync GetCompositionString(uint32_t aType)
                             returns (uint8_t[] aDist, int32_t aLength);
   // Set candidate window position.
   //
@@ -288,19 +285,16 @@ child:
                        nsCString headers);
 
   // Implements the legacy (synchronous) version of NPP_NewStream for when
   // async plugin init is preffed off.
   intr NPP_NewStream(PBrowserStream actor, nsCString mimeType, bool seekable)
     returns (NPError rv,
              uint16_t stype);
 
-  // Implements the async plugin init version of NPP_NewStream.
-  async AsyncNPP_NewStream(PBrowserStream actor, nsCString mimeType, bool seekable);
-
 parent:
   /* NPN_NewStream */
   intr PPluginStream(nsCString mimeType,
                     nsCString target)
     returns (NPError result);
 
 parent:
   intr PluginFocusChange(bool gotFocus);
--- a/dom/plugins/ipc/PPluginModule.ipdl
+++ b/dom/plugins/ipc/PPluginModule.ipdl
@@ -57,30 +57,25 @@ child:
 
   // Forces the child process to update its plugin function table.
   intr NP_GetEntryPoints()
     returns (NPError rv);
 
   intr NP_Initialize(PluginSettings settings)
     returns (NPError rv);
 
-  async AsyncNP_Initialize(PluginSettings settings);
-
   async PPluginInstance(nsCString aMimeType,
                         nsCString[] aNames,
                         nsCString[] aValues);
 
   // Implements the synchronous version of NPP_New for when async plugin init
   // is preffed off.
   intr SyncNPP_New(PPluginInstance aActor)
     returns (NPError rv);
 
-  // Implements the async plugin init version of NPP_New.
-  async AsyncNPP_New(PPluginInstance aActor);
-
   intr NP_Shutdown()
     returns (NPError rv);
 
   intr OptionalFunctionsSupported()
     returns (bool aURLRedirectNotify, bool aClearSiteData,
              bool aGetSitesWithData);
 
   async NPP_ClearSiteData(nsCString site, uint64_t flags, uint64_t maxAge, uint64_t aCallbackId);
@@ -99,18 +94,16 @@ child:
 
   async SettingChanged(PluginSettings settings);
 
   async NPP_SetValue_NPNVaudioDeviceChangeDetails(NPAudioDeviceChangeDetailsIPC changeDetails);
 
   async InitPluginModuleChild(Endpoint<PPluginModuleChild> endpoint);
 
 parent:
-  async NP_InitializeResult(NPError aError);
-
   /**
    * This message is only used on X11 platforms.
    *
    * Send a dup of the plugin process's X socket to the parent
    * process.  In theory, this scheme keeps the plugin's X resources
    * around until after both the plugin process shuts down *and* the
    * parent process closes the dup fd.  This is used to prevent the
    * parent process from crashing on X errors if, e.g., the plugin
deleted file mode 100644
--- a/dom/plugins/ipc/PluginAsyncSurrogate.cpp
+++ /dev/null
@@ -1,996 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 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 "PluginAsyncSurrogate.h"
-
-#include "base/message_loop.h"
-#include "base/message_pump_default.h"
-#include "mozilla/dom/ContentChild.h"
-#include "mozilla/plugins/PluginInstanceParent.h"
-#include "mozilla/plugins/PluginModuleParent.h"
-#include "mozilla/plugins/PluginScriptableObjectParent.h"
-#include "mozilla/Telemetry.h"
-#include "nsJSNPRuntime.h"
-#include "nsNPAPIPlugin.h"
-#include "nsNPAPIPluginInstance.h"
-#include "nsNPAPIPluginStreamListener.h"
-#include "nsPluginInstanceOwner.h"
-#include "nsPluginStreamListenerPeer.h"
-#include "npruntime.h"
-#include "nsThreadUtils.h"
-#include "PluginMessageUtils.h"
-
-namespace mozilla {
-namespace plugins {
-
-AsyncNPObject::AsyncNPObject(PluginAsyncSurrogate* aSurrogate)
-  : NPObject()
-  , mSurrogate(aSurrogate)
-  , mRealObject(nullptr)
-{
-}
-
-AsyncNPObject::~AsyncNPObject()
-{
-  if (mRealObject) {
-    --mRealObject->asyncWrapperCount;
-    parent::_releaseobject(mRealObject);
-    mRealObject = nullptr;
-  }
-}
-
-NPObject*
-AsyncNPObject::GetRealObject()
-{
-  if (mRealObject) {
-    return mRealObject;
-  }
-  PluginInstanceParent* instance = PluginInstanceParent::Cast(mSurrogate->GetNPP());
-  if (!instance) {
-    return nullptr;
-  }
-  NPObject* realObject = nullptr;
-  NPError err = instance->NPP_GetValue(NPPVpluginScriptableNPObject,
-                                       &realObject);
-  if (err != NPERR_NO_ERROR) {
-    return nullptr;
-  }
-  if (realObject->_class != PluginScriptableObjectParent::GetClass()) {
-    NS_ERROR("Don't know what kind of object this is!");
-    parent::_releaseobject(realObject);
-    return nullptr;
-  }
-  mRealObject = static_cast<ParentNPObject*>(realObject);
-  ++mRealObject->asyncWrapperCount;
-  return mRealObject;
-}
-
-class MOZ_STACK_CLASS RecursionGuard
-{
-public:
-  RecursionGuard()
-    : mIsRecursive(sHasEntered)
-  {
-    if (!mIsRecursive) {
-      sHasEntered = true;
-    }
-  }
-
-  ~RecursionGuard()
-  {
-    if (!mIsRecursive) {
-      sHasEntered = false;
-    }
-  }
-
-  inline bool
-  IsRecursive()
-  {
-    return mIsRecursive;
-  }
-
-private:
-  bool        mIsRecursive;
-  static bool sHasEntered;
-};
-
-bool RecursionGuard::sHasEntered = false;
-
-PluginAsyncSurrogate::PluginAsyncSurrogate(PluginModuleParent* aParent)
-  : mParent(aParent)
-  , mWindow(nullptr)
-  , mAcceptCalls(false)
-  , mInstantiated(false)
-  , mAsyncSetWindow(false)
-  , mInitCancelled(false)
-  , mDestroyPending(false)
-  , mAsyncCallsInFlight(0)
-{
-  MOZ_ASSERT(aParent);
-}
-
-PluginAsyncSurrogate::~PluginAsyncSurrogate()
-{
-}
-
-bool
-PluginAsyncSurrogate::Init(NPMIMEType aPluginType, NPP aInstance,
-                           int16_t aArgc, char* aArgn[], char* aArgv[])
-{
-  mMimeType = aPluginType;
-  nsNPAPIPluginInstance* instance =
-    static_cast<nsNPAPIPluginInstance*>(aInstance->ndata);
-  MOZ_ASSERT(instance);
-  mInstance = instance;
-  for (int i = 0; i < aArgc; ++i) {
-    mNames.AppendElement(NullableString(aArgn[i]));
-    mValues.AppendElement(NullableString(aArgv[i]));
-  }
-  return true;
-}
-
-/* static */ bool
-PluginAsyncSurrogate::Create(PluginModuleParent* aParent, NPMIMEType aPluginType,
-                             NPP aInstance, int16_t aArgc,
-                             char* aArgn[], char* aArgv[])
-{
-  RefPtr<PluginAsyncSurrogate> surrogate(new PluginAsyncSurrogate(aParent));
-  if (!surrogate->Init(aPluginType, aInstance, aArgc, aArgn, aArgv)) {
-    return false;
-  }
-  PluginAsyncSurrogate* rawSurrogate = nullptr;
-  surrogate.forget(&rawSurrogate);
-  aInstance->pdata = static_cast<PluginDataResolver*>(rawSurrogate);
-  return true;
-}
-
-/* static */ PluginAsyncSurrogate*
-PluginAsyncSurrogate::Cast(NPP aInstance)
-{
-  MOZ_ASSERT(aInstance);
-  PluginDataResolver* resolver =
-    reinterpret_cast<PluginDataResolver*>(aInstance->pdata);
-  if (!resolver) {
-    return nullptr;
-  }
-  return resolver->GetAsyncSurrogate();
-}
-
-nsresult
-PluginAsyncSurrogate::NPP_New(NPError* aError)
-{
-  if (!mInstance) {
-    return NS_ERROR_NULL_POINTER;
-  }
-
-  nsresult rv = mParent->NPP_NewInternal(mMimeType.BeginWriting(), GetNPP(),
-                                         mNames, mValues, nullptr,
-                                         aError);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return NS_OK;
-}
-
-void
-PluginAsyncSurrogate::NP_GetEntryPoints(NPPluginFuncs* aFuncs)
-{
-  aFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
-  aFuncs->destroy = &NPP_Destroy;
-  aFuncs->getvalue = &NPP_GetValue;
-  aFuncs->setvalue = &NPP_SetValue;
-  aFuncs->newstream = &NPP_NewStream;
-  aFuncs->setwindow = &NPP_SetWindow;
-  aFuncs->writeready = &NPP_WriteReady;
-  aFuncs->event = &NPP_HandleEvent;
-  aFuncs->destroystream = &NPP_DestroyStream;
-  // We need to set these so that content code doesn't make assumptions
-  // about these operations not being supported
-  aFuncs->write = &PluginModuleParent::NPP_Write;
-  aFuncs->asfile = &PluginModuleParent::NPP_StreamAsFile;
-}
-
-/* static */ void
-PluginAsyncSurrogate::NotifyDestroyPending(NPP aInstance)
-{
-  PluginAsyncSurrogate* surrogate = Cast(aInstance);
-  if (!surrogate) {
-    return;
-  }
-  surrogate->NotifyDestroyPending();
-}
-
-NPP
-PluginAsyncSurrogate::GetNPP()
-{
-  MOZ_ASSERT(mInstance);
-  NPP npp;
-  DebugOnly<nsresult> rv = mInstance->GetNPP(&npp);
-  MOZ_ASSERT(NS_SUCCEEDED(rv));
-  return npp;
-}
-
-void
-PluginAsyncSurrogate::NotifyDestroyPending()
-{
-  mDestroyPending = true;
-  nsJSNPRuntime::OnPluginDestroyPending(GetNPP());
-}
-
-NPError
-PluginAsyncSurrogate::NPP_Destroy(NPSavedData** aSave)
-{
-  NotifyDestroyPending();
-  if (!WaitForInit()) {
-    return NPERR_GENERIC_ERROR;
-  }
-  return PluginModuleParent::NPP_Destroy(GetNPP(), aSave);
-}
-
-NPError
-PluginAsyncSurrogate::NPP_GetValue(NPPVariable aVariable, void* aRetval)
-{
-  if (aVariable != NPPVpluginScriptableNPObject) {
-    if (!WaitForInit()) {
-      return NPERR_GENERIC_ERROR;
-    }
-
-    PluginInstanceParent* instance = PluginInstanceParent::Cast(GetNPP());
-    MOZ_ASSERT(instance);
-    return instance->NPP_GetValue(aVariable, aRetval);
-  }
-
-  NPObject* npobject = parent::_createobject(GetNPP(),
-                                             const_cast<NPClass*>(GetClass()));
-  MOZ_ASSERT(npobject);
-  MOZ_ASSERT(npobject->_class == GetClass());
-  MOZ_ASSERT(npobject->referenceCount == 1);
-  *(NPObject**)aRetval = npobject;
-  return npobject ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
-}
-
-NPError
-PluginAsyncSurrogate::NPP_SetValue(NPNVariable aVariable, void* aValue)
-{
-  if (!WaitForInit()) {
-    return NPERR_GENERIC_ERROR;
-  }
-  return PluginModuleParent::NPP_SetValue(GetNPP(), aVariable, aValue);
-}
-
-NPError
-PluginAsyncSurrogate::NPP_NewStream(NPMIMEType aType, NPStream* aStream,
-                                    NPBool aSeekable, uint16_t* aStype)
-{
-  mPendingNewStreamCalls.AppendElement(PendingNewStreamCall(aType, aStream,
-                                                            aSeekable));
-  if (aStype) {
-    *aStype = nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN;
-  }
-  return NPERR_NO_ERROR;
-}
-
-NPError
-PluginAsyncSurrogate::NPP_SetWindow(NPWindow* aWindow)
-{
-  mWindow = aWindow;
-  mAsyncSetWindow = false;
-  return NPERR_NO_ERROR;
-}
-
-nsresult
-PluginAsyncSurrogate::AsyncSetWindow(NPWindow* aWindow)
-{
-  mWindow = aWindow;
-  mAsyncSetWindow = true;
-  return NS_OK;
-}
-
-void
-PluginAsyncSurrogate::NPP_Print(NPPrint* aPrintInfo)
-{
-  // Do nothing, we've got nothing to print right now
-}
-
-int16_t
-PluginAsyncSurrogate::NPP_HandleEvent(void* event)
-{
-  // Drop the event -- the plugin isn't around to handle it
-  return false;
-}
-
-int32_t
-PluginAsyncSurrogate::NPP_WriteReady(NPStream* aStream)
-{
-  // We'll tell the browser to retry in a bit. Eventually NPP_WriteReady
-  // will resolve to the plugin's NPP_WriteReady and this should all just work.
-  return 0;
-}
-
-NPError
-PluginAsyncSurrogate::NPP_DestroyStream(NPStream* aStream, NPReason aReason)
-{
-  for (uint32_t idx = 0, len = mPendingNewStreamCalls.Length(); idx < len; ++idx) {
-    PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[idx];
-    if (curPendingCall.mStream == aStream) {
-      mPendingNewStreamCalls.RemoveElementAt(idx);
-      break;
-    }
-  }
-  return NPERR_NO_ERROR;
-}
-
-/* static */ NPError
-PluginAsyncSurrogate::NPP_Destroy(NPP aInstance, NPSavedData** aSave)
-{
-  PluginAsyncSurrogate* rawSurrogate = Cast(aInstance);
-  MOZ_ASSERT(rawSurrogate);
-  PluginModuleParent* module = rawSurrogate->GetParent();
-  if (module && !module->IsInitialized()) {
-    // Take ownership of pdata's surrogate since we're going to release it
-    RefPtr<PluginAsyncSurrogate> surrogate(dont_AddRef(rawSurrogate));
-    aInstance->pdata = nullptr;
-    // We haven't actually called NPP_New yet, so we should remove the
-    // surrogate for this instance.
-    bool removeOk = module->RemovePendingSurrogate(surrogate);
-    MOZ_ASSERT(removeOk);
-    if (!removeOk) {
-      return NPERR_GENERIC_ERROR;
-    }
-    surrogate->mInitCancelled = true;
-    return NPERR_NO_ERROR;
-  }
-  return rawSurrogate->NPP_Destroy(aSave);
-}
-
-/* static */ NPError
-PluginAsyncSurrogate::NPP_GetValue(NPP aInstance, NPPVariable aVariable,
-                                   void* aRetval)
-{
-  PluginAsyncSurrogate* surrogate = Cast(aInstance);
-  MOZ_ASSERT(surrogate);
-  return surrogate->NPP_GetValue(aVariable, aRetval);
-}
-
-/* static */ NPError
-PluginAsyncSurrogate::NPP_SetValue(NPP aInstance, NPNVariable aVariable,
-                                   void* aValue)
-{
-  PluginAsyncSurrogate* surrogate = Cast(aInstance);
-  MOZ_ASSERT(surrogate);
-  return surrogate->NPP_SetValue(aVariable, aValue);
-}
-
-/* static */ NPError
-PluginAsyncSurrogate::NPP_NewStream(NPP aInstance, NPMIMEType aType,
-                                    NPStream* aStream, NPBool aSeekable,
-                                    uint16_t* aStype)
-{
-  PluginAsyncSurrogate* surrogate = Cast(aInstance);
-  MOZ_ASSERT(surrogate);
-  return surrogate->NPP_NewStream(aType, aStream, aSeekable, aStype);
-}
-
-/* static */ NPError
-PluginAsyncSurrogate::NPP_SetWindow(NPP aInstance, NPWindow* aWindow)
-{
-  PluginAsyncSurrogate* surrogate = Cast(aInstance);
-  MOZ_ASSERT(surrogate);
-  return surrogate->NPP_SetWindow(aWindow);
-}
-
-/* static */ void
-PluginAsyncSurrogate::NPP_Print(NPP aInstance, NPPrint* aPrintInfo)
-{
-  PluginAsyncSurrogate* surrogate = Cast(aInstance);
-  MOZ_ASSERT(surrogate);
-  surrogate->NPP_Print(aPrintInfo);
-}
-
-/* static */ int16_t
-PluginAsyncSurrogate::NPP_HandleEvent(NPP aInstance, void* aEvent)
-{
-  PluginAsyncSurrogate* surrogate = Cast(aInstance);
-  MOZ_ASSERT(surrogate);
-  return surrogate->NPP_HandleEvent(aEvent);
-}
-
-/* static */ int32_t
-PluginAsyncSurrogate::NPP_WriteReady(NPP aInstance, NPStream* aStream)
-{
-  PluginAsyncSurrogate* surrogate = Cast(aInstance);
-  MOZ_ASSERT(surrogate);
-  return surrogate->NPP_WriteReady(aStream);
-}
-
-/* static */ NPError
-PluginAsyncSurrogate::NPP_DestroyStream(NPP aInstance,
-                                        NPStream* aStream,
-                                        NPReason aReason)
-{
-  PluginAsyncSurrogate* surrogate = Cast(aInstance);
-  MOZ_ASSERT(surrogate);
-  return surrogate->NPP_DestroyStream(aStream, aReason);
-}
-
-PluginAsyncSurrogate::PendingNewStreamCall::PendingNewStreamCall(
-    NPMIMEType aType, NPStream* aStream, NPBool aSeekable)
-  : mType(NullableString(aType))
-  , mStream(aStream)
-  , mSeekable(aSeekable)
-{
-}
-
-/* static */ nsNPAPIPluginStreamListener*
-PluginAsyncSurrogate::GetStreamListener(NPStream* aStream)
-{
-  nsNPAPIStreamWrapper* wrapper =
-    reinterpret_cast<nsNPAPIStreamWrapper*>(aStream->ndata);
-  if (!wrapper) {
-    return nullptr;
-  }
-  return wrapper->GetStreamListener();
-}
-
-void
-PluginAsyncSurrogate::DestroyAsyncStream(NPStream* aStream)
-{
-  MOZ_ASSERT(aStream);
-  nsNPAPIPluginStreamListener* streamListener = GetStreamListener(aStream);
-  MOZ_ASSERT(streamListener);
-  // streamListener was suspended during async init. We must resume the stream
-  // request prior to calling _destroystream for cleanup to work correctly.
-  streamListener->ResumeRequest();
-  if (!mInstance) {
-    return;
-  }
-  parent::_destroystream(GetNPP(), aStream, NPRES_DONE);
-}
-
-/* static */ bool
-PluginAsyncSurrogate::SetStreamType(NPStream* aStream, uint16_t aStreamType)
-{
-  nsNPAPIPluginStreamListener* streamListener = GetStreamListener(aStream);
-  if (!streamListener) {
-    return false;
-  }
-  return streamListener->SetStreamType(aStreamType);
-}
-
-void
-PluginAsyncSurrogate::OnInstanceCreated(PluginInstanceParent* aInstance)
-{
-  if (!mDestroyPending) {
-    // If NPP_Destroy has already been called then these streams have already
-    // been cleaned up on the browser side and are no longer valid.
-    for (uint32_t i = 0, len = mPendingNewStreamCalls.Length(); i < len; ++i) {
-      PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[i];
-      uint16_t streamType = NP_NORMAL;
-      NPError curError = aInstance->NPP_NewStream(
-                      const_cast<char*>(NullableStringGet(curPendingCall.mType)),
-                      curPendingCall.mStream, curPendingCall.mSeekable,
-                      &streamType);
-      if (curError != NPERR_NO_ERROR) {
-        // If we failed here then the send failed and we need to clean up
-        DestroyAsyncStream(curPendingCall.mStream);
-      }
-    }
-  }
-  mPendingNewStreamCalls.Clear();
-  mInstantiated = true;
-}
-
-/**
- * During asynchronous initialization it might be necessary to wait for the
- * plugin to complete its initialization. This typically occurs when the result
- * of a plugin call depends on the plugin being fully instantiated. For example,
- * if some JS calls into the plugin, the call must be executed synchronously to
- * preserve correctness.
- *
- * This function works by pumping the plugin's IPC channel for events until
- * initialization has completed.
- */
-bool
-PluginAsyncSurrogate::WaitForInit()
-{
-  if (mInitCancelled) {
-    return false;
-  }
-  if (mAcceptCalls) {
-    return true;
-  }
-  Telemetry::AutoTimer<Telemetry::BLOCKED_ON_PLUGINASYNCSURROGATE_WAITFORINIT_MS>
-    timer(mParent->GetHistogramKey());
-  bool result = false;
-  MOZ_ASSERT(mParent);
-  if (mParent->IsChrome()) {
-    PluginProcessParent* process = static_cast<PluginModuleChromeParent*>(mParent)->Process();
-    MOZ_ASSERT(process);
-    process->SetCallRunnableImmediately(true);
-    if (!process->WaitUntilConnected()) {
-      return false;
-    }
-  }
-  if (!mParent->WaitForIPCConnection()) {
-    return false;
-  }
-  if (!mParent->IsChrome()) {
-    // For e10s content processes, we need to spin the content channel until the
-    // protocol bridging has occurred.
-    dom::ContentChild* cp = dom::ContentChild::GetSingleton();
-    mozilla::ipc::MessageChannel* contentChannel = cp->GetIPCChannel();
-    MOZ_ASSERT(contentChannel);
-    while (!mParent->mNPInitialized) {
-      if (mParent->mShutdown) {
-        // Since we are pumping the message channel for events, it may be
-        // possible for module initialization to fail during this loop. We must
-        // return false if this happens or else we'll be permanently stuck.
-        return false;
-      }
-      result = contentChannel->WaitForIncomingMessage();
-      if (!result) {
-        return result;
-      }
-    }
-  }
-  mozilla::ipc::MessageChannel* channel = mParent->GetIPCChannel();
-  MOZ_ASSERT(channel);
-  while (!mAcceptCalls) {
-    if (mInitCancelled) {
-      // Since we are pumping the message channel for events, it may be
-      // possible for plugin instantiation to fail during this loop. We must
-      // return false if this happens or else we'll be permanently stuck.
-      return false;
-    }
-    result = channel->WaitForIncomingMessage();
-    if (!result) {
-      break;
-    }
-  }
-  return result;
-}
-
-void
-PluginAsyncSurrogate::AsyncCallDeparting()
-{
-  ++mAsyncCallsInFlight;
-  if (!mPluginDestructionGuard) {
-    mPluginDestructionGuard = MakeUnique<PluginDestructionGuard>(this);
-  }
-}
-
-void
-PluginAsyncSurrogate::AsyncCallArriving()
-{
-  MOZ_ASSERT(mAsyncCallsInFlight > 0);
-  if (--mAsyncCallsInFlight == 0) {
-    mPluginDestructionGuard.reset(nullptr);
-  }
-}
-
-void
-PluginAsyncSurrogate::NotifyAsyncInitFailed()
-{
-  if (!mDestroyPending) {
-    // Clean up any pending NewStream requests
-    for (uint32_t i = 0, len = mPendingNewStreamCalls.Length(); i < len; ++i) {
-      PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[i];
-      DestroyAsyncStream(curPendingCall.mStream);
-    }
-  }
-  mPendingNewStreamCalls.Clear();
-
-  // Make sure that any WaitForInit calls on this surrogate will fail, or else
-  // we'll be perma-blocked
-  mInitCancelled = true;
-
-  if (!mInstance) {
-      return;
-  }
-  nsPluginInstanceOwner* owner = mInstance->GetOwner();
-  if (owner) {
-    owner->NotifyHostAsyncInitFailed();
-  }
-}
-
-// static
-NPObject*
-PluginAsyncSurrogate::ScriptableAllocate(NPP aInstance, NPClass* aClass)
-{
-  PLUGIN_LOG_DEBUG_FUNCTION;
-  if (aClass != GetClass()) {
-    NS_ERROR("Huh?! Wrong class!");
-    return nullptr;
-  }
-
-  return new AsyncNPObject(Cast(aInstance));
-}
-
-// static
-void
-PluginAsyncSurrogate::ScriptableInvalidate(NPObject* aObject)
-{
-  PLUGIN_LOG_DEBUG_FUNCTION;
-  if (aObject->_class != GetClass()) {
-    NS_ERROR("Don't know what kind of object this is!");
-    return;
-  }
-
-  AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject);
-  if (!object->mSurrogate->WaitForInit()) {
-    return;
-  }
-  NPObject* realObject = object->GetRealObject();
-  if (!realObject) {
-    return;
-  }
-  realObject->_class->invalidate(realObject);
-}
-
-// static
-void
-PluginAsyncSurrogate::ScriptableDeallocate(NPObject* aObject)
-{
-  PLUGIN_LOG_DEBUG_FUNCTION;
-  if (aObject->_class != GetClass()) {
-    NS_ERROR("Don't know what kind of object this is!");
-    return;
-  }
-
-  AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject);
-  delete object;
-}
-
-// static
-bool
-PluginAsyncSurrogate::ScriptableHasMethod(NPObject* aObject,
-                                                  NPIdentifier aName)
-{
-  PLUGIN_LOG_DEBUG_FUNCTION;
-  if (aObject->_class != GetClass()) {
-    NS_ERROR("Don't know what kind of object this is!");
-    return false;
-  }
-
-  RecursionGuard guard;
-  if (guard.IsRecursive()) {
-    return false;
-  }
-
-  AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject);
-  MOZ_ASSERT(object);
-  bool checkPluginObject = !object->mSurrogate->mInstantiated &&
-                           !object->mSurrogate->mAcceptCalls;
-
-  if (!object->mSurrogate->WaitForInit()) {
-    return false;
-  }
-  NPObject* realObject = object->GetRealObject();
-  if (!realObject) {
-    return false;
-  }
-  bool result = realObject->_class->hasMethod(realObject, aName);
-  if (!result && checkPluginObject) {
-    // We may be calling into this object because properties in the WebIDL
-    // object hadn't been set yet. Now that we're further along in
-    // initialization, we should try again.
-    const NPNetscapeFuncs* npn = object->mSurrogate->mParent->GetNetscapeFuncs();
-    NPObject* pluginObject = nullptr;
-    NPError nperror = npn->getvalue(object->mSurrogate->GetNPP(),
-                                    NPNVPluginElementNPObject,
-                                    (void*)&pluginObject);
-    if (nperror == NPERR_NO_ERROR) {
-      NPPAutoPusher nppPusher(object->mSurrogate->GetNPP());
-      result = pluginObject->_class->hasMethod(pluginObject, aName);
-      npn->releaseobject(pluginObject);
-      NPUTF8* idstr = npn->utf8fromidentifier(aName);
-      npn->memfree(idstr);
-    }
-  }
-  return result;
-}
-
-bool
-PluginAsyncSurrogate::GetPropertyHelper(NPObject* aObject, NPIdentifier aName,
-                                        bool* aHasProperty, bool* aHasMethod,
-                                        NPVariant* aResult)
-{
-  PLUGIN_LOG_DEBUG_FUNCTION;
-
-  if (!aObject) {
-    return false;
-  }
-
-  RecursionGuard guard;
-  if (guard.IsRecursive()) {
-    return false;
-  }
-
-  if (!WaitForInit()) {
-    return false;
-  }
-
-  AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject);
-  NPObject* realObject = object->GetRealObject();
-  if (!realObject) {
-    return false;
-  }
-  if (realObject->_class != PluginScriptableObjectParent::GetClass()) {
-    NS_ERROR("Don't know what kind of object this is!");
-    return false;
-  }
-
-  PluginScriptableObjectParent* actor =
-    static_cast<ParentNPObject*>(realObject)->parent;
-  if (!actor) {
-    return false;
-  }
-  bool success = actor->GetPropertyHelper(aName, aHasProperty, aHasMethod, aResult);
-  if (!success) {
-    const NPNetscapeFuncs* npn = mParent->GetNetscapeFuncs();
-    NPObject* pluginObject = nullptr;
-    NPError nperror = npn->getvalue(GetNPP(), NPNVPluginElementNPObject,
-                                    (void*)&pluginObject);
-    if (nperror == NPERR_NO_ERROR) {
-      NPPAutoPusher nppPusher(GetNPP());
-      bool hasProperty = nsJSObjWrapper::HasOwnProperty(pluginObject, aName);
-      NPUTF8* idstr = npn->utf8fromidentifier(aName);
-      npn->memfree(idstr);
-      bool hasMethod = false;
-      if (hasProperty) {
-        hasMethod = pluginObject->_class->hasMethod(pluginObject, aName);
-        success = pluginObject->_class->getProperty(pluginObject, aName, aResult);
-        idstr = npn->utf8fromidentifier(aName);
-        npn->memfree(idstr);
-      }
-      *aHasProperty = hasProperty;
-      *aHasMethod = hasMethod;
-      npn->releaseobject(pluginObject);
-    }
-  }
-  return success;
-}
-
-// static
-bool
-PluginAsyncSurrogate::ScriptableInvoke(NPObject* aObject,
-                                               NPIdentifier aName,
-                                               const NPVariant* aArgs,
-                                               uint32_t aArgCount,
-                                               NPVariant* aResult)
-{
-  PLUGIN_LOG_DEBUG_FUNCTION;
-  if (aObject->_class != GetClass()) {
-    NS_ERROR("Don't know what kind of object this is!");
-    return false;
-  }
-
-  AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject);
-  if (!object->mSurrogate->WaitForInit()) {
-    return false;
-  }
-  NPObject* realObject = object->GetRealObject();
-  if (!realObject) {
-    return false;
-  }
-  return realObject->_class->invoke(realObject, aName, aArgs, aArgCount, aResult);
-}
-
-// static
-bool
-PluginAsyncSurrogate::ScriptableInvokeDefault(NPObject* aObject,
-                                                      const NPVariant* aArgs,
-                                                      uint32_t aArgCount,
-                                                      NPVariant* aResult)
-{
-  PLUGIN_LOG_DEBUG_FUNCTION;
-  if (aObject->_class != GetClass()) {
-    NS_ERROR("Don't know what kind of object this is!");
-    return false;
-  }
-
-  AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject);
-  if (!object->mSurrogate->WaitForInit()) {
-    return false;
-  }
-  NPObject* realObject = object->GetRealObject();
-  if (!realObject) {
-    return false;
-  }
-  return realObject->_class->invokeDefault(realObject, aArgs, aArgCount, aResult);
-}
-
-// static
-bool
-PluginAsyncSurrogate::ScriptableHasProperty(NPObject* aObject,
-                                                    NPIdentifier aName)
-{
-  PLUGIN_LOG_DEBUG_FUNCTION;
-  if (aObject->_class != GetClass()) {
-    NS_ERROR("Don't know what kind of object this is!");
-    return false;
-  }
-
-  RecursionGuard guard;
-  if (guard.IsRecursive()) {
-    return false;
-  }
-
-  AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject);
-  MOZ_ASSERT(object);
-  bool checkPluginObject = !object->mSurrogate->mInstantiated &&
-                           !object->mSurrogate->mAcceptCalls;
-
-  if (!object->mSurrogate->WaitForInit()) {
-    return false;
-  }
-  NPObject* realObject = object->GetRealObject();
-  if (!realObject) {
-    return false;
-  }
-  bool result = realObject->_class->hasProperty(realObject, aName);
-  const NPNetscapeFuncs* npn = object->mSurrogate->mParent->GetNetscapeFuncs();
-  NPUTF8* idstr = npn->utf8fromidentifier(aName);
-  npn->memfree(idstr);
-  if (!result && checkPluginObject) {
-    // We may be calling into this object because properties in the WebIDL
-    // object hadn't been set yet. Now that we're further along in
-    // initialization, we should try again.
-    NPObject* pluginObject = nullptr;
-    NPError nperror = npn->getvalue(object->mSurrogate->GetNPP(),
-                                    NPNVPluginElementNPObject,
-                                    (void*)&pluginObject);
-    if (nperror == NPERR_NO_ERROR) {
-      NPPAutoPusher nppPusher(object->mSurrogate->GetNPP());
-      result = nsJSObjWrapper::HasOwnProperty(pluginObject, aName);
-      npn->releaseobject(pluginObject);
-      idstr = npn->utf8fromidentifier(aName);
-      npn->memfree(idstr);
-    }
-  }
-  return result;
-}
-
-// static
-bool
-PluginAsyncSurrogate::ScriptableGetProperty(NPObject* aObject,
-                                                    NPIdentifier aName,
-                                                    NPVariant* aResult)
-{
-  PLUGIN_LOG_DEBUG_FUNCTION;
-  // See GetPropertyHelper below.
-  NS_NOTREACHED("Shouldn't ever call this directly!");
-  return false;
-}
-
-// static
-bool
-PluginAsyncSurrogate::ScriptableSetProperty(NPObject* aObject,
-                                                    NPIdentifier aName,
-                                                    const NPVariant* aValue)
-{
-  PLUGIN_LOG_DEBUG_FUNCTION;
-  if (aObject->_class != GetClass()) {
-    NS_ERROR("Don't know what kind of object this is!");
-    return false;
-  }
-
-  AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject);
-  if (!object->mSurrogate->WaitForInit()) {
-    return false;
-  }
-  NPObject* realObject = object->GetRealObject();
-  if (!realObject) {
-    return false;
-  }
-  return realObject->_class->setProperty(realObject, aName, aValue);
-}
-
-// static
-bool
-PluginAsyncSurrogate::ScriptableRemoveProperty(NPObject* aObject,
-                                                       NPIdentifier aName)
-{
-  PLUGIN_LOG_DEBUG_FUNCTION;
-  if (aObject->_class != GetClass()) {
-    NS_ERROR("Don't know what kind of object this is!");
-    return false;
-  }
-
-  AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject);
-  if (!object->mSurrogate->WaitForInit()) {
-    return false;
-  }
-  NPObject* realObject = object->GetRealObject();
-  if (!realObject) {
-    return false;
-  }
-  return realObject->_class->removeProperty(realObject, aName);
-}
-
-// static
-bool
-PluginAsyncSurrogate::ScriptableEnumerate(NPObject* aObject,
-                                                  NPIdentifier** aIdentifiers,
-                                                  uint32_t* aCount)
-{
-  PLUGIN_LOG_DEBUG_FUNCTION;
-  if (aObject->_class != GetClass()) {
-    NS_ERROR("Don't know what kind of object this is!");
-    return false;
-  }
-
-  AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject);
-  if (!object->mSurrogate->WaitForInit()) {
-    return false;
-  }
-  NPObject* realObject = object->GetRealObject();
-  if (!realObject) {
-    return false;
-  }
-  return realObject->_class->enumerate(realObject, aIdentifiers, aCount);
-}
-
-// static
-bool
-PluginAsyncSurrogate::ScriptableConstruct(NPObject* aObject,
-                                                  const NPVariant* aArgs,
-                                                  uint32_t aArgCount,
-                                                  NPVariant* aResult)
-{
-  PLUGIN_LOG_DEBUG_FUNCTION;
-  if (aObject->_class != GetClass()) {
-    NS_ERROR("Don't know what kind of object this is!");
-    return false;
-  }
-
-  AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject);
-  if (!object->mSurrogate->WaitForInit()) {
-    return false;
-  }
-  NPObject* realObject = object->GetRealObject();
-  if (!realObject) {
-    return false;
-  }
-  return realObject->_class->construct(realObject, aArgs, aArgCount, aResult);
-}
-
-const NPClass PluginAsyncSurrogate::sNPClass = {
-  NP_CLASS_STRUCT_VERSION,
-  PluginAsyncSurrogate::ScriptableAllocate,
-  PluginAsyncSurrogate::ScriptableDeallocate,
-  PluginAsyncSurrogate::ScriptableInvalidate,
-  PluginAsyncSurrogate::ScriptableHasMethod,
-  PluginAsyncSurrogate::ScriptableInvoke,
-  PluginAsyncSurrogate::ScriptableInvokeDefault,
-  PluginAsyncSurrogate::ScriptableHasProperty,
-  PluginAsyncSurrogate::ScriptableGetProperty,
-  PluginAsyncSurrogate::ScriptableSetProperty,
-  PluginAsyncSurrogate::ScriptableRemoveProperty,
-  PluginAsyncSurrogate::ScriptableEnumerate,
-  PluginAsyncSurrogate::ScriptableConstruct
-};
-
-PushSurrogateAcceptCalls::PushSurrogateAcceptCalls(PluginInstanceParent* aInstance)
-  : mSurrogate(nullptr)
-  , mPrevAcceptCallsState(false)
-{
-  MOZ_ASSERT(aInstance);
-  mSurrogate = aInstance->GetAsyncSurrogate();
-  if (mSurrogate) {
-    mPrevAcceptCallsState = mSurrogate->SetAcceptingCalls(true);
-  }
-}
-
-PushSurrogateAcceptCalls::~PushSurrogateAcceptCalls()
-{
-  if (mSurrogate) {
-    mSurrogate->SetAcceptingCalls(mPrevAcceptCallsState);
-  }
-}
-
-} // namespace plugins
-} // namespace mozilla
deleted file mode 100644
--- a/dom/plugins/ipc/PluginAsyncSurrogate.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 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/. */
-
-#ifndef dom_plugins_ipc_PluginAsyncSurrogate_h
-#define dom_plugins_ipc_PluginAsyncSurrogate_h
-
-#include "mozilla/UniquePtr.h"
-#include "npapi.h"
-#include "npfunctions.h"
-#include "npruntime.h"
-#include "nsISupportsImpl.h"
-#include "nsPluginHost.h"
-#include "nsString.h"
-#include "nsTArray.h"
-#include "PluginDataResolver.h"
-
-namespace mozilla {
-namespace plugins {
-
-struct ParentNPObject;
-class PluginInstanceParent;
-class PluginModuleParent;
-
-class PluginAsyncSurrogate : public PluginDataResolver
-{
-public:
-  NS_INLINE_DECL_REFCOUNTING(PluginAsyncSurrogate)
-
-  bool Init(NPMIMEType aPluginType, NPP aInstance,
-            int16_t aArgc, char* aArgn[], char* aArgv[]);
-  nsresult NPP_New(NPError* aError);
-  NPError NPP_Destroy(NPSavedData** aSave);
-  NPError NPP_GetValue(NPPVariable aVariable, void* aRetval);
-  NPError NPP_SetValue(NPNVariable aVariable, void* aValue);
-  NPError NPP_NewStream(NPMIMEType aType, NPStream* aStream, NPBool aSeekable,
-                        uint16_t* aStype);
-  NPError NPP_SetWindow(NPWindow* aWindow);
-  nsresult AsyncSetWindow(NPWindow* aWindow);
-  void NPP_Print(NPPrint* aPrintInfo);
-  int16_t NPP_HandleEvent(void* aEvent);
-  int32_t NPP_WriteReady(NPStream* aStream);
-  NPError NPP_DestroyStream(NPStream* aStream, NPReason aReason);
-  void OnInstanceCreated(PluginInstanceParent* aInstance);
-  static bool Create(PluginModuleParent* aParent, NPMIMEType aPluginType,
-                     NPP aInstance, int16_t aArgc,
-                     char* aArgn[], char* aArgv[]);
-  static const NPClass* GetClass() { return &sNPClass; }
-  static void NP_GetEntryPoints(NPPluginFuncs* aFuncs);
-  static PluginAsyncSurrogate* Cast(NPP aInstance);
-  static void NotifyDestroyPending(NPP aInstance);
-  void NotifyDestroyPending();
-
-  virtual PluginAsyncSurrogate*
-  GetAsyncSurrogate() { return this; }
-
-  virtual PluginInstanceParent*
-  GetInstance() { return nullptr; }
-
-  NPP GetNPP();
-
-  bool GetPropertyHelper(NPObject* aObject, NPIdentifier aName,
-                         bool* aHasProperty, bool* aHasMethod,
-                         NPVariant* aResult);
-
-  PluginModuleParent* GetParent() { return mParent; }
-
-  bool IsDestroyPending() const { return mDestroyPending; }
-
-  bool SetAcceptingCalls(bool aAccept)
-  {
-    bool prevState = mAcceptCalls;
-    if (mInstantiated) {
-      aAccept = true;
-    }
-    mAcceptCalls = aAccept;
-    return prevState;
-  }
-
-  void AsyncCallDeparting();
-  void AsyncCallArriving();
-
-  void NotifyAsyncInitFailed();
-  void DestroyAsyncStream(NPStream* aStream);
-
-private:
-  explicit PluginAsyncSurrogate(PluginModuleParent* aParent);
-  virtual ~PluginAsyncSurrogate();
-
-  bool WaitForInit();
-
-  static bool SetStreamType(NPStream* aStream, uint16_t aStreamType);
-
-  static NPError NPP_Destroy(NPP aInstance, NPSavedData** aSave);
-  static NPError NPP_GetValue(NPP aInstance, NPPVariable aVariable, void* aRetval);
-  static NPError NPP_SetValue(NPP aInstance, NPNVariable aVariable, void* aValue);
-  static NPError NPP_NewStream(NPP aInstance, NPMIMEType aType, NPStream* aStream,
-                               NPBool aSeekable, uint16_t* aStype);
-  static NPError NPP_SetWindow(NPP aInstance, NPWindow* aWindow);
-  static void NPP_Print(NPP aInstance, NPPrint* aPrintInfo);
-  static int16_t NPP_HandleEvent(NPP aInstance, void* aEvent);
-  static int32_t NPP_WriteReady(NPP aInstance, NPStream* aStream);
-  static NPError NPP_DestroyStream(NPP aInstance, NPStream* aStream,
-                                   NPReason aReason);
-
-  static NPObject* ScriptableAllocate(NPP aInstance, NPClass* aClass);
-  static void ScriptableInvalidate(NPObject* aObject);
-  static void ScriptableDeallocate(NPObject* aObject);
-  static bool ScriptableHasMethod(NPObject* aObject, NPIdentifier aName);
-  static bool ScriptableInvoke(NPObject* aObject, NPIdentifier aName,
-                               const NPVariant* aArgs, uint32_t aArgCount,
-                               NPVariant* aResult);
-  static bool ScriptableInvokeDefault(NPObject* aObject, const NPVariant* aArgs,
-                                      uint32_t aArgCount, NPVariant* aResult);
-  static bool ScriptableHasProperty(NPObject* aObject, NPIdentifier aName);
-  static bool ScriptableGetProperty(NPObject* aObject, NPIdentifier aName,
-                                    NPVariant* aResult);
-  static bool ScriptableSetProperty(NPObject* aObject, NPIdentifier aName,
-                                    const NPVariant* aValue);
-  static bool ScriptableRemoveProperty(NPObject* aObject, NPIdentifier aName);
-  static bool ScriptableEnumerate(NPObject* aObject, NPIdentifier** aIdentifiers,
-                                  uint32_t* aCount);
-  static bool ScriptableConstruct(NPObject* aObject, const NPVariant* aArgs,
-                                  uint32_t aArgCount, NPVariant* aResult);
-  static nsNPAPIPluginStreamListener* GetStreamListener(NPStream* aStream);
-
-private:
-  struct PendingNewStreamCall
-  {
-    PendingNewStreamCall(NPMIMEType aType, NPStream* aStream, NPBool aSeekable);
-    ~PendingNewStreamCall() {}
-    nsCString   mType;
-    NPStream*   mStream;
-    NPBool      mSeekable;
-  };
-
-private:
-  PluginModuleParent*             mParent;
-  // These values are used to construct the plugin instance
-  nsCString                       mMimeType;
-  mozilla::WeakPtr<nsNPAPIPluginInstance> mInstance;
-  InfallibleTArray<nsCString>     mNames;
-  InfallibleTArray<nsCString>     mValues;
-  // This is safe to store as a pointer because the spec says it will remain
-  // valid until destruction or a subsequent NPP_SetWindow call.
-  NPWindow*                       mWindow;
-  nsTArray<PendingNewStreamCall>  mPendingNewStreamCalls;
-  UniquePtr<PluginDestructionGuard> mPluginDestructionGuard;
-
-  bool      mAcceptCalls;
-  bool      mInstantiated;
-  bool      mAsyncSetWindow;
-  bool      mInitCancelled;
-  bool      mDestroyPending;
-  int32_t   mAsyncCallsInFlight;
-
-  static const NPClass sNPClass;
-};
-
-struct AsyncNPObject : NPObject
-{
-  explicit AsyncNPObject(PluginAsyncSurrogate* aSurrogate);
-  ~AsyncNPObject();
-
-  NPObject* GetRealObject();
-
-  RefPtr<PluginAsyncSurrogate>  mSurrogate;
-  ParentNPObject*                 mRealObject;
-};
-
-class MOZ_STACK_CLASS PushSurrogateAcceptCalls
-{
-public:
-  explicit PushSurrogateAcceptCalls(PluginInstanceParent* aInstance);
-  ~PushSurrogateAcceptCalls();
-
-private:
-  PluginAsyncSurrogate* mSurrogate;
-  bool                  mPrevAcceptCallsState;
-};
-
-} // namespace plugins
-} // namespace mozilla
-
-#endif // dom_plugins_ipc_PluginAsyncSurrogate_h
--- a/dom/plugins/ipc/PluginBridge.h
+++ b/dom/plugins/ipc/PluginBridge.h
@@ -23,17 +23,17 @@ class Endpoint;
 } // namespace ipc
 
 namespace plugins {
 
 class PPluginModuleParent;
 
 bool
 SetupBridge(uint32_t aPluginId, dom::ContentParent* aContentParent,
-            bool aForceBridgeNow, nsresult* aResult, uint32_t* aRunID,
+            nsresult* aResult, uint32_t* aRunID,
             ipc::Endpoint<PPluginModuleParent>* aEndpoint);
 
 nsresult
 FindPluginsForContent(uint32_t aPluginEpoch,
                       nsTArray<PluginTag>* aPlugins,
                       nsTArray<FakePluginTag>* aFakePlugins,
                       uint32_t* aNewPluginEpoch);
 
deleted file mode 100644
--- a/dom/plugins/ipc/PluginDataResolver.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 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/. */
-
-#ifndef dom_plugins_ipc_PluginDataResolver_h
-#define dom_plugins_ipc_PluginDataResolver_h
-
-namespace mozilla {
-namespace plugins {
-
-class PluginAsyncSurrogate;
-class PluginInstanceParent;
-
-class PluginDataResolver
-{
-public:
-    virtual PluginAsyncSurrogate* GetAsyncSurrogate() = 0;
-    virtual PluginInstanceParent* GetInstance() = 0;
-};
-
-} // namespace plugins
-} // namespace mozilla
-
-#endif // dom_plugins_ipc_PluginDataResolver_h
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -2503,62 +2503,16 @@ PluginInstanceChild::AnswerNPP_NewStream
                                          NPError* rv,
                                          uint16_t* stype)
 {
     *rv = DoNPP_NewStream(static_cast<BrowserStreamChild*>(actor), mimeType,
                           seekable, stype);
     return IPC_OK();
 }
 
-class NewStreamAsyncCall : public ChildAsyncCall
-{
-public:
-    NewStreamAsyncCall(PluginInstanceChild* aInstance,
-                       BrowserStreamChild* aBrowserStreamChild,
-                       const nsCString& aMimeType,
-                       const bool aSeekable)
-        : ChildAsyncCall(aInstance, nullptr, nullptr)
-        , mBrowserStreamChild(aBrowserStreamChild)
-        , mMimeType(aMimeType)
-        , mSeekable(aSeekable)
-    {
-    }
-
-    NS_IMETHOD Run() override
-    {
-        RemoveFromAsyncList();
-
-        uint16_t stype = NP_NORMAL;
-        NPError rv = mInstance->DoNPP_NewStream(mBrowserStreamChild, mMimeType,
-                                                mSeekable, &stype);
-        DebugOnly<bool> sendOk =
-            mBrowserStreamChild->SendAsyncNPP_NewStreamResult(rv, stype);
-        MOZ_ASSERT(sendOk);
-        return NS_OK;
-    }
-
-private:
-    BrowserStreamChild* mBrowserStreamChild;
-    const nsCString     mMimeType;
-    const bool          mSeekable;
-};
-
-mozilla::ipc::IPCResult
-PluginInstanceChild::RecvAsyncNPP_NewStream(PBrowserStreamChild* actor,
-                                            const nsCString& mimeType,
-                                            const bool& seekable)
-{
-    // Reusing ChildAsyncCall so that the task is cancelled properly on Destroy
-    BrowserStreamChild* child = static_cast<BrowserStreamChild*>(actor);
-    RefPtr<NewStreamAsyncCall> task =
-        new NewStreamAsyncCall(this, child, mimeType, seekable);
-    PostChildAsyncCall(task.forget());
-    return IPC_OK();
-}
-
 PBrowserStreamChild*
 PluginInstanceChild::AllocPBrowserStreamChild(const nsCString& url,
                                               const uint32_t& length,
                                               const uint32_t& lastmodified,
                                               PStreamNotifyChild* notifyData,
                                               const nsCString& headers)
 {
     AssertPluginThread();
--- a/dom/plugins/ipc/PluginInstanceChild.h
+++ b/dom/plugins/ipc/PluginInstanceChild.h
@@ -160,22 +160,16 @@ protected:
     virtual mozilla::ipc::IPCResult
     AnswerNPP_NewStream(
             PBrowserStreamChild* actor,
             const nsCString& mimeType,
             const bool& seekable,
             NPError* rv,
             uint16_t* stype) override;
 
-    virtual mozilla::ipc::IPCResult
-    RecvAsyncNPP_NewStream(
-        PBrowserStreamChild* actor,
-        const nsCString& mimeType,
-        const bool& seekable) override;
-
     virtual PBrowserStreamChild*
     AllocPBrowserStreamChild(const nsCString& url,
                              const uint32_t& length,
                              const uint32_t& lastmodified,
                              PStreamNotifyChild* notifyData,
                              const nsCString& headers) override;
 
     virtual bool
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -7,17 +7,16 @@
 #include "mozilla/DebugOnly.h"
 #include <stdint.h> // for intptr_t
 
 #include "mozilla/BasicEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "PluginInstanceParent.h"
 #include "BrowserStreamParent.h"
-#include "PluginAsyncSurrogate.h"
 #include "PluginBackgroundDestroyer.h"
 #include "PluginModuleParent.h"
 #include "PluginStreamParent.h"
 #include "StreamNotifyParent.h"
 #include "npfunctions.h"
 #include "nsAutoPtr.h"
 #include "gfxASurface.h"
 #include "gfxContext.h"
@@ -110,18 +109,16 @@ PluginInstanceParent::LookupPluginInstan
 }
 #endif
 
 PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
                                            NPP npp,
                                            const nsCString& aMimeType,
                                            const NPNetscapeFuncs* npniface)
     : mParent(parent)
-    , mSurrogate(PluginAsyncSurrogate::Cast(npp))
-    , mUseSurrogate(true)
     , mNPP(npp)
     , mNPNIface(npniface)
     , mWindowType(NPWindowTypeWindow)
     , mDrawingModel(kDefaultDrawingModel)
     , mLastRecordedDrawingModel(-1)
     , mFrameID(0)
 #if defined(OS_WIN)
     , mPluginHWND(nullptr)
@@ -1218,22 +1215,16 @@ PluginInstanceParent::GetScrollCaptureCo
 
   RefPtr<ImageContainer> container = GetImageContainer();
   container.forget(aContainer);
 
   return NS_OK;
 }
 #endif // XP_WIN
 
-PluginAsyncSurrogate*
-PluginInstanceParent::GetAsyncSurrogate()
-{
-    return mSurrogate;
-}
-
 bool
 PluginInstanceParent::CreateBackground(const nsIntSize& aSize)
 {
     MOZ_ASSERT(!mBackground, "Already have a background");
 
     // XXX refactor me
 
 #if defined(MOZ_X11)
@@ -1770,32 +1761,22 @@ PluginInstanceParent::NPP_NewStream(NPMI
                                        NullableString(stream->headers))) {
         return NPERR_GENERIC_ERROR;
     }
 
     Telemetry::AutoTimer<Telemetry::BLOCKED_ON_PLUGIN_STREAM_INIT_MS>
         timer(Module()->GetHistogramKey());
 
     NPError err = NPERR_NO_ERROR;
-    if (mParent->IsStartingAsync()) {
-        MOZ_ASSERT(mSurrogate);
-        mSurrogate->AsyncCallDeparting();
-        if (SendAsyncNPP_NewStream(bs, NullableString(type), seekable)) {
-            *stype = nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN;
-        } else {
-            err = NPERR_GENERIC_ERROR;
-        }
-    } else {
-        bs->SetAlive();
-        if (!CallNPP_NewStream(bs, NullableString(type), seekable, &err, stype)) {
-            err = NPERR_GENERIC_ERROR;
-        }
-        if (NPERR_NO_ERROR != err) {
-            Unused << PBrowserStreamParent::Send__delete__(bs);
-        }
+    bs->SetAlive();
+    if (!CallNPP_NewStream(bs, NullableString(type), seekable, &err, stype)) {
+        err = NPERR_GENERIC_ERROR;
+    }
+    if (NPERR_NO_ERROR != err) {
+        Unused << PBrowserStreamParent::Send__delete__(bs);
     }
 
     return err;
 }
 
 NPError
 PluginInstanceParent::NPP_DestroyStream(NPStream* stream, NPReason reason)
 {
@@ -2047,52 +2028,16 @@ PluginInstanceParent::GetOwner()
     nsNPAPIPluginInstance* inst = static_cast<nsNPAPIPluginInstance*>(mNPP->ndata);
     if (!inst) {
         return nullptr;
     }
     return inst->GetOwner();
 }
 
 mozilla::ipc::IPCResult
-PluginInstanceParent::RecvAsyncNPP_NewResult(const NPError& aResult)
-{
-    // NB: mUseSurrogate must be cleared before doing anything else, especially
-    //     calling NPP_SetWindow!
-    mUseSurrogate = false;
-
-    mSurrogate->AsyncCallArriving();
-    if (aResult == NPERR_NO_ERROR) {
-        mSurrogate->SetAcceptingCalls(true);
-    }
-
-    // It is possible for a plugin instance to outlive its owner (eg. When a
-    // PluginDestructionGuard was on the stack at the time the owner was being
-    // destroyed). We need to handle that case.
-    nsPluginInstanceOwner* owner = GetOwner();
-    if (!owner) {
-        // We can't do anything at this point, just return. Any pending browser
-        // streams will be cleaned up when the plugin instance is destroyed.
-        return IPC_OK();
-    }
-
-    if (aResult != NPERR_NO_ERROR) {
-        mSurrogate->NotifyAsyncInitFailed();
-        return IPC_OK();
-    }
-
-    // Now we need to do a bunch of exciting post-NPP_New housekeeping.
-    owner->NotifyHostCreateWidget();
-
-    MOZ_ASSERT(mSurrogate);
-    mSurrogate->OnInstanceCreated(this);
-
-    return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
 PluginInstanceParent::RecvSetNetscapeWindowAsParent(const NativeWindowHandle& childWindow)
 {
 #if defined(XP_WIN)
     nsPluginInstanceOwner* owner = GetOwner();
     if (!owner || NS_FAILED(owner->SetNetscapeWindowAsParent(childWindow))) {
         NS_WARNING("Failed to set Netscape window as parent.");
     }
 
@@ -2330,38 +2275,31 @@ PluginInstanceParent::AnswerPluginFocusC
     return IPC_OK();
 #else
     NS_NOTREACHED("PluginInstanceParent::AnswerPluginFocusChange not implemented!");
     return IPC_FAIL_NO_REASON(this);
 #endif
 }
 
 PluginInstanceParent*
-PluginInstanceParent::Cast(NPP aInstance, PluginAsyncSurrogate** aSurrogate)
+PluginInstanceParent::Cast(NPP aInstance)
 {
-    PluginDataResolver* resolver =
-        static_cast<PluginDataResolver*>(aInstance->pdata);
+    auto ip = static_cast<PluginInstanceParent*>(aInstance->pdata);
 
     // If the plugin crashed and the PluginInstanceParent was deleted,
     // aInstance->pdata will be nullptr.
-    if (!resolver) {
+    if (!ip) {
         return nullptr;
     }
 
-    PluginInstanceParent* instancePtr = resolver->GetInstance();
-
-    if (instancePtr && aInstance != instancePtr->mNPP) {
+    if (aInstance != ip->mNPP) {
         MOZ_CRASH("Corrupted plugin data.");
     }
 
-    if (aSurrogate) {
-        *aSurrogate = resolver->GetAsyncSurrogate();
-    }
-
-    return instancePtr;
+    return ip;
 }
 
 mozilla::ipc::IPCResult
 PluginInstanceParent::RecvGetCompositionString(const uint32_t& aIndex,
                                                nsTArray<uint8_t>* aDist,
                                                int32_t* aLength)
 {
 #if defined(OS_WIN)
--- a/dom/plugins/ipc/PluginInstanceParent.h
+++ b/dom/plugins/ipc/PluginInstanceParent.h
@@ -16,17 +16,16 @@
 #elif defined(MOZ_WIDGET_COCOA)
 #include "mozilla/gfx/QuartzSupport.h"
 #endif
 
 #include "npfunctions.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsRect.h"
-#include "PluginDataResolver.h"
 
 #include "mozilla/Unused.h"
 #include "mozilla/EventForwards.h"
 
 class gfxASurface;
 class gfxContext;
 class nsPluginInstanceOwner;
 
@@ -38,17 +37,16 @@ class TextureClientRecycleAllocator;
 } // namespace layers
 namespace plugins {
 
 class PBrowserStreamParent;
 class PluginModuleParent;
 class D3D11SurfaceHolder;
 
 class PluginInstanceParent : public PPluginInstanceParent
-                           , public PluginDataResolver
 {
     friend class PluginModuleParent;
     friend class BrowserStreamParent;
     friend class PluginStreamParent;
     friend class StreamNotifyParent;
 
 #if defined(XP_WIN)
 public:
@@ -237,19 +235,16 @@ public:
                            double *destX,
                            double *destY,
                            bool *result) override;
 
     virtual mozilla::ipc::IPCResult
     RecvRedrawPlugin() override;
 
     virtual mozilla::ipc::IPCResult
-    RecvAsyncNPP_NewResult(const NPError& aResult) override;
-
-    virtual mozilla::ipc::IPCResult
     RecvSetNetscapeWindowAsParent(const NativeWindowHandle& childWindow) override;
 
     NPError NPP_SetWindow(const NPWindow* aWindow);
 
     NPError NPP_GetValue(NPPVariable variable, void* retval);
     NPError NPP_SetValue(NPNVariable variable, void* value);
 
     void NPP_URLRedirectNotify(const char* url, int32_t status,
@@ -286,22 +281,16 @@ public:
     GetActorForNPObject(NPObject* aObject);
 
     NPP
     GetNPP()
     {
       return mNPP;
     }
 
-    bool
-    UseSurrogate() const
-    {
-        return mUseSurrogate;
-    }
-
     void
     GetSrcAttribute(nsACString& aOutput) const
     {
         aOutput = mSrcAttribute;
     }
 
     virtual mozilla::ipc::IPCResult
     AnswerPluginFocusChange(const bool& gotFocus) override;
@@ -322,22 +311,17 @@ public:
 #if defined(XP_WIN)
     nsresult SetScrollCaptureId(uint64_t aScrollCaptureId);
     nsresult GetScrollCaptureContainer(mozilla::layers::ImageContainer** aContainer);
 #endif
     void DidComposite();
 
     bool IsUsingDirectDrawing();
 
-    virtual PluginAsyncSurrogate* GetAsyncSurrogate() override;
-
-    virtual PluginInstanceParent* GetInstance() override { return this; }
-
-    static PluginInstanceParent* Cast(NPP instance,
-                                      PluginAsyncSurrogate** aSurrogate = nullptr);
+    static PluginInstanceParent* Cast(NPP instance);
 
     // for IME hook
     virtual mozilla::ipc::IPCResult
     RecvGetCompositionString(const uint32_t& aIndex,
                              nsTArray<uint8_t>* aBuffer,
                              int32_t* aLength) override;
     virtual mozilla::ipc::IPCResult
     RecvSetCandidateWindow(
@@ -377,18 +361,16 @@ private:
 
     void SetCurrentImage(layers::Image* aImage);
 
     // Update Telemetry with the current drawing model.
     void RecordDrawingModel();
 
 private:
     PluginModuleParent* mParent;
-    RefPtr<PluginAsyncSurrogate> mSurrogate;
-    bool mUseSurrogate;
     NPP mNPP;
     const NPNetscapeFuncs* mNPNIface;
     nsCString mSrcAttribute;
     NPWindowType mWindowType;
     int16_t mDrawingModel;
 
     // Since plugins may request different drawing models to find a compatible
     // one, we only record the drawing model after a SetWindow call and if the
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -1837,26 +1837,16 @@ PluginModuleChild::AnswerNP_GetEntryPoin
 
 mozilla::ipc::IPCResult
 PluginModuleChild::AnswerNP_Initialize(const PluginSettings& aSettings, NPError* rv)
 {
     *rv = DoNP_Initialize(aSettings);
     return IPC_OK();
 }
 
-mozilla::ipc::IPCResult
-PluginModuleChild::RecvAsyncNP_Initialize(const PluginSettings& aSettings)
-{
-    NPError error = DoNP_Initialize(aSettings);
-    if (!SendNP_InitializeResult(error)) {
-        return IPC_FAIL_NO_REASON(this);
-    }
-    return IPC_OK();
-}
-
 NPError
 PluginModuleChild::DoNP_Initialize(const PluginSettings& aSettings)
 {
     PLUGIN_LOG_DEBUG_METHOD;
     AssertPluginThread();
     MOZ_ASSERT(mIsChrome);
 
     mCachedSettings = aSettings;
@@ -2381,61 +2371,16 @@ PluginModuleChild::AnswerSyncNPP_New(PPl
     PLUGIN_LOG_DEBUG_METHOD;
     PluginInstanceChild* childInstance =
         reinterpret_cast<PluginInstanceChild*>(aActor);
     AssertPluginThread();
     *rv = childInstance->DoNPP_New();
     return IPC_OK();
 }
 
-class AsyncNewResultSender : public ChildAsyncCall
-{
-public:
-    AsyncNewResultSender(PluginInstanceChild* aInstance, NPError aResult)
-        : ChildAsyncCall(aInstance, nullptr, nullptr)
-        , mResult(aResult)
-    {
-    }
-
-    NS_IMETHOD Run() override
-    {
-        RemoveFromAsyncList();
-        DebugOnly<bool> sendOk = mInstance->SendAsyncNPP_NewResult(mResult);
-        MOZ_ASSERT(sendOk);
-        return NS_OK;
-    }
-
-private:
-    NPError  mResult;
-};
-
-static void
-RunAsyncNPP_New(void* aChildInstance)
-{
-    MOZ_ASSERT(aChildInstance);
-    PluginInstanceChild* childInstance =
-        static_cast<PluginInstanceChild*>(aChildInstance);
-    NPError rv = childInstance->DoNPP_New();
-    RefPtr<AsyncNewResultSender> task =
-        new AsyncNewResultSender(childInstance, rv);
-    childInstance->PostChildAsyncCall(task.forget());
-}
-
-mozilla::ipc::IPCResult
-PluginModuleChild::RecvAsyncNPP_New(PPluginInstanceChild* aActor)
-{
-    PLUGIN_LOG_DEBUG_METHOD;
-    PluginInstanceChild* childInstance =
-        reinterpret_cast<PluginInstanceChild*>(aActor);
-    AssertPluginThread();
-    // We don't want to run NPP_New async from within nested calls
-    childInstance->AsyncCall(&RunAsyncNPP_New, childInstance);
-    return IPC_OK();
-}
-
 bool
 PluginModuleChild::DeallocPPluginInstanceChild(PPluginInstanceChild* aActor)
 {
     PLUGIN_LOG_DEBUG_METHOD;
     AssertPluginThread();
 
     delete aActor;
 
--- a/dom/plugins/ipc/PluginModuleChild.h
+++ b/dom/plugins/ipc/PluginModuleChild.h
@@ -67,20 +67,18 @@ protected:
 
     virtual mozilla::ipc::IPCResult RecvSettingChanged(const PluginSettings& aSettings) override;
 
     // Implement the PPluginModuleChild interface
     virtual mozilla::ipc::IPCResult RecvInitProfiler(Endpoint<mozilla::PProfilerChild>&& aEndpoint) override;
     virtual mozilla::ipc::IPCResult RecvDisableFlashProtectedMode() override;
     virtual mozilla::ipc::IPCResult AnswerNP_GetEntryPoints(NPError* rv) override;
     virtual mozilla::ipc::IPCResult AnswerNP_Initialize(const PluginSettings& aSettings, NPError* rv) override;
-    virtual mozilla::ipc::IPCResult RecvAsyncNP_Initialize(const PluginSettings& aSettings) override;
     virtual mozilla::ipc::IPCResult AnswerSyncNPP_New(PPluginInstanceChild* aActor, NPError* rv)
                                    override;
-    virtual mozilla::ipc::IPCResult RecvAsyncNPP_New(PPluginInstanceChild* aActor) override;
 
     virtual mozilla::ipc::IPCResult
     RecvInitPluginModuleChild(Endpoint<PPluginModuleChild>&& endpoint) override;
 
     virtual PPluginInstanceChild*
     AllocPPluginInstanceChild(const nsCString& aMimeType,
                               const InfallibleTArray<nsCString>& aNames,
                               const InfallibleTArray<nsCString>& aValues)
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -9,17 +9,16 @@
 #include "base/process_util.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/ipc/MessageChannel.h"
 #include "mozilla/ipc/ProtocolUtils.h"
 #include "mozilla/plugins/BrowserStreamParent.h"
-#include "mozilla/plugins/PluginAsyncSurrogate.h"
 #include "mozilla/plugins/PluginBridge.h"
 #include "mozilla/plugins/PluginInstanceParent.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ProcessHangMonitor.h"
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Unused.h"
 #include "nsAutoPtr.h"
@@ -72,63 +71,52 @@ using namespace mozilla::plugins::parent
 
 using namespace CrashReporter;
 #endif
 
 static const char kContentTimeoutPref[] = "dom.ipc.plugins.contentTimeoutSecs";
 static const char kChildTimeoutPref[] = "dom.ipc.plugins.timeoutSecs";
 static const char kParentTimeoutPref[] = "dom.ipc.plugins.parentTimeoutSecs";
 static const char kLaunchTimeoutPref[] = "dom.ipc.plugins.processLaunchTimeoutSecs";
-static const char kAsyncInitPref[] = "dom.ipc.plugins.asyncInit.enabled";
 #ifdef XP_WIN
 static const char kHangUITimeoutPref[] = "dom.ipc.plugins.hangUITimeoutSecs";
 static const char kHangUIMinDisplayPref[] = "dom.ipc.plugins.hangUIMinDisplaySecs";
 #define CHILD_TIMEOUT_PREF kHangUITimeoutPref
 #else
 #define CHILD_TIMEOUT_PREF kChildTimeoutPref
 #endif
 
 bool
 mozilla::plugins::SetupBridge(uint32_t aPluginId,
                               dom::ContentParent* aContentParent,
-                              bool aForceBridgeNow,
                               nsresult* rv,
                               uint32_t* runID,
                               ipc::Endpoint<PPluginModuleParent>* aEndpoint)
 {
     AUTO_PROFILER_LABEL("plugins::SetupBridge", OTHER);
     if (NS_WARN_IF(!rv) || NS_WARN_IF(!runID)) {
         return false;
     }
 
-    PluginModuleChromeParent::ClearInstantiationFlag();
     RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
     RefPtr<nsNPAPIPlugin> plugin;
     *rv = host->GetPluginForContentProcess(aPluginId, getter_AddRefs(plugin));
     if (NS_FAILED(*rv)) {
         return true;
     }
     PluginModuleChromeParent* chromeParent = static_cast<PluginModuleChromeParent*>(plugin->GetLibrary());
     /*
      *  We can't accumulate BLOCKED_ON_PLUGIN_MODULE_INIT_MS until here because
      *  its histogram key is not available until *after* NP_Initialize.
      */
     chromeParent->AccumulateModuleInitBlockedTime();
     *rv = chromeParent->GetRunID(runID);
     if (NS_FAILED(*rv)) {
         return true;
     }
-    if (chromeParent->IsStartingAsync()) {
-        chromeParent->SetContentParent(aContentParent);
-    }
-    if (!aForceBridgeNow && chromeParent->IsStartingAsync() &&
-        PluginModuleChromeParent::DidInstantiate()) {
-        // We'll handle the bridging asynchronously
-        return true;
-    }
 
     ipc::Endpoint<PPluginModuleParent> parent;
     ipc::Endpoint<PPluginModuleChild> child;
 
     *rv = PPluginModule::CreateEndpoints(aContentParent->OtherPid(),
                                          chromeParent->OtherPid(),
                                          &parent, &child);
     if (NS_FAILED(*rv)) {
@@ -204,26 +192,24 @@ private:
     MessageLoop*              mMainThreadMsgLoop;
 };
 
 #endif // MOZ_CRASHREPORTER_INJECTOR
 
 namespace {
 
 /**
- * Objects of this class remain linked until either an error occurs in the
- * plugin initialization sequence, or until
- * PluginModuleContentParent::OnLoadPluginResult has completed executing.
+ * Objects of this class remain linked until an error occurs in the
+ * plugin initialization sequence.
  */
 class PluginModuleMapping : public PRCList
 {
 public:
-    explicit PluginModuleMapping(uint32_t aPluginId, bool aAllowAsyncInit)
+    explicit PluginModuleMapping(uint32_t aPluginId)
         : mPluginId(aPluginId)
-        , mAllowAsyncInit(aAllowAsyncInit)
         , mProcessIdValid(false)
         , mModule(nullptr)
         , mChannelOpened(false)
     {
         MOZ_COUNT_CTOR(PluginModuleMapping);
         PR_INIT_CLIST(this);
         PR_APPEND_LINK(this, &sModuleListHead);
     }
@@ -245,17 +231,17 @@ public:
     {
         mChannelOpened = true;
     }
 
     PluginModuleContentParent*
     GetModule()
     {
         if (!mModule) {
-            mModule = new PluginModuleContentParent(mAllowAsyncInit);
+            mModule = new PluginModuleContentParent();
         }
         return mModule;
     }
 
     static PluginModuleMapping*
     AssociateWithProcessId(uint32_t aPluginId, base::ProcessId aProcessId)
     {
         PluginModuleMapping* mapping =
@@ -332,17 +318,16 @@ private:
     AssociateWithProcessId(base::ProcessId aProcessId)
     {
         MOZ_ASSERT(!mProcessIdValid);
         mProcessId = aProcessId;
         mProcessIdValid = true;
     }
 
     uint32_t mPluginId;
-    bool mAllowAsyncInit;
     bool mProcessIdValid;
     base::ProcessId mProcessId;
     PluginModuleContentParent* mModule;
     bool mChannelOpened;
 
     friend class NotifyLoadingModule;
 
     static PRCList sModuleListHead;
@@ -413,18 +398,17 @@ mozilla::plugins::TerminatePlugin(uint32
   }
 }
 
 /* static */ PluginLibrary*
 PluginModuleContentParent::LoadModule(uint32_t aPluginId,
                                       nsPluginTag* aPluginTag)
 {
     PluginModuleMapping::NotifyLoadingModule loadingModule;
-    nsAutoPtr<PluginModuleMapping> mapping(
-            new PluginModuleMapping(aPluginId, aPluginTag->mSupportsAsyncInit));
+    nsAutoPtr<PluginModuleMapping> mapping(new PluginModuleMapping(aPluginId));
 
     MOZ_ASSERT(XRE_IsContentProcess());
 
     /*
      * We send a LoadPlugin message to the chrome process using an intr
      * message. Before it sends its response, it sends a message to create
      * PluginModuleParent instance. That message is handled by
      * PluginModuleContentParent::Initialize, which saves the instance in
@@ -455,25 +439,16 @@ PluginModuleContentParent::LoadModule(ui
 
     parent->mPluginId = aPluginId;
     parent->mRunID = runID;
 
     return parent;
 }
 
 /* static */ void
-PluginModuleContentParent::AssociatePluginId(uint32_t aPluginId,
-                                             base::ProcessId aOtherPid)
-{
-    DebugOnly<PluginModuleMapping*> mapping =
-        PluginModuleMapping::AssociateWithProcessId(aPluginId, aOtherPid);
-    MOZ_ASSERT(mapping);
-}
-
-/* static */ void
 PluginModuleContentParent::Initialize(Endpoint<PPluginModuleParent>&& aEndpoint)
 {
     nsAutoPtr<PluginModuleMapping> moduleMapping(
         PluginModuleMapping::Resolve(aEndpoint.OtherPid()));
     MOZ_ASSERT(moduleMapping);
     PluginModuleContentParent* parent = moduleMapping->GetModule();
     MOZ_ASSERT(parent);
 
@@ -490,94 +465,60 @@ PluginModuleContentParent::Initialize(En
     TimeoutChanged(kContentTimeoutPref, parent);
 
     // moduleMapping is linked into PluginModuleMapping::sModuleListHead and is
     // needed later, so since this function is returning successfully we
     // forget it here.
     moduleMapping.forget();
 }
 
-/* static */ void
-PluginModuleContentParent::OnLoadPluginResult(const uint32_t& aPluginId,
-                                              const bool& aResult,
-                                              Endpoint<PPluginModuleParent>&& aEndpoint)
-{
-    Initialize(Move(aEndpoint));
-    nsAutoPtr<PluginModuleMapping> moduleMapping(
-        PluginModuleMapping::FindModuleByPluginId(aPluginId));
-    MOZ_ASSERT(moduleMapping);
-    PluginModuleContentParent* parent = moduleMapping->GetModule();
-    MOZ_ASSERT(parent);
-    parent->RecvNP_InitializeResult(aResult ? NPERR_NO_ERROR
-                                            : NPERR_GENERIC_ERROR);
-}
-
-void
-PluginModuleChromeParent::SetContentParent(dom::ContentParent* aContentParent)
-{
-    // mContentParent is to be used ONLY during async plugin init!
-    MOZ_ASSERT(aContentParent && mIsStartingAsync);
-    mContentParent = aContentParent;
-}
-
-bool
-PluginModuleChromeParent::SendAssociatePluginId()
-{
-    MOZ_ASSERT(mContentParent);
-    return mContentParent->SendAssociatePluginId(mPluginId, OtherPid());
-}
-
 // static
 PluginLibrary*
 PluginModuleChromeParent::LoadModule(const char* aFilePath, uint32_t aPluginId,
                                      nsPluginTag* aPluginTag)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
 
     nsAutoPtr<PluginModuleChromeParent> parent(
             new PluginModuleChromeParent(aFilePath, aPluginId,
-                                         aPluginTag->mSandboxLevel,
-                                         aPluginTag->mSupportsAsyncInit));
+                                         aPluginTag->mSandboxLevel));
     UniquePtr<LaunchCompleteTask> onLaunchedRunnable(new LaunchedTask(parent));
-    parent->mSubprocess->SetCallRunnableImmediately(!parent->mIsStartingAsync);
     TimeStamp launchStart = TimeStamp::Now();
     bool launched = parent->mSubprocess->Launch(Move(onLaunchedRunnable),
                                                 aPluginTag->mSandboxLevel);
     if (!launched) {
         // We never reached open
         parent->mShutdown = true;
         return nullptr;
     }
     parent->mIsFlashPlugin = aPluginTag->mIsFlashPlugin;
     uint32_t blocklistState;
     nsresult rv = aPluginTag->GetBlocklistState(&blocklistState);
     parent->mIsBlocklisted = NS_FAILED(rv) || blocklistState != 0;
-    if (!parent->mIsStartingAsync) {
-        int32_t launchTimeoutSecs = Preferences::GetInt(kLaunchTimeoutPref, 0);
-        if (!parent->mSubprocess->WaitUntilConnected(launchTimeoutSecs * 1000)) {
-            parent->mShutdown = true;
-            return nullptr;
-        }
+    int32_t launchTimeoutSecs = Preferences::GetInt(kLaunchTimeoutPref, 0);
+    if (!parent->mSubprocess->WaitUntilConnected(launchTimeoutSecs * 1000)) {
+        parent->mShutdown = true;
+        return nullptr;
     }
     TimeStamp launchEnd = TimeStamp::Now();
     parent->mTimeBlocked = (launchEnd - launchStart);
     return parent.forget();
 }
 
 void
 PluginModuleChromeParent::OnProcessLaunched(const bool aSucceeded)
 {
     if (!aSucceeded) {
         mShutdown = true;
         OnInitFailure();
         return;
     }
     // We may have already been initialized by another call that was waiting
     // for process connect. If so, this function doesn't need to run.
-    if (mAsyncInitRv != NS_ERROR_NOT_INITIALIZED || mShutdown) {
+    if (mShutdown) {
         return;
     }
 
     Open(mSubprocess->GetChannel(),
          base::GetProcId(mSubprocess->GetChildProcessHandle()));
 
     // Request Windows message deferral behavior on our channel. This
     // applies to the top level and all sub plugin protocols since they
@@ -609,60 +550,22 @@ PluginModuleChromeParent::OnProcessLaunc
     // Protected mode only applies to Windows and only to x86.
     if (!mIsBlocklisted && mIsFlashPlugin &&
         (Preferences::GetBool("dom.ipc.plugins.flash.disable-protected-mode", false) ||
          mSandboxLevel >= 2)) {
         SendDisableFlashProtectedMode();
     }
 #endif
 
-    if (mInitOnAsyncConnect) {
-        mInitOnAsyncConnect = false;
-#if defined(XP_WIN)
-        mAsyncInitRv = NP_GetEntryPoints(mNPPIface,
-                                         &mAsyncInitError);
-        if (NS_SUCCEEDED(mAsyncInitRv))
-#endif
-        {
-#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK)
-            mAsyncInitRv = NP_Initialize(mNPNIface,
-                                         mNPPIface,
-                                         &mAsyncInitError);
-#else
-            mAsyncInitRv = NP_Initialize(mNPNIface,
-                                         &mAsyncInitError);
-#endif
-        }
-
-#if defined(XP_MACOSX)
-        if (NS_SUCCEEDED(mAsyncInitRv)) {
-            mAsyncInitRv = NP_GetEntryPoints(mNPPIface,
-                                             &mAsyncInitError);
-        }
-#endif
-    }
-
 #ifdef MOZ_GECKO_PROFILER
     Unused << SendInitProfiler(ProfilerParent::CreateForProcess(OtherPid()));
 #endif
 }
 
 bool
-PluginModuleChromeParent::WaitForIPCConnection()
-{
-    PluginProcessParent* process = Process();
-    MOZ_ASSERT(process);
-    process->SetCallRunnableImmediately(true);
-    if (!process->WaitUntilConnected()) {
-        return false;
-    }
-    return true;
-}
-
-bool
 PluginModuleChromeParent::InitCrashReporter()
 {
 #ifdef MOZ_CRASHREPORTER
     ipc::Shmem shmem;
     if (!ipc::CrashReporterClient::AllocShmem(this, &shmem)) {
         return false;
     }
 
@@ -672,109 +575,86 @@ PluginModuleChromeParent::InitCrashRepor
     }
 
     {
       mozilla::MutexAutoLock lock(mCrashReporterMutex);
       mCrashReporter = MakeUnique<ipc::CrashReporterHost>(
         GeckoProcessType_Plugin,
         shmem,
         threadId);
-
-      mCrashReporter->AddNote(NS_LITERAL_CSTRING("AsyncPluginInit"),
-                              mIsStartingAsync ?
-                                  NS_LITERAL_CSTRING("1") :
-                                  NS_LITERAL_CSTRING("0"));
     }
 #endif
 
     return true;
 }
 
-PluginModuleParent::PluginModuleParent(bool aIsChrome, bool aAllowAsyncInit)
+PluginModuleParent::PluginModuleParent(bool aIsChrome)
     : mQuirks(QUIRKS_NOT_INITIALIZED)
     , mIsChrome(aIsChrome)
     , mShutdown(false)
     , mHadLocalInstance(false)
     , mClearSiteDataSupported(false)
     , mGetSitesWithDataSupported(false)
     , mNPNIface(nullptr)
     , mNPPIface(nullptr)
     , mPlugin(nullptr)
     , mTaskFactory(this)
     , mSandboxLevel(0)
     , mIsFlashPlugin(false)
-    , mIsStartingAsync(false)
-    , mNPInitialized(false)
-    , mIsNPShutdownPending(false)
-    , mAsyncNewRv(NS_ERROR_NOT_INITIALIZED)
 #ifdef MOZ_CRASHREPORTER
     , mCrashReporterMutex("PluginModuleChromeParent::mCrashReporterMutex")
 #endif
 {
-#if defined(MOZ_CRASHREPORTER)
-    CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AsyncPluginInit"),
-                                       mIsStartingAsync ?
-                                           NS_LITERAL_CSTRING("1") :
-                                           NS_LITERAL_CSTRING("0"));
-#endif
 }
 
 PluginModuleParent::~PluginModuleParent()
 {
     if (!OkToCleanup()) {
         MOZ_CRASH("unsafe destruction");
     }
 
     if (!mShutdown) {
         NS_WARNING("Plugin host deleted the module without shutting down.");
         NPError err;
         NP_Shutdown(&err);
     }
 }
 
-PluginModuleContentParent::PluginModuleContentParent(bool aAllowAsyncInit)
-    : PluginModuleParent(false, aAllowAsyncInit)
+PluginModuleContentParent::PluginModuleContentParent()
+    : PluginModuleParent(false)
 {
     Preferences::RegisterCallback(TimeoutChanged, kContentTimeoutPref, this);
 }
 
 PluginModuleContentParent::~PluginModuleContentParent()
 {
     Preferences::UnregisterCallback(TimeoutChanged, kContentTimeoutPref, this);
 }
 
-bool PluginModuleChromeParent::sInstantiated = false;
-
 PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath,
                                                    uint32_t aPluginId,
-                                                   int32_t aSandboxLevel,
-                                                   bool aAllowAsyncInit)
-    : PluginModuleParent(true, aAllowAsyncInit)
+                                                   int32_t aSandboxLevel)
+    : PluginModuleParent(true)
     , mSubprocess(new PluginProcessParent(aFilePath))
     , mPluginId(aPluginId)
     , mChromeTaskFactory(this)
     , mHangAnnotationFlags(0)
 #ifdef XP_WIN
     , mPluginCpuUsageOnHang()
     , mHangUIParent(nullptr)
     , mHangUIEnabled(true)
     , mIsTimerReset(true)
 #endif
 #ifdef MOZ_CRASHREPORTER_INJECTOR
     , mFlashProcess1(0)
     , mFlashProcess2(0)
     , mFinishInitTask(nullptr)
 #endif
-    , mInitOnAsyncConnect(false)
-    , mAsyncInitRv(NS_ERROR_NOT_INITIALIZED)
-    , mAsyncInitError(NPERR_NO_ERROR)
-    , mContentParent(nullptr)
 {
     NS_ASSERTION(mSubprocess, "Out of memory!");
-    sInstantiated = true;
     mSandboxLevel = aSandboxLevel;
     mRunID = GeckoChildProcessHost::GetUniqueID();
 
     mozilla::HangMonitor::RegisterAnnotator(*this);
 }
 
 PluginModuleChromeParent::~PluginModuleChromeParent()
 {
@@ -1852,94 +1732,72 @@ PluginModuleParent::SetPluginFuncs(NPPlu
     Unused << CallOptionalFunctionsSupported(&urlRedirectSupported,
                                              &mClearSiteDataSupported,
                                              &mGetSitesWithDataSupported);
     if (urlRedirectSupported) {
       aFuncs->urlredirectnotify = NPP_URLRedirectNotify;
     }
 }
 
-#define RESOLVE_AND_CALL(instance, func)                                       \
-NP_BEGIN_MACRO                                                                 \
-    PluginAsyncSurrogate* surrogate = nullptr;                                 \
-    PluginInstanceParent* i = PluginInstanceParent::Cast(instance, &surrogate);\
-    if (surrogate && (!i || i->UseSurrogate())) {                              \
-        return surrogate->func;                                                \
-    }                                                                          \
-    if (!i) {                                                                  \
-        return NPERR_GENERIC_ERROR;                                            \
-    }                                                                          \
-    return i->func;                                                            \
-NP_END_MACRO
-
 NPError
 PluginModuleParent::NPP_Destroy(NPP instance,
                                 NPSavedData** saved)
 {
     // FIXME/cjones:
     //  (1) send a "destroy" message to the child
     //  (2) the child shuts down its instance
     //  (3) remove both parent and child IDs from map
     //  (4) free parent
 
     PLUGIN_LOG_DEBUG_FUNCTION;
-    PluginAsyncSurrogate* surrogate = nullptr;
-    PluginInstanceParent* parentInstance =
-        PluginInstanceParent::Cast(instance, &surrogate);
-    if (surrogate && (!parentInstance || parentInstance->UseSurrogate())) {
-        return surrogate->NPP_Destroy(saved);
-    }
-
-    if (!parentInstance)
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    if (!pip)
         return NPERR_NO_ERROR;
 
-    NPError retval = parentInstance->Destroy();
+    NPError retval = pip->Destroy();
     instance->pdata = nullptr;
 
-    Unused << PluginInstanceParent::Call__delete__(parentInstance);
+    Unused << PluginInstanceParent::Call__delete__(pip);
     return retval;
 }
 
 NPError
 PluginModuleParent::NPP_NewStream(NPP instance, NPMIMEType type,
                                   NPStream* stream, NPBool seekable,
                                   uint16_t* stype)
 {
     AUTO_PROFILER_LABEL("PluginModuleParent::NPP_NewStream", OTHER);
-    RESOLVE_AND_CALL(instance, NPP_NewStream(type, stream, seekable, stype));
+
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->NPP_NewStream(type, stream, seekable, stype)
+               : NPERR_GENERIC_ERROR;
 }
 
 NPError
 PluginModuleParent::NPP_SetWindow(NPP instance, NPWindow* window)
 {
-    RESOLVE_AND_CALL(instance, NPP_SetWindow(window));
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->NPP_SetWindow(window) : NPERR_GENERIC_ERROR;
 }
 
 NPError
 PluginModuleParent::NPP_DestroyStream(NPP instance,
                                       NPStream* stream,
                                       NPReason reason)
 {
-    RESOLVE_AND_CALL(instance, NPP_DestroyStream(stream, reason));
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->NPP_DestroyStream(stream, reason) : NPERR_GENERIC_ERROR;
 }
 
 int32_t
 PluginModuleParent::NPP_WriteReady(NPP instance,
                                    NPStream* stream)
 {
-    PluginAsyncSurrogate* surrogate = nullptr;
-    BrowserStreamParent* s = StreamCast(instance, stream, &surrogate);
-    if (!s) {
-        if (surrogate) {
-            return surrogate->NPP_WriteReady(stream);
-        }
-        return -1;
-    }
-
-    return s->WriteReady();
+    BrowserStreamParent* s = StreamCast(instance, stream);
+    return s ? s->WriteReady() : -1;
 }
 
 int32_t
 PluginModuleParent::NPP_Write(NPP instance,
                               NPStream* stream,
                               int32_t offset,
                               int32_t len,
                               void* buffer)
@@ -1962,59 +1820,49 @@ PluginModuleParent::NPP_StreamAsFile(NPP
 
     s->StreamAsFile(fname);
 }
 
 void
 PluginModuleParent::NPP_Print(NPP instance, NPPrint* platformPrint)
 {
 
-    PluginInstanceParent* i = PluginInstanceParent::Cast(instance);
-    i->NPP_Print(platformPrint);
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->NPP_Print(platformPrint) : (void)0;
 }
 
 int16_t
 PluginModuleParent::NPP_HandleEvent(NPP instance, void* event)
 {
-    RESOLVE_AND_CALL(instance, NPP_HandleEvent(event));
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->NPP_HandleEvent(event) : NPERR_GENERIC_ERROR;
 }
 
 void
 PluginModuleParent::NPP_URLNotify(NPP instance, const char* url,
                                   NPReason reason, void* notifyData)
 {
-    PluginInstanceParent* i = PluginInstanceParent::Cast(instance);
-    if (!i)
-        return;
-
-    i->NPP_URLNotify(url, reason, notifyData);
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->NPP_URLNotify(url, reason, notifyData) : (void)0;
 }
 
 NPError
 PluginModuleParent::NPP_GetValue(NPP instance,
                                  NPPVariable variable, void *ret_value)
 {
-    // The rules are slightly different for this function.
-    // If there is a surrogate, we *always* use it.
-    PluginAsyncSurrogate* surrogate = nullptr;
-    PluginInstanceParent* i = PluginInstanceParent::Cast(instance, &surrogate);
-    if (surrogate) {
-        return surrogate->NPP_GetValue(variable, ret_value);
-    }
-    if (!i) {
-        return NPERR_GENERIC_ERROR;
-    }
-    return i->NPP_GetValue(variable, ret_value);
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->NPP_GetValue(variable, ret_value) : NPERR_GENERIC_ERROR;
 }
 
 NPError
 PluginModuleParent::NPP_SetValue(NPP instance, NPNVariable variable,
                                  void *value)
 {
-    RESOLVE_AND_CALL(instance, NPP_SetValue(variable, value));
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->NPP_SetValue(variable, value) : NPERR_GENERIC_ERROR;
 }
 
 mozilla::ipc::IPCResult
 PluginModuleChromeParent::AnswerNPN_SetValue_NPPVpluginRequiresAudioDeviceChanges(
     const bool& shouldRegister, NPError* result)
 {
 #ifdef XP_WIN
     *result = NPERR_NO_ERROR;
@@ -2047,156 +1895,125 @@ PluginModuleParent::RecvBackUpXResources
 #endif
     return IPC_OK();
 }
 
 void
 PluginModuleParent::NPP_URLRedirectNotify(NPP instance, const char* url,
                                           int32_t status, void* notifyData)
 {
-  PluginInstanceParent* i = PluginInstanceParent::Cast(instance);
-  if (!i)
-    return;
-
-  i->NPP_URLRedirectNotify(url, status, notifyData);
+  PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+  return pip ? pip->NPP_URLRedirectNotify(url, status, notifyData) : (void)0;
 }
 
 BrowserStreamParent*
-PluginModuleParent::StreamCast(NPP instance, NPStream* s,
-                               PluginAsyncSurrogate** aSurrogate)
+PluginModuleParent::StreamCast(NPP instance, NPStream* s)
 {
-    PluginInstanceParent* ip = PluginInstanceParent::Cast(instance, aSurrogate);
-    if (!ip || (aSurrogate && *aSurrogate && ip->UseSurrogate())) {
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    if (!pip) {
         return nullptr;
     }
 
     BrowserStreamParent* sp =
         static_cast<BrowserStreamParent*>(static_cast<AStream*>(s->pdata));
-    if (sp && (sp->mNPP != ip || s != sp->mStream)) {
+    if (sp && (sp->mNPP != pip || s != sp->mStream)) {
         MOZ_CRASH("Corrupted plugin stream data.");
     }
     return sp;
 }
 
 bool
 PluginModuleParent::HasRequiredFunctions()
 {
     return true;
 }
 
 nsresult
 PluginModuleParent::AsyncSetWindow(NPP instance, NPWindow* window)
 {
-    PluginAsyncSurrogate* surrogate = nullptr;
-    PluginInstanceParent* i = PluginInstanceParent::Cast(instance, &surrogate);
-    if (surrogate && (!i || i->UseSurrogate())) {
-        return surrogate->AsyncSetWindow(window);
-    } else if (!i) {
-        return NS_ERROR_FAILURE;
-    }
-    return i->AsyncSetWindow(window);
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->AsyncSetWindow(window) : NS_ERROR_FAILURE;
 }
 
 nsresult
 PluginModuleParent::GetImageContainer(NPP instance,
                              mozilla::layers::ImageContainer** aContainer)
 {
-    PluginInstanceParent* i = PluginInstanceParent::Cast(instance);
-    return !i ? NS_ERROR_FAILURE : i->GetImageContainer(aContainer);
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->GetImageContainer(aContainer) : NS_ERROR_FAILURE;
 }
 
 nsresult
 PluginModuleParent::GetImageSize(NPP instance,
                                  nsIntSize* aSize)
 {
-    PluginInstanceParent* i = PluginInstanceParent::Cast(instance);
-    return !i ? NS_ERROR_FAILURE : i->GetImageSize(aSize);
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->GetImageSize(aSize) : NS_ERROR_FAILURE;
 }
 
 void
 PluginModuleParent::DidComposite(NPP aInstance)
 {
-    if (PluginInstanceParent* i = PluginInstanceParent::Cast(aInstance)) {
-        i->DidComposite();
-    }
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(aInstance);
+    return pip ? pip->DidComposite() : (void)0;
 }
 
 nsresult
 PluginModuleParent::SetBackgroundUnknown(NPP instance)
 {
-    PluginInstanceParent* i = PluginInstanceParent::Cast(instance);
-    if (!i)
-        return NS_ERROR_FAILURE;
-
-    return i->SetBackgroundUnknown();
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->SetBackgroundUnknown() : NS_ERROR_FAILURE;
 }
 
 nsresult
 PluginModuleParent::BeginUpdateBackground(NPP instance,
                                           const nsIntRect& aRect,
                                           DrawTarget** aDrawTarget)
 {
-    PluginInstanceParent* i = PluginInstanceParent::Cast(instance);
-    if (!i)
-        return NS_ERROR_FAILURE;
-
-    return i->BeginUpdateBackground(aRect, aDrawTarget);
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->BeginUpdateBackground(aRect, aDrawTarget)
+               : NS_ERROR_FAILURE;
 }
 
 nsresult
 PluginModuleParent::EndUpdateBackground(NPP instance, const nsIntRect& aRect)
 {
-    PluginInstanceParent* i = PluginInstanceParent::Cast(instance);
-    if (!i)
-        return NS_ERROR_FAILURE;
-
-    return i->EndUpdateBackground(aRect);
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->EndUpdateBackground(aRect) : NS_ERROR_FAILURE;
 }
 
 #if defined(XP_WIN)
 nsresult
 PluginModuleParent::GetScrollCaptureContainer(NPP aInstance,
                                               mozilla::layers::ImageContainer** aContainer)
 {
-    PluginInstanceParent* inst = PluginInstanceParent::Cast(aInstance);
-    return !inst ? NS_ERROR_FAILURE : inst->GetScrollCaptureContainer(aContainer);
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(aInstance);
+    return pip ? pip->GetScrollCaptureContainer(aContainer) : NS_ERROR_FAILURE;
 }
 #endif
 
 nsresult
 PluginModuleParent::HandledWindowedPluginKeyEvent(
                         NPP aInstance,
                         const NativeEventData& aNativeKeyData,
                         bool aIsConsumed)
 {
-    PluginInstanceParent* parent = PluginInstanceParent::Cast(aInstance);
-    if (NS_WARN_IF(!parent)) {
-        return NS_ERROR_FAILURE;
-    }
-    return parent->HandledWindowedPluginKeyEvent(aNativeKeyData, aIsConsumed);
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(aInstance);
+    return pip ? pip->HandledWindowedPluginKeyEvent(aNativeKeyData, aIsConsumed)
+               : NS_ERROR_FAILURE;
 }
 
 void
 PluginModuleParent::OnInitFailure()
 {
     if (GetIPCChannel()->CanSend()) {
         Close();
     }
 
     mShutdown = true;
-
-    if (mIsStartingAsync) {
-        /* If we've failed then we need to enumerate any pending NPP_New calls
-           and clean them up. */
-        uint32_t len = mSurrogateInstances.Length();
-        for (uint32_t i = 0; i < len; ++i) {
-            mSurrogateInstances[i]->NotifyAsyncInitFailed();
-        }
-        mSurrogateInstances.Clear();
-    }
 }
 
 class PluginOfflineObserver final : public nsIObserver
 {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIOBSERVER
 
@@ -2305,26 +2122,17 @@ PluginModuleParent::NP_Initialize(NPNets
     mNPPIface = pFuncs;
 
     if (mShutdown) {
         *error = NPERR_GENERIC_ERROR;
         return NS_ERROR_FAILURE;
     }
 
     *error = NPERR_NO_ERROR;
-    if (mIsStartingAsync) {
-        if (GetIPCChannel()->CanSend()) {
-            // We're already connected, so we may call this immediately.
-            RecvNP_InitializeResult(*error);
-        } else {
-            PluginAsyncSurrogate::NP_GetEntryPoints(pFuncs);
-        }
-    } else {
-        SetPluginFuncs(pFuncs);
-    }
+    SetPluginFuncs(pFuncs);
 
     return NS_OK;
 }
 
 nsresult
 PluginModuleChromeParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error)
 {
     PLUGIN_LOG_DEBUG_METHOD;
@@ -2334,98 +2142,39 @@ PluginModuleChromeParent::NP_Initialize(
         return NS_ERROR_FAILURE;
     }
 
     *error = NPERR_NO_ERROR;
 
     mNPNIface = bFuncs;
     mNPPIface = pFuncs;
 
-    // NB: This *MUST* be set prior to checking whether the subprocess has
-    // been connected!
-    if (mIsStartingAsync) {
-        PluginAsyncSurrogate::NP_GetEntryPoints(pFuncs);
-    }
-
-    if (!mSubprocess->IsConnected()) {
-        // The subprocess isn't connected yet. Defer NP_Initialize until
-        // OnProcessLaunched is invoked.
-        mInitOnAsyncConnect = true;
-        return NS_OK;
-    }
-
     PluginSettings settings;
     GetSettings(&settings);
 
     TimeStamp callNpInitStart = TimeStamp::Now();
-    // Asynchronous case
-    if (mIsStartingAsync) {
-        if (!SendAsyncNP_Initialize(settings)) {
-            Close();
-            return NS_ERROR_FAILURE;
-        }
-        TimeStamp callNpInitEnd = TimeStamp::Now();
-        mTimeBlocked += (callNpInitEnd - callNpInitStart);
-        return NS_OK;
-    }
-
-    // Synchronous case
     if (!CallNP_Initialize(settings, error)) {
         Close();
         return NS_ERROR_FAILURE;
     }
     else if (*error != NPERR_NO_ERROR) {
         Close();
         return NS_ERROR_FAILURE;
     }
     TimeStamp callNpInitEnd = TimeStamp::Now();
     mTimeBlocked += (callNpInitEnd - callNpInitStart);
 
-    RecvNP_InitializeResult(*error);
-
-    return NS_OK;
-}
-
-mozilla::ipc::IPCResult
-PluginModuleParent::RecvNP_InitializeResult(const NPError& aError)
-{
-    if (aError != NPERR_NO_ERROR) {
+    if (*error != NPERR_NO_ERROR) {
         OnInitFailure();
-        return IPC_OK();
+        return NS_OK;
     }
 
     SetPluginFuncs(mNPPIface);
-    if (mIsStartingAsync) {
-        InitAsyncSurrogates();
-    }
-
-    mNPInitialized = true;
-    return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
-PluginModuleChromeParent::RecvNP_InitializeResult(const NPError& aError)
-{
-    if (!mContentParent) {
-        return PluginModuleParent::RecvNP_InitializeResult(aError);
-    }
-    bool initOk = aError == NPERR_NO_ERROR;
-    if (initOk) {
-        SetPluginFuncs(mNPPIface);
-        if (mIsStartingAsync && !SendAssociatePluginId()) {
-            initOk = false;
-        }
-    }
-    mNPInitialized = initOk;
-    bool result = mContentParent->SendLoadPluginResult(mPluginId, initOk);
-    mContentParent = nullptr;
-    if (!result) {
-      return IPC_FAIL_NO_REASON(this);
-    }
-    return IPC_OK();
+
+    return NS_OK;
 }
 
 #else
 
 nsresult
 PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
 {
     PLUGIN_LOG_DEBUG_METHOD;
@@ -2442,192 +2191,84 @@ PluginModuleParent::NP_Initialize(NPNets
 }
 
 #if defined(XP_WIN) || defined(XP_MACOSX)
 
 nsresult
 PluginModuleContentParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
 {
     PLUGIN_LOG_DEBUG_METHOD;
-    nsresult rv = PluginModuleParent::NP_Initialize(bFuncs, error);
-    if (mIsStartingAsync && GetIPCChannel()->CanSend()) {
-        // We're already connected, so we may call this immediately.
-        RecvNP_InitializeResult(*error);
-    }
-    return rv;
+    return PluginModuleParent::NP_Initialize(bFuncs, error);
 }
 
 #endif
 
 nsresult
 PluginModuleChromeParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
 {
     nsresult rv = PluginModuleParent::NP_Initialize(bFuncs, error);
     if (NS_FAILED(rv))
         return rv;
 
-#if defined(XP_MACOSX)
-    if (!mSubprocess->IsConnected()) {
-        // The subprocess isn't connected yet. Defer NP_Initialize until
-        // OnProcessLaunched is invoked.
-        mInitOnAsyncConnect = true;
-        *error = NPERR_NO_ERROR;
-        return NS_OK;
-    }
-#else
-    if (mInitOnAsyncConnect) {
-        *error = NPERR_NO_ERROR;
-        return NS_OK;
-    }
-#endif
-
     PluginSettings settings;
     GetSettings(&settings);
 
     TimeStamp callNpInitStart = TimeStamp::Now();
-    if (mIsStartingAsync) {
-        if (!SendAsyncNP_Initialize(settings)) {
-            return NS_ERROR_FAILURE;
-        }
-        TimeStamp callNpInitEnd = TimeStamp::Now();
-        mTimeBlocked += (callNpInitEnd - callNpInitStart);
-        return NS_OK;
-    }
-
     if (!CallNP_Initialize(settings, error)) {
         Close();
         return NS_ERROR_FAILURE;
     }
     TimeStamp callNpInitEnd = TimeStamp::Now();
     mTimeBlocked += (callNpInitEnd - callNpInitStart);
-    RecvNP_InitializeResult(*error);
-    return NS_OK;
-}
-
-mozilla::ipc::IPCResult
-PluginModuleParent::RecvNP_InitializeResult(const NPError& aError)
-{
-    if (aError != NPERR_NO_ERROR) {
-        OnInitFailure();
-        return IPC_OK();
-    }
-
-    if (mIsStartingAsync && mNPPIface) {
-        SetPluginFuncs(mNPPIface);
-        InitAsyncSurrogates();
-    }
-
-    mNPInitialized = true;
-    return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
-PluginModuleChromeParent::RecvNP_InitializeResult(const NPError& aError)
-{
+
     bool ok = true;
-    if (mContentParent) {
-        if ((ok = SendAssociatePluginId())) {
-            ok = mContentParent->SendLoadPluginResult(mPluginId,
-                                                      aError == NPERR_NO_ERROR);
-            mContentParent = nullptr;
-        }
-    } else if (aError == NPERR_NO_ERROR) {
+    if (*error == NPERR_NO_ERROR) {
         // Initialization steps for (e10s && !asyncInit) || !e10s
 #if defined XP_WIN
-        if (mIsStartingAsync) {
-            SetPluginFuncs(mNPPIface);
-        }
-
-        // Send the info needed to join the browser process's audio session to the
-        // plugin process.
+        // Send the info needed to join the browser process's audio session to
+        // the plugin process.
         nsID id;
         nsString sessionName;
         nsString iconPath;
 
         if (NS_SUCCEEDED(mozilla::widget::GetAudioSessionData(id, sessionName,
                                                               iconPath))) {
             Unused << SendSetAudioSessionData(id, sessionName, iconPath);
         }
 #endif
 
 #ifdef MOZ_CRASHREPORTER_INJECTOR
         InitializeInjector();
 #endif
     }
 
     if (!ok) {
-        return IPC_FAIL_NO_REASON(this);
+        return NS_ERROR_FAILURE;
     }
-    return PluginModuleParent::RecvNP_InitializeResult(aError);
+
+    if (*error != NPERR_NO_ERROR) {
+        OnInitFailure();
+        return NS_OK;
+    }
+
+    return NS_OK;
 }
 
 #endif
 
-void
-PluginModuleParent::InitAsyncSurrogates()
-{
-    if (MaybeRunDeferredShutdown()) {
-        // We've shut down, so the surrogates are no longer valid. Clear
-        // mSurrogateInstances to ensure that these aren't used.
-        mSurrogateInstances.Clear();
-        return;
-    }
-
-    uint32_t len = mSurrogateInstances.Length();
-    for (uint32_t i = 0; i < len; ++i) {
-        NPError err;
-        mAsyncNewRv = mSurrogateInstances[i]->NPP_New(&err);
-        if (NS_FAILED(mAsyncNewRv)) {
-            mSurrogateInstances[i]->NotifyAsyncInitFailed();
-            continue;
-        }
-    }
-    mSurrogateInstances.Clear();
-}
-
-bool
-PluginModuleParent::RemovePendingSurrogate(
-                            const RefPtr<PluginAsyncSurrogate>& aSurrogate)
-{
-    return mSurrogateInstances.RemoveElement(aSurrogate);
-}
-
-bool
-PluginModuleParent::MaybeRunDeferredShutdown()
-{
-    if (!mIsStartingAsync || !mIsNPShutdownPending) {
-        return false;
-    }
-    MOZ_ASSERT(!mShutdown);
-    NPError error;
-    if (!DoShutdown(&error)) {
-        return false;
-    }
-    mIsNPShutdownPending = false;
-    return true;
-}
-
 nsresult
 PluginModuleParent::NP_Shutdown(NPError* error)
 {
     PLUGIN_LOG_DEBUG_METHOD;
 
     if (mShutdown) {
         *error = NPERR_GENERIC_ERROR;
         return NS_ERROR_FAILURE;
     }
 
-    /* If we're still running an async NP_Initialize then we need to defer
-       shutdown until we've received the result of the NP_Initialize call. */
-    if (mIsStartingAsync && !mNPInitialized) {
-        mIsNPShutdownPending = true;
-        *error = NPERR_NO_ERROR;
-        return NS_OK;
-    }
-
     if (!DoShutdown(error)) {
         return NS_ERROR_FAILURE;
     }
 
     return NS_OK;
 }
 
 bool
@@ -2682,52 +2323,27 @@ PluginModuleParent::NP_GetValue(void *fu
 
 #if defined(XP_WIN) || defined(XP_MACOSX)
 nsresult
 PluginModuleParent::NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error)
 {
     NS_ASSERTION(pFuncs, "Null pointer!");
 
     *error = NPERR_NO_ERROR;
-    if (mIsStartingAsync && !IsChrome()) {
-        mNPPIface = pFuncs;
-#if defined(XP_MACOSX)
-        if (mNPInitialized) {
-            SetPluginFuncs(pFuncs);
-            InitAsyncSurrogates();
-        } else {
-            PluginAsyncSurrogate::NP_GetEntryPoints(pFuncs);
-        }
-#else
-        PluginAsyncSurrogate::NP_GetEntryPoints(pFuncs);
-#endif
-    } else {
-        SetPluginFuncs(pFuncs);
-    }
+    SetPluginFuncs(pFuncs);
 
     return NS_OK;
 }
 
 nsresult
 PluginModuleChromeParent::NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error)
 {
-#if defined(XP_MACOSX)
-    if (mInitOnAsyncConnect) {
-        PluginAsyncSurrogate::NP_GetEntryPoints(pFuncs);
-        mNPPIface = pFuncs;
-        *error = NPERR_NO_ERROR;
-        return NS_OK;
-    }
-#else
-    if (mIsStartingAsync) {
-        PluginAsyncSurrogate::NP_GetEntryPoints(pFuncs);
-    }
+#if !defined(XP_MACOSX)
     if (!mSubprocess->IsConnected()) {
         mNPPIface = pFuncs;
-        mInitOnAsyncConnect = true;
         *error = NPERR_NO_ERROR;
         return NS_OK;
     }
 #endif
 
     // We need to have the plugin process update its function table here by
     // actually calling NP_GetEntryPoints. The parent's function table will
     // reflect nullptr entries in the child's table once SetPluginFuncs is
@@ -2753,47 +2369,26 @@ PluginModuleParent::NPP_New(NPMIMEType p
 {
     PLUGIN_LOG_DEBUG_METHOD;
 
     if (mShutdown) {
         *error = NPERR_GENERIC_ERROR;
         return NS_ERROR_FAILURE;
     }
 
-    if (mIsStartingAsync) {
-        if (!PluginAsyncSurrogate::Create(this, pluginType, instance,
-                                          argc, argn, argv)) {
-            *error = NPERR_GENERIC_ERROR;
-            return NS_ERROR_FAILURE;
-        }
-
-        if (!mNPInitialized) {
-            RefPtr<PluginAsyncSurrogate> surrogate =
-                PluginAsyncSurrogate::Cast(instance);
-            mSurrogateInstances.AppendElement(surrogate);
-            *error = NPERR_NO_ERROR;
-            return NS_PLUGIN_INIT_PENDING;
-        }
-    }
-
     // create the instance on the other side
     InfallibleTArray<nsCString> names;
     InfallibleTArray<nsCString> values;
 
     for (int i = 0; i < argc; ++i) {
         names.AppendElement(NullableString(argn[i]));
         values.AppendElement(NullableString(argv[i]));
     }
 
-    nsresult rv = NPP_NewInternal(pluginType, instance, names, values,
-                                  saved, error);
-    if (NS_FAILED(rv) || !mIsStartingAsync) {
-        return rv;
-    }
-    return NS_PLUGIN_INIT_PENDING;
+    return NPP_NewInternal(pluginType, instance, names, values, saved, error);
 }
 
 class nsCaseInsensitiveUTF8StringArrayComparator
 {
 public:
   template<class A, class B>
   bool Equals(const A& a, const B& b) const {
     return a.Equals(b.get(), nsCaseInsensitiveUTF8StringComparator());
@@ -2917,21 +2512,17 @@ PluginModuleParent::NPP_NewInternal(NPMI
         // specified.
         if (supportsAsyncRender && supportsForceDirect &&
             gfxWindowsPlatform::GetPlatform()->SupportsPluginDirectDXGIDrawing()) {
             ForceDirect(names, values);
         }
 #endif
     }
 
-    // Release the surrogate reference that was in pdata
-    RefPtr<PluginAsyncSurrogate> surrogate(
-        dont_AddRef(PluginAsyncSurrogate::Cast(instance)));
-    // Now replace it with the instance
-    instance->pdata = static_cast<PluginDataResolver*>(parentInstance);
+    instance->pdata = parentInstance;
 
     // Any IPC messages for the PluginInstance actor should be dispatched to the
     // DocGroup for the plugin's document.
     RefPtr<nsPluginInstanceOwner> owner = parentInstance->GetOwner();
     nsCOMPtr<nsIDOMElement> elt;
     owner->GetDOMElement(getter_AddRefs(elt));
     if (nsCOMPtr<nsINode> node = do_QueryInterface(elt)) {
         nsCOMPtr<nsIDocument> doc = node->OwnerDoc();
@@ -2948,41 +2539,29 @@ PluginModuleParent::NPP_NewInternal(NPMI
         instance->pdata = nullptr;
         *error = NPERR_GENERIC_ERROR;
         return NS_ERROR_FAILURE;
     }
 
     {   // Scope for timer
         Telemetry::AutoTimer<Telemetry::BLOCKED_ON_PLUGIN_INSTANCE_INIT_MS>
             timer(GetHistogramKey());
-        if (mIsStartingAsync) {
-            MOZ_ASSERT(surrogate);
-            surrogate->AsyncCallDeparting();
-            if (!SendAsyncNPP_New(parentInstance)) {
+        if (!CallSyncNPP_New(parentInstance, error)) {
+            // if IPC is down, we'll get an immediate "failed" return, but
+            // without *error being set.  So make sure that the error
+            // condition is signaled to nsNPAPIPluginInstance
+            if (NPERR_NO_ERROR == *error) {
                 *error = NPERR_GENERIC_ERROR;
-                return NS_ERROR_FAILURE;
             }
-            *error = NPERR_NO_ERROR;
-        } else {
-            if (!CallSyncNPP_New(parentInstance, error)) {
-                // if IPC is down, we'll get an immediate "failed" return, but
-                // without *error being set.  So make sure that the error
-                // condition is signaled to nsNPAPIPluginInstance
-                if (NPERR_NO_ERROR == *error) {
-                    *error = NPERR_GENERIC_ERROR;
-                }
-                return NS_ERROR_FAILURE;
-            }
+            return NS_ERROR_FAILURE;
         }
     }
 
     if (*error != NPERR_NO_ERROR) {
-        if (!mIsStartingAsync) {
-            NPP_Destroy(instance, 0);
-        }
+        NPP_Destroy(instance, 0);
         return NS_ERROR_FAILURE;
     }
 
     UpdatePluginTimeout();
 
     return NS_OK;
 }
 
@@ -3025,32 +2604,27 @@ PluginModuleParent::NPP_GetSitesWithData
 
     return NS_OK;
 }
 
 #if defined(XP_MACOSX)
 nsresult
 PluginModuleParent::IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing)
 {
-    PluginInstanceParent* i = PluginInstanceParent::Cast(instance);
-    if (!i)
-        return NS_ERROR_FAILURE;
-
-    return i->IsRemoteDrawingCoreAnimation(aDrawing);
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->IsRemoteDrawingCoreAnimation(aDrawing) : NS_ERROR_FAILURE;
 }
 #endif
 #if defined(XP_MACOSX) || defined(XP_WIN)
 nsresult
 PluginModuleParent::ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor)
 {
-    PluginInstanceParent* i = PluginInstanceParent::Cast(instance);
-    if (!i)
-        return NS_ERROR_FAILURE;
-
-    return i->ContentsScaleFactorChanged(aContentsScaleFactor);
+    PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+    return pip ? pip->ContentsScaleFactorChanged(aContentsScaleFactor)
+               : NS_ERROR_FAILURE;
 }
 #endif // #if defined(XP_MACOSX)
 
 #if defined(XP_MACOSX)
 mozilla::ipc::IPCResult
 PluginModuleParent::AnswerProcessSomeEvents()
 {
     mozilla::plugins::PluginUtilsOSX::InvokeNativeEventLoop();
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -42,17 +42,16 @@ namespace mozilla {
 namespace layers {
 class TextureClientRecycleAllocator;
 } // namespace layers
 
 namespace plugins {
 //-----------------------------------------------------------------------------
 
 class BrowserStreamParent;
-class PluginAsyncSurrogate;
 class PluginInstanceParent;
 
 #ifdef XP_WIN
 class PluginHangUIParent;
 #endif
 #ifdef MOZ_CRASHREPORTER_INJECTOR
 class FinishInjectorInitTask;
 #endif
@@ -89,26 +88,19 @@ protected:
                                const InfallibleTArray<nsCString>& aNames,
                                const InfallibleTArray<nsCString>& aValues)
                                override;
 
     virtual bool
     DeallocPPluginInstanceParent(PPluginInstanceParent* aActor) override;
 
 public:
-    explicit PluginModuleParent(bool aIsChrome, bool aAllowAsyncInit);
+    explicit PluginModuleParent(bool aIsChrome);
     virtual ~PluginModuleParent();
 
-    bool RemovePendingSurrogate(const RefPtr<PluginAsyncSurrogate>& aSurrogate);
-
-    /** @return the state of the pref that controls async plugin init */
-    bool IsStartingAsync() const { return mIsStartingAsync; }
-    /** @return whether this modules NP_Initialize has successfully completed
-        executing */
-    bool IsInitialized() const { return mNPInitialized; }
     bool IsChrome() const { return mIsChrome; }
 
     virtual void SetPlugin(nsNPAPIPlugin* plugin) override
     {
         mPlugin = plugin;
     }
 
     virtual void ActorDestroy(ActorDestroyReason why) override;
@@ -118,18 +110,16 @@ public:
     }
 
     bool OkToCleanup() const {
         return !IsOnCxxStack();
     }
 
     void ProcessRemoteNativeEventsInInterruptCall() override;
 
-    virtual bool WaitForIPCConnection() { return true; }
-
     nsCString GetHistogramKey() const {
         return mPluginName + mPluginVersion;
     }
 
     void AccumulateModuleInitBlockedTime();
 
     virtual nsresult GetRunID(uint32_t* aRunID) override;
     virtual void SetHasLocalInstance() override {
@@ -175,21 +165,17 @@ protected:
     RecvPopCursor() override;
 
     virtual mozilla::ipc::IPCResult
     RecvNPN_SetException(const nsCString& aMessage) override;
 
     virtual mozilla::ipc::IPCResult
     RecvNPN_ReloadPlugins(const bool& aReloadPages) override;
 
-    virtual mozilla::ipc::IPCResult
-    RecvNP_InitializeResult(const NPError& aError) override;
-
-    static BrowserStreamParent* StreamCast(NPP instance, NPStream* s,
-                                           PluginAsyncSurrogate** aSurrogate = nullptr);
+    static BrowserStreamParent* StreamCast(NPP instance, NPStream* s);
 
     virtual mozilla::ipc::IPCResult
     AnswerNPN_SetValue_NPPVpluginRequiresAudioDeviceChanges(
                                         const bool& shouldRegister,
                                         NPError* result) override;
 
     virtual mozilla::ipc::IPCResult
     AnswerGetFileName(const GetFileNameFunc& aFunc,
@@ -310,26 +296,23 @@ public:
 
 #if defined(XP_MACOSX)
     virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing) override;
 #endif
 #if defined(XP_MACOSX) || defined(XP_WIN)
     virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor) override;
 #endif
 
-    void InitAsyncSurrogates();
-
     layers::TextureClientRecycleAllocator* EnsureTextureAllocatorForDirectBitmap();
     layers::TextureClientRecycleAllocator* EnsureTextureAllocatorForDXGISurface();
 
 protected:
     void NotifyFlashHang();
     void NotifyPluginCrashed();
     void OnInitFailure();
-    bool MaybeRunDeferredShutdown();
     bool DoShutdown(NPError* error);
 
     bool GetSetting(NPNVariable aVariable);
     void GetSettings(PluginSettings* aSettings);
 
     bool mIsChrome;
     bool mShutdown;
     bool mHadLocalInstance;
@@ -350,23 +333,16 @@ protected:
     // Dup of plugin's X socket, used to scope its resources to this
     // object instead of the plugin process's lifetime
     ScopedClose mPluginXSocketFdDup;
 #endif
 
     bool
     GetPluginDetails();
 
-    friend class mozilla::plugins::PluginAsyncSurrogate;
-
-    bool              mIsStartingAsync;
-    bool              mNPInitialized;
-    bool              mIsNPShutdownPending;
-    nsTArray<RefPtr<PluginAsyncSurrogate>> mSurrogateInstances;
-    nsresult          mAsyncNewRv;
     uint32_t          mRunID;
 
     RefPtr<layers::TextureClientRecycleAllocator> mTextureAllocatorForDirectBitmap;
     RefPtr<layers::TextureClientRecycleAllocator> mTextureAllocatorForDXGISurface;
 
 #ifdef MOZ_CRASHREPORTER
     /**
      * This mutex protects the crash reporter when the Plugin Hang UI event
@@ -377,26 +353,20 @@ protected:
     mozilla::Mutex mCrashReporterMutex;
     UniquePtr<ipc::CrashReporterHost> mCrashReporter;
 #endif // MOZ_CRASHREPORTER
 };
 
 class PluginModuleContentParent : public PluginModuleParent
 {
   public:
-    explicit PluginModuleContentParent(bool aAllowAsyncInit);
+    explicit PluginModuleContentParent();
 
     static PluginLibrary* LoadModule(uint32_t aPluginId, nsPluginTag* aPluginTag);
 
-    static void OnLoadPluginResult(const uint32_t& aPluginId,
-                                   const bool& aResult,
-                                   Endpoint<PPluginModuleParent>&& aEndpoint);
-
-    static void AssociatePluginId(uint32_t aPluginId, base::ProcessId aProcessId);
-
     virtual ~PluginModuleContentParent();
 
 #if defined(XP_WIN) || defined(XP_MACOSX)
     nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) override;
 #endif
 
   private:
     static void Initialize(Endpoint<PPluginModuleParent>&& aEndpoint);
@@ -427,24 +397,16 @@ class PluginModuleChromeParent
      * LoadModule
      *
      * This may or may not launch a plugin child process,
      * and may or may not be very expensive.
      */
     static PluginLibrary* LoadModule(const char* aFilePath, uint32_t aPluginId,
                                      nsPluginTag* aPluginTag);
 
-    /**
-     * The following two functions are called by SetupBridge to determine
-     * whether an existing plugin module was reused, or whether a new module
-     * was instantiated by the plugin host.
-     */
-    static void ClearInstantiationFlag() { sInstantiated = false; }
-    static bool DidInstantiate() { return sInstantiated; }
-
     virtual ~PluginModuleChromeParent();
 
     /*
      * Takes a full multi-process dump including the plugin process and the
      * content process. If aBrowserDumpId is not empty then the browser dump
      * associated with it will be paired to the resulting minidump.
      * Takes ownership of the file associated with aBrowserDumpId.
      *
@@ -530,27 +492,16 @@ class PluginModuleChromeParent
      */
     void
     OnHangUIContinue();
 
     void
     EvaluateHangUIState(const bool aReset);
 #endif // XP_WIN
 
-    virtual bool WaitForIPCConnection() override;
-
-    virtual mozilla::ipc::IPCResult
-    RecvNP_InitializeResult(const NPError& aError) override;
-
-    void
-    SetContentParent(dom::ContentParent* aContentParent);
-
-    bool
-    SendAssociatePluginId();
-
     void CachedSettingChanged();
 
     virtual mozilla::ipc::IPCResult
     AnswerGetKeyState(const int32_t& aVirtKey, int16_t* aRet) override;
 
     // Proxy GetOpenFileName/GetSaveFileName on Windows.
     virtual mozilla::ipc::IPCResult
     AnswerGetFileName(const GetFileNameFunc& aFunc,
@@ -595,18 +546,17 @@ private:
 #if defined(XP_WIN) || defined(XP_MACOSX)
     virtual nsresult NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error) override;
 #endif
 
     virtual void ActorDestroy(ActorDestroyReason why) override;
 
     // aFilePath is UTF8, not native!
     explicit PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId,
-                                      int32_t aSandboxLevel,
-                                      bool aAllowAsyncInit);
+                                      int32_t aSandboxLevel);
 
     void CleanupFromTimeout(const bool aByHangUI);
 
     virtual void UpdatePluginTimeout() override;
 
     void RegisterSettingsCallbacks();
     void UnregisterSettingsCallbacks();
 
@@ -652,18 +602,16 @@ private:
 
     /**
      * Finishes the Plugin Hang UI and cancels if it is being shown to the user.
      */
     void
     FinishHangUI();
 #endif
 
-    friend class mozilla::plugins::PluginAsyncSurrogate;
-
 #ifdef MOZ_CRASHREPORTER_INJECTOR
     friend class mozilla::plugins::FinishInjectorInitTask;
 
     void InitializeInjector();
     void DoInjection(const nsAutoHandle& aSnapshot);
     static DWORD WINAPI GetToolhelpSnapshot(LPVOID aContext);
 
     void OnCrash(DWORD processID) override;
@@ -691,27 +639,18 @@ private:
         }
 
     private:
         PluginModuleChromeParent* mModule;
     };
 
     friend class LaunchedTask;
 
-    bool                mInitOnAsyncConnect;
-    nsresult            mAsyncInitRv;
-    NPError             mAsyncInitError;
-    // mContentParent is to be used ONLY during the IPC dance that occurs
-    // when ContentParent::RecvLoadPlugin is called under async plugin init!
-    // In other contexts it is *unsafe*, as there might be multiple content
-    // processes in existence!
-    dom::ContentParent* mContentParent;
     nsCOMPtr<nsIObserver> mPluginOfflineObserver;
     bool mIsBlocklisted;
-    static bool sInstantiated;
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
     mozilla::SandboxPermissions mSandboxPermissions;
 #endif
 
 #ifdef MOZ_CRASHREPORTER
     nsCOMPtr<nsIFile> mBrowserDumpFile;
     TakeFullMinidumpCallback mTakeFullMinidumpCallback;
 #endif
--- a/dom/plugins/ipc/PluginProcessParent.cpp
+++ b/dom/plugins/ipc/PluginProcessParent.cpp
@@ -27,17 +27,16 @@ using base::ProcessArchitecture;
 PluginProcessParent::PidSet* PluginProcessParent::sPidSet = nullptr;
 #endif
 
 PluginProcessParent::PluginProcessParent(const std::string& aPluginFilePath) :
       GeckoChildProcessHost(GeckoProcessType_Plugin)
     , mPluginFilePath(aPluginFilePath)
     , mTaskFactory(this)
     , mMainMsgLoop(MessageLoop::current())
-    , mRunCompleteTaskImmediately(false)
 #ifdef XP_WIN
     , mChildPid(0)
 #endif
 {
 }
 
 PluginProcessParent::~PluginProcessParent()
 {
@@ -125,22 +124,16 @@ PluginProcessParent::Delete()
   }
 
   ioLoop->PostTask(
     NewNonOwningRunnableMethod("plugins::PluginProcessParent::Delete",
                                this,
                                &PluginProcessParent::Delete));
 }
 
-void
-PluginProcessParent::SetCallRunnableImmediately(bool aCallImmediately)
-{
-    mRunCompleteTaskImmediately = aCallImmediately;
-}
-
 /**
  * This function exists so that we may provide an additional level of
  * indirection between the task being posted to main event loop (a
  * RunnableMethod) and the launch complete task itself. This is needed
  * for cases when both WaitUntilConnected or OnChannel* race to invoke the
  * task.
  */
 void
@@ -151,17 +144,17 @@ PluginProcessParent::RunLaunchCompleteTa
         mLaunchCompleteTask = nullptr;
     }
 }
 
 bool
 PluginProcessParent::WaitUntilConnected(int32_t aTimeoutMs)
 {
     bool result = GeckoChildProcessHost::WaitUntilConnected(aTimeoutMs);
-    if (mRunCompleteTaskImmediately && mLaunchCompleteTask) {
+    if (mLaunchCompleteTask) {
         if (result) {
             mLaunchCompleteTask->SetLaunchSucceeded();
         }
         RunLaunchCompleteTask();
     }
     return result;
 }
 
@@ -172,31 +165,22 @@ PluginProcessParent::OnChannelConnected(
     mChildPid = static_cast<uint32_t>(peer_pid);
     if (!sPidSet) {
         sPidSet = new PluginProcessParent::PidSet();
     }
     sPidSet->PutEntry(mChildPid);
 #endif
 
     GeckoChildProcessHost::OnChannelConnected(peer_pid);
-    if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) {
-        mLaunchCompleteTask->SetLaunchSucceeded();
-        mMainMsgLoop->PostTask(mTaskFactory.NewRunnableMethod(
-                                   &PluginProcessParent::RunLaunchCompleteTask));
-    }
 }
 
 void
 PluginProcessParent::OnChannelError()
 {
     GeckoChildProcessHost::OnChannelError();
-    if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) {
-        mMainMsgLoop->PostTask(mTaskFactory.NewRunnableMethod(
-                                   &PluginProcessParent::RunLaunchCompleteTask));
-    }
 }
 
 bool
 PluginProcessParent::IsConnected()
 {
     mozilla::MonitorAutoLock lock(mMonitor);
     return mProcessState == PROCESS_CONNECTED;
 }
--- a/dom/plugins/ipc/PluginProcessParent.h
+++ b/dom/plugins/ipc/PluginProcessParent.h
@@ -63,34 +63,32 @@ public:
     {
         return true;
     }
 
     const std::string& GetPluginFilePath() { return mPluginFilePath; }
 
     using mozilla::ipc::GeckoChildProcessHost::GetChannel;
 
-    void SetCallRunnableImmediately(bool aCallImmediately);
     virtual bool WaitUntilConnected(int32_t aTimeoutMs = 0) override;
 
     virtual void OnChannelConnected(int32_t peer_pid) override;
     virtual void OnChannelError() override;
 
     bool IsConnected();
 
     static bool IsPluginProcessId(base::ProcessId procId);
 
 private:
     void RunLaunchCompleteTask();
 
     std::string mPluginFilePath;
     ipc::TaskFactory<PluginProcessParent> mTaskFactory;
     UniquePtr<LaunchCompleteTask> mLaunchCompleteTask;
     MessageLoop* mMainMsgLoop;
-    bool mRunCompleteTaskImmediately;
 #ifdef XP_WIN
     typedef nsTHashtable<nsUint32HashKey> PidSet;
     // Set of PIDs for all plugin child processes or NULL if empty.
     static PidSet* sPidSet;
     uint32_t mChildPid;
 #endif
 
     DISALLOW_EVIL_CONSTRUCTORS(PluginProcessParent);
--- a/dom/plugins/ipc/PluginScriptableObjectParent.cpp
+++ b/dom/plugins/ipc/PluginScriptableObjectParent.cpp
@@ -7,17 +7,16 @@
 #include "PluginScriptableObjectParent.h"
 
 #include "jsapi.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/plugins/PluginTypes.h"
 #include "mozilla/Unused.h"
 #include "nsNPAPIPlugin.h"
-#include "PluginAsyncSurrogate.h"
 #include "PluginScriptableObjectUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::plugins;
 using namespace mozilla::plugins::parent;
 
 /**
  * NPIdentifiers in the chrome process are stored as jsids. The difficulty is in
@@ -106,17 +105,16 @@ FromNPIdentifier(NPIdentifier aIdentifie
 }
 
 namespace {
 
 inline void
 ReleaseVariant(NPVariant& aVariant,
                PluginInstanceParent* aInstance)
 {
-  PushSurrogateAcceptCalls acceptCalls(aInstance);
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(aInstance);
   if (npn) {
     npn->releasevariantvalue(&aVariant);
   }
 }
 
 } // namespace
 
@@ -649,17 +647,16 @@ PluginScriptableObjectParent::Initialize
 }
 
 NPObject*
 PluginScriptableObjectParent::CreateProxyObject()
 {
   NS_ASSERTION(mInstance, "Must have an instance!");
   NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!");
 
-  PushSurrogateAcceptCalls acceptCalls(mInstance);
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(mInstance);
 
   NPObject* npobject = npn->createobject(mInstance->GetNPP(),
                                          const_cast<NPClass*>(GetClass()));
   NS_ASSERTION(npobject, "Failed to create object?!");
   NS_ASSERTION(npobject->_class == GetClass(), "Wrong kind of object!");
   NS_ASSERTION(npobject->referenceCount == 1, "Some kind of live object!");
 
@@ -768,17 +765,16 @@ PluginScriptableObjectParent::AnswerHasM
 
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aHasMethod = false;
     return IPC_OK();
   }
 
-  PushSurrogateAcceptCalls acceptCalls(instance);
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aHasMethod = false;
     return IPC_OK();
   }
 
   StackIdentifier stackID(aId);
@@ -809,17 +805,16 @@ PluginScriptableObjectParent::AnswerInvo
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aResult = void_t();
     *aSuccess = false;
     return IPC_OK();
   }
 
-  PushSurrogateAcceptCalls acceptCalls(instance);
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aResult = void_t();
     *aSuccess = false;
     return IPC_OK();
   }
 
@@ -899,17 +894,16 @@ PluginScriptableObjectParent::AnswerInvo
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aResult = void_t();
     *aSuccess = false;
     return IPC_OK();
   }
 
-  PushSurrogateAcceptCalls acceptCalls(instance);
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aResult = void_t();
     *aSuccess = false;
     return IPC_OK();
   }
 
@@ -980,17 +974,16 @@ PluginScriptableObjectParent::AnswerHasP
 
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aHasProperty = false;
     return IPC_OK();
   }
 
-  PushSurrogateAcceptCalls acceptCalls(instance);
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aHasProperty = false;
     return IPC_OK();
   }
 
   StackIdentifier stackID(aId);
@@ -1023,17 +1016,16 @@ PluginScriptableObjectParent::AnswerGetP
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aResult = void_t();
     *aSuccess = false;
     return IPC_OK();
   }
 
-  PushSurrogateAcceptCalls acceptCalls(instance);
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aResult = void_t();
     *aSuccess = false;
     return IPC_OK();
   }
 
@@ -1080,17 +1072,16 @@ PluginScriptableObjectParent::AnswerSetP
 
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aSuccess = false;
     return IPC_OK();
   }
 
-  PushSurrogateAcceptCalls acceptCalls(instance);
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aSuccess = false;
     return IPC_OK();
   }
 
   NPVariant converted;
@@ -1127,17 +1118,16 @@ PluginScriptableObjectParent::AnswerRemo
 
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aSuccess = false;
     return IPC_OK();
   }
 
-  PushSurrogateAcceptCalls acceptCalls(instance);
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aSuccess = false;
     return IPC_OK();
   }
 
   StackIdentifier stackID(aId);
@@ -1166,17 +1156,16 @@ PluginScriptableObjectParent::AnswerEnum
 
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aSuccess = false;
     return IPC_OK();
   }
 
-  PushSurrogateAcceptCalls acceptCalls(instance);
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_WARNING("No netscape funcs?!");
     *aSuccess = false;
     return IPC_OK();
   }
 
   NPIdentifier* ids;
@@ -1219,17 +1208,16 @@ PluginScriptableObjectParent::AnswerCons
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aResult = void_t();
     *aSuccess = false;
     return IPC_OK();
   }
 
-  PushSurrogateAcceptCalls acceptCalls(instance);
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aResult = void_t();
     *aSuccess = false;
     return IPC_OK();
   }
 
@@ -1312,17 +1300,16 @@ PluginScriptableObjectParent::AnswerNPN_
   PluginInstanceParent* instance = GetInstance();
   if (!instance) {
     NS_ERROR("No instance?!");
     *aResult = void_t();
     *aSuccess = false;
     return IPC_OK();
   }
 
-  PushSurrogateAcceptCalls acceptCalls(instance);
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aResult = void_t();
     *aSuccess = false;
     return IPC_OK();
   }
 
--- a/dom/plugins/ipc/PluginTypes.ipdlh
+++ b/dom/plugins/ipc/PluginTypes.ipdlh
@@ -13,17 +13,16 @@ struct PluginTag
   uint32_t id;
   nsCString name;
   nsCString description;
   nsCString[] mimeTypes;
   nsCString[] mimeDescriptions;
   nsCString[] extensions;
   bool isJavaPlugin;
   bool isFlashPlugin;
-  bool supportsAsyncInit;
   bool supportsAsyncRender; // flash specific
   nsCString filename;
   nsCString version;
   int64_t lastModifiedTime;
   bool isFromExtension;
   int32_t sandboxLevel;
 };
 
--- a/dom/plugins/ipc/moz.build
+++ b/dom/plugins/ipc/moz.build
@@ -16,19 +16,17 @@ EXPORTS.mozilla.plugins += [
     'BrowserStreamChild.h',
     'BrowserStreamParent.h',
     'ChildAsyncCall.h',
     'ChildTimer.h',
     'NPEventAndroid.h',
     'NPEventOSX.h',
     'NPEventUnix.h',
     'NPEventWindows.h',
-    'PluginAsyncSurrogate.h',
     'PluginBridge.h',
-    'PluginDataResolver.h',
     'PluginInstanceChild.h',
     'PluginInstanceParent.h',
     'PluginMessageUtils.h',
     'PluginModuleChild.h',
     'PluginModuleParent.h',
     'PluginProcessChild.h',
     'PluginProcessParent.h',
     'PluginQuirks.h',
@@ -65,17 +63,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
         'PluginInterposeOSX.h',
     ]
 
 UNIFIED_SOURCES += [
     'BrowserStreamChild.cpp',
     'BrowserStreamParent.cpp',
     'ChildAsyncCall.cpp',
     'ChildTimer.cpp',
-    'PluginAsyncSurrogate.cpp',
     'PluginBackgroundDestroyer.cpp',
     'PluginInstanceParent.cpp',
     'PluginMessageUtils.cpp',
     'PluginModuleParent.cpp',
     'PluginProcessChild.cpp',
     'PluginProcessParent.cpp',
     'PluginQuirks.cpp',
     'PluginScriptableObjectChild.cpp',
--- a/dom/workers/ServiceWorkerClients.cpp
+++ b/dom/workers/ServiceWorkerClients.cpp
@@ -749,20 +749,24 @@ private:
 
     nsCOMPtr<nsIBrowserDOMWindow> bwin;
     chromeWin->GetBrowserDOMWindow(getter_AddRefs(bwin));
 
     if (NS_WARN_IF(!bwin)) {
       return NS_ERROR_FAILURE;
     }
 
+    nsCOMPtr<nsIPrincipal> triggeringPrincipal = workerPrivate->GetPrincipal();
+    MOZ_DIAGNOSTIC_ASSERT(triggeringPrincipal);
+
     nsCOMPtr<mozIDOMWindowProxy> win;
     rv = bwin->OpenURI(uri, nullptr,
                        nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW,
                        nsIBrowserDOMWindow::OPEN_NEW,
+                       triggeringPrincipal,
                        getter_AddRefs(win));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     NS_ENSURE_STATE(win);
 
     nsCOMPtr<nsPIDOMWindowOuter> pWin = nsPIDOMWindowOuter::From(win);
     pWin.forget(aWindow);
--- a/gfx/layers/AnimationHelper.h
+++ b/gfx/layers/AnimationHelper.h
@@ -160,17 +160,17 @@ public:
 
   /**
    * Clear AnimatedValues and Animations data
    */
   void Clear();
 
   void ClearById(const uint64_t& aId);
 private:
-  ~CompositorAnimationStorage() { Clear(); };
+  ~CompositorAnimationStorage() { };
 
 private:
   AnimatedValueTable mAnimatedValues;
   AnimationsTable mAnimations;
 };
 
 class AnimationHelper
 {
--- a/gfx/layers/PaintThread.cpp
+++ b/gfx/layers/PaintThread.cpp
@@ -1,58 +1,65 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=99: */
 /* 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 "PaintThread.h"
 
+#include "base/task.h"
+#include "gfxPrefs.h"
+#include "mozilla/layers/CompositorBridgeChild.h"
 #include "mozilla/gfx/2D.h"
+#include "mozilla/Preferences.h"
 #include "mozilla/SyncRunnable.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace gfx;
 
 StaticAutoPtr<PaintThread> PaintThread::sSingleton;
+StaticRefPtr<nsIThread> PaintThread::sThread;
+PlatformThreadId PaintThread::sThreadId;
 
 void
 PaintThread::Release()
 {
 }
 
 void
 PaintThread::AddRef()
 {
 }
 
 void
 PaintThread::InitOnPaintThread()
 {
   MOZ_ASSERT(!NS_IsMainThread());
-  mThreadId = PlatformThread::CurrentId();
+  sThreadId = PlatformThread::CurrentId();
 }
 
 bool
 PaintThread::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  nsresult rv = NS_NewNamedThread("PaintThread", getter_AddRefs(mThread));
 
+  RefPtr<nsIThread> thread;
+  nsresult rv = NS_NewNamedThread("PaintThread", getter_AddRefs(thread));
   if (NS_FAILED(rv)) {
     return false;
   }
+  sThread = thread;
 
   nsCOMPtr<nsIRunnable> paintInitTask =
     NewRunnableMethod("PaintThread::InitOnPaintThread",
                       this, &PaintThread::InitOnPaintThread);
-
-  SyncRunnable::DispatchToThread(PaintThread::sSingleton->mThread, paintInitTask);
+  SyncRunnable::DispatchToThread(sThread, paintInitTask);
   return true;
 }
 
 /* static */ void
 PaintThread::Start()
 {
   PaintThread::sSingleton = new PaintThread();
 
@@ -64,55 +71,90 @@ PaintThread::Start()
 
 /* static */ PaintThread*
 PaintThread::Get()
 {
   MOZ_ASSERT(NS_IsMainThread());
   return PaintThread::sSingleton.get();
 }
 
+void
+DestroyPaintThread(UniquePtr<PaintThread>&& pt)
+{
+  MOZ_ASSERT(PaintThread::IsOnPaintThread());
+  pt->ShutdownOnPaintThread();
+}
+
 /* static */ void
 PaintThread::Shutdown()
 {
-  if (!PaintThread::sSingleton) {
+  MOZ_ASSERT(NS_IsMainThread());
+
+  UniquePtr<PaintThread> pt(sSingleton.forget());
+  if (!pt) {
     return;
   }
 
-  PaintThread::sSingleton->ShutdownImpl();
-  PaintThread::sSingleton = nullptr;
+  sThread->Dispatch(NewRunnableFunction(DestroyPaintThread, Move(pt)));
+  sThread->Shutdown();
+  sThread = nullptr;
 }
 
 void
-PaintThread::ShutdownImpl()
+PaintThread::ShutdownOnPaintThread()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  PaintThread::sSingleton->mThread->AsyncShutdown();
+  MOZ_ASSERT(IsOnPaintThread());
+}
+
+/* static */ bool
+PaintThread::IsOnPaintThread()
+{
+  return sThreadId == PlatformThread::CurrentId();
 }
 
-bool
-PaintThread::IsOnPaintThread()
+void
+PaintThread::PaintContentsAsync(CompositorBridgeChild* aBridge,
+                                gfx::DrawTargetCapture* aCapture,
+                                gfx::DrawTarget* aTarget)
 {
-  MOZ_ASSERT(mThread);
-  return PlatformThread::CurrentId() == mThreadId;
+  MOZ_ASSERT(IsOnPaintThread());
+
+  // Draw all the things into the actual dest target.
+  aTarget->DrawCapturedDT(aCapture, Matrix());
+
+  if (aBridge) {
+    aBridge->NotifyFinishedAsyncPaint();
+  }
 }
 
 void
 PaintThread::PaintContents(DrawTargetCapture* aCapture,
                            DrawTarget* aTarget)
 {
-  if (!IsOnPaintThread()) {
-    MOZ_ASSERT(NS_IsMainThread());
-    nsCOMPtr<nsIRunnable> paintTask =
-      NewRunnableMethod<DrawTargetCapture*, DrawTarget*>("PaintThread::PaintContents",
-                                                         this,
-                                                         &PaintThread::PaintContents,
-                                                         aCapture, aTarget);
+  MOZ_ASSERT(NS_IsMainThread());
+
+  // If painting asynchronously, we need to acquire the compositor bridge which
+  // owns the underlying MessageChannel. Otherwise we leave it null and use
+  // synchronous dispatch.
+  RefPtr<CompositorBridgeChild> cbc;
+  if (!gfxPrefs::LayersOMTPForceSync()) {
+    cbc = CompositorBridgeChild::Get();
+    cbc->NotifyBeginAsyncPaint();
+  }
+  RefPtr<DrawTargetCapture> capture(aCapture);
+  RefPtr<DrawTarget> target(aTarget);
 
-    SyncRunnable::DispatchToThread(mThread, paintTask);
-    return;
+  RefPtr<PaintThread> self = this;
+  RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::PaintContents",
+    [self, cbc, capture, target]() -> void
+  {
+    self->PaintContentsAsync(cbc, capture, target);
+  });
+
+  if (cbc) {
+    sThread->Dispatch(task.forget());
+  } else {
+    SyncRunnable::DispatchToThread(sThread, task);
   }
-
-  // Draw all the things into the actual dest target.
-  aTarget->DrawCapturedDT(aCapture, Matrix());
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/PaintThread.h
+++ b/gfx/layers/PaintThread.h
@@ -4,48 +4,59 @@
  * 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 MOZILLA_LAYERS_PAINTTHREAD_H
 #define MOZILLA_LAYERS_PAINTTHREAD_H
 
 #include "base/platform_thread.h"
 #include "mozilla/StaticPtr.h"
+#include "mozilla/UniquePtr.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 namespace gfx {
 class DrawTarget;
 class DrawTargetCapture;
 };
 
 namespace layers {
 
+class CompositorBridgeChild;
+
 class PaintThread final
 {
+  friend void DestroyPaintThread(UniquePtr<PaintThread>&& aPaintThread);
+
 public:
   static void Start();
   static void Shutdown();
   static PaintThread* Get();
   void PaintContents(gfx::DrawTargetCapture* aCapture,
                      gfx::DrawTarget* aTarget);
+
   // Sync Runnables need threads to be ref counted,
   // But this thread lives through the whole process.
   // We're only temporarily using sync runnables so
   // Override release/addref but don't do anything.
   void Release();
   void AddRef();
 
+  // Helper for asserts.
+  static bool IsOnPaintThread();
+
 private:
-  bool IsOnPaintThread();
   bool Init();
-  void ShutdownImpl();
+  void ShutdownOnPaintThread();
   void InitOnPaintThread();
+  void PaintContentsAsync(CompositorBridgeChild* aBridge,
+                          gfx::DrawTargetCapture* aCapture,
+                          gfx::DrawTarget* aTarget);
 
   static StaticAutoPtr<PaintThread> sSingleton;
-  RefPtr<nsIThread> mThread;
-  PlatformThreadId mThreadId;
+  static StaticRefPtr<nsIThread> sThread;
+  static PlatformThreadId sThreadId;
 };
 
 } // namespace layers
 } // namespace mozilla
 
-#endif
\ No newline at end of file
+#endif
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -221,16 +221,19 @@ ClientLayerManager::CreateReadbackLayer(
 {
   RefPtr<ReadbackLayer> layer = new ClientReadbackLayer(this);
   return layer.forget();
 }
 
 bool
 ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
 {
+  // Wait for any previous async paints to complete before starting to paint again.
+  GetCompositorBridgeChild()->FlushAsyncPaints();
+
   MOZ_ASSERT(mForwarder, "ClientLayerManager::BeginTransaction without forwarder");
   if (!mForwarder->IPCOpen()) {
     gfxCriticalNote << "ClientLayerManager::BeginTransaction with IPC channel down. GPU process may have died.";
     return false;
   }
 
   if (XRE_IsContentProcess() &&
       mForwarder->DeviceCanReset() &&
--- a/gfx/layers/composite/LayerManagerComposite.h
+++ b/gfx/layers/composite/LayerManagerComposite.h
@@ -308,16 +308,17 @@ public:
   virtual already_AddRefed<ImageLayer> CreateImageLayer() override;
   virtual already_AddRefed<ColorLayer> CreateColorLayer() override;
   virtual already_AddRefed<TextLayer> CreateTextLayer() override;
   virtual already_AddRefed<BorderLayer> CreateBorderLayer() override;
   virtual already_AddRefed<CanvasLayer> CreateCanvasLayer() override;
   virtual already_AddRefed<RefLayer> CreateRefLayer() override;
 
   virtual bool AreComponentAlphaLayersEnabled() override;
+  virtual bool SupportsBackdropCopyForComponentAlpha() override { return false; }
 
   virtual already_AddRefed<DrawTarget>
     CreateOptimalMaskDrawTarget(const IntSize &aSize) override;
 
   virtual const char* Name() const override { return ""; }
   virtual bool IsCompositingToScreen() const override;
 
   bool AlwaysScheduleComposite() const override;
@@ -509,17 +510,17 @@ private:
   /**
    * Render paint and composite times above the frame.
    */
   void DrawPaintTimes(Compositor* aCompositor);
   RefPtr<PaintCounter> mPaintCounter;
 #endif
 #if defined(MOZ_WIDGET_ANDROID)
 public:
-  virtual void RequestScreenPixels(UiCompositorControllerParent* aController)
+  virtual void RequestScreenPixels(UiCompositorControllerParent* aController) override
   {
     mScreenPixelsTarget = aController;
   }
 private:
   UiCompositorControllerParent* mScreenPixelsTarget;
 #endif // defined(MOZ_WIDGET_ANDROID)
 };
 
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -14,16 +14,17 @@
 #include "gfxPrefs.h"
 #include "mozilla/dom/TabGroup.h"
 #include "mozilla/layers/CompositorManagerChild.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/APZChild.h"
 #include "mozilla/layers/IAPZCTreeManager.h"
 #include "mozilla/layers/APZCTreeManagerChild.h"
 #include "mozilla/layers/LayerTransactionChild.h"
+#include "mozilla/layers/PaintThread.h"
 #include "mozilla/layers/PLayerTransactionChild.h"
 #include "mozilla/layers/PTextureChild.h"
 #include "mozilla/layers/TextureClient.h"// for TextureClient
 #include "mozilla/layers/TextureClientPool.h"// for TextureClientPool
 #include "mozilla/layers/WebRenderBridgeChild.h"
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/gfx/Logging.h"
@@ -84,16 +85,19 @@ CompositorBridgeChild::CompositorBridgeC
   , mResourceId(0)
   , mCanSend(false)
   , mActorDestroyed(false)
   , mFwdTransactionId(0)
   , mDeviceResetSequenceNumber(0)
   , mMessageLoop(MessageLoop::current())
   , mProcessToken(0)
   , mSectionAllocator(nullptr)
+  , mPaintLock("CompositorBridgeChild.mPaintLock")
+  , mOutstandingAsyncPaints(0)
+  , mIsWaitingForPaint(false)
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 CompositorBridgeChild::~CompositorBridgeChild()
 {
   if (mCanSend) {
     gfxCriticalError() << "CompositorBridgeChild was not deinitialized";
@@ -537,18 +541,30 @@ void
 CompositorBridgeChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   if (aWhy == AbnormalShutdown) {
     // If the parent side runs into a problem then the actor will be destroyed.
     // There is nothing we can do in the child side, here sets mCanSend as false.
     gfxCriticalNote << "Receive IPC close with reason=AbnormalShutdown";
   }
 
-  mCanSend = false;
-  mActorDestroyed = true;
+  {
+    // We take the lock to update these fields, since they are read from the
+    // paint thread. We don't need the lock to init them, since that happens
+    // on the main thread before the paint thread can ever grab a reference
+    // to the CompositorBridge object.
+    //
+    // Note that it is useful to take this lock for one other reason: It also
+    // tells us whether GetIPCChannel is safe to call. If we access the IPC
+    // channel within this lock, when mCanSend is true, then we know it has not
+    // been zapped by IPDL.
+    MonitorAutoLock lock(mPaintLock);
+    mCanSend = false;
+    mActorDestroyed = true;
+  }
 
   if (mProcessToken && XRE_IsParentProcess()) {
     GPUProcessManager::Get()->NotifyRemoteActorDestroyed(mProcessToken);
   }
 }
 
 mozilla::ipc::IPCResult
 CompositorBridgeChild::RecvSharedCompositorFrameMetrics(
@@ -1109,11 +1125,91 @@ CompositorBridgeChild::GetNextExternalIm
 }
 
 wr::PipelineId
 CompositorBridgeChild::GetNextPipelineId()
 {
   return wr::AsPipelineId(GetNextResourceId());
 }
 
+void
+CompositorBridgeChild::NotifyBeginAsyncPaint()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  MonitorAutoLock lock(mPaintLock);
+
+  // We must not be waiting for paints to complete yet. This would imply we
+  // started a new paint without waiting for a previous one, which could lead to
+  // incorrect rendering or IPDL deadlocks.
+  MOZ_ASSERT(!mIsWaitingForPaint);
+
+  mOutstandingAsyncPaints++;
+}
+
+void
+CompositorBridgeChild::NotifyFinishedAsyncPaint()
+{
+  MOZ_ASSERT(PaintThread::IsOnPaintThread());
+
+  MonitorAutoLock lock(mPaintLock);
+
+  mOutstandingAsyncPaints--;
+
+  // It's possible that we painted so fast that the main thread never reached
+  // the code that starts delaying messages. If so, mIsWaitingForPaint will be
+  // false, and we can safely return.
+  if (mIsWaitingForPaint && mOutstandingAsyncPaints == 0) {
+    ResumeIPCAfterAsyncPaint();
+
+    // Notify the main thread in case it's blocking. We do this unconditionally
+    // to avoid deadlocking.
+    lock.Notify();
+  }
+}
+
+void
+CompositorBridgeChild::PostponeMessagesIfAsyncPainting()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  MonitorAutoLock lock(mPaintLock);
+
+  MOZ_ASSERT(!mIsWaitingForPaint);
+
+  if (mOutstandingAsyncPaints > 0) {
+    mIsWaitingForPaint = true;
+    GetIPCChannel()->BeginPostponingSends();
+  }
+}
+
+void
+CompositorBridgeChild::ResumeIPCAfterAsyncPaint()
+{
+  // Note: the caller is responsible for holding the lock.
+  mPaintLock.AssertCurrentThreadOwns();
+  MOZ_ASSERT(PaintThread::IsOnPaintThread());
+  MOZ_ASSERT(mOutstandingAsyncPaints == 0);
+  MOZ_ASSERT(mIsWaitingForPaint);
+
+  mIsWaitingForPaint = false;
+
+  // It's also possible that the channel has shut down already.
+  if (!mCanSend || mActorDestroyed) {
+    return;
+  }
+
+  GetIPCChannel()->StopPostponingSends();
+}
+
+void
+CompositorBridgeChild::FlushAsyncPaints()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  MonitorAutoLock lock(mPaintLock);
+  while (mIsWaitingForPaint) {
+    lock.Wait();
+  }
+}
+
 } // namespace layers
 } // namespace mozilla
-
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_CompositorBridgeChild_h
 #define mozilla_layers_CompositorBridgeChild_h
 
 #include "base/basictypes.h"            // for DISALLOW_EVIL_CONSTRUCTORS
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT_HELPER2
 #include "mozilla/Attributes.h"         // for override
+#include "mozilla/Monitor.h"
 #include "mozilla/ipc/ProtocolUtils.h"
 #include "mozilla/layers/PCompositorBridgeChild.h"
 #include "mozilla/layers/TextureForwarder.h" // for TextureForwarder
 #include "mozilla/webrender/WebRenderTypes.h"
 #include "nsClassHashtable.h"           // for nsClassHashtable
 #include "nsRefPtrHashtable.h"
 #include "nsCOMPtr.h"                   // for nsCOMPtr
 #include "nsHashKeys.h"                 // for nsUint64HashKey
@@ -215,20 +216,43 @@ public:
   uint64_t DeviceResetSequenceNumber() const {
     return mDeviceResetSequenceNumber;
   }
 
   wr::MaybeExternalImageId GetNextExternalImageId() override;
 
   wr::PipelineId GetNextPipelineId();
 
+  // Must only be called from the main thread. Notifies the CompositorBridge
+  // that the paint thread is going to begin painting asynchronously.
+  void NotifyBeginAsyncPaint();
+
+  // Must only be called from the paint thread. Notifies the CompositorBridge
+  // that the paint thread has finished an asynchronous paint request.
+  void NotifyFinishedAsyncPaint();
+
+  // Must only be called from the main thread. Notifies the CompoistorBridge
+  // that a transaction is about to be sent, and if the paint thread is
+  // currently painting, to begin delaying IPC messages.
+  void PostponeMessagesIfAsyncPainting();
+
+  // Must only be called from the main thread. Ensures that any paints from
+  // previous frames have been flushed. The main thread blocks until the
+  // operation completes.
+  void FlushAsyncPaints();
+
 private:
   // Private destructor, to discourage deletion outside of Release():
   virtual ~CompositorBridgeChild();
 
+  // Must only be called from the paint thread. If the main thread is delaying
+  // IPC messages, this forwards all such delayed IPC messages to the I/O thread
+  // and resumes IPC.
+  void ResumeIPCAfterAsyncPaint();
+
   void AfterDestroy();
 
   virtual PLayerTransactionChild*
     AllocPLayerTransactionChild(const nsTArray<LayersBackend>& aBackendHints,
                                 const uint64_t& aId) override;
 
   virtual bool DeallocPLayerTransactionChild(PLayerTransactionChild *aChild) override;
 
@@ -323,14 +347,28 @@ private:
 
   MessageLoop* mMessageLoop;
 
   AutoTArray<RefPtr<TextureClientPool>,2> mTexturePools;
 
   uint64_t mProcessToken;
 
   FixedSizeSmallShmemSectionAllocator* mSectionAllocator;
+
+  // Off-Main-Thread Painting state. This covers access to the OMTP-related
+  // state below.
+  Monitor mPaintLock;
+
+  // Contains the number of outstanding asynchronous paints tied to a
+  // PLayerTransaction on this bridge. This is R/W on both the main and paint
+  // threads, and must be accessed within the paint lock.
+  size_t mOutstandingAsyncPaints;
+
+  // True if this CompositorBridge is currently delaying its messages until the
+  // paint thread completes. This is R/W on both the main and paint threads, and
+  // must be accessed within the paint lock.
+  bool mIsWaitingForPaint;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_layers_CompositorBrigedChild_h
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1510,24 +1510,24 @@ CompositorBridgeParent::AllocPLayerTrans
                                                      const uint64_t& aId)
 {
   MOZ_ASSERT(aId == 0);
 
   InitializeLayerManager(aBackendHints);
 
   if (!mLayerManager) {
     NS_WARNING("Failed to initialise Compositor");
-    LayerTransactionParent* p = new LayerTransactionParent(nullptr, this, 0);
+    LayerTransactionParent* p = new LayerTransactionParent(/* aManager */ nullptr, this, /* aAnimStorage */ nullptr, 0);
     p->AddIPDLReference();
     return p;
   }
 
   mCompositionManager = new AsyncCompositionManager(this, mLayerManager);
 
-  LayerTransactionParent* p = new LayerTransactionParent(mLayerManager, this, 0);
+  LayerTransactionParent* p = new LayerTransactionParent(mLayerManager, this, GetAnimationStorage(0), 0);
   p->AddIPDLReference();
   return p;
 }
 
 bool
 CompositorBridgeParent::DeallocPLayerTransactionParent(PLayerTransactionParent* actor)
 {
   static_cast<LayerTransactionParent*>(actor)->ReleaseIPDLReference();
@@ -1639,17 +1639,17 @@ CompositorBridgeParent::RecvAdoptChild(c
   APZCTreeManagerParent* parent;
   {
     MonitorAutoLock lock(*sIndirectLayerTreesLock);
     // We currently don't support adopting children from one compositor to
     // another if the two compositors don't have the same options.
     MOZ_ASSERT(sIndirectLayerTrees[child].mParent->mOptions == mOptions);
     NotifyChildCreated(child);
     if (sIndirectLayerTrees[child].mLayerTree) {
-      sIndirectLayerTrees[child].mLayerTree->SetLayerManager(mLayerManager);
+      sIndirectLayerTrees[child].mLayerTree->SetLayerManager(mLayerManager, GetAnimationStorage(0));
       // Trigger composition to handle a case that mLayerTree was not composited yet
       // by previous CompositorBridgeParent, since nsRefreshDriver might wait composition complete.
       ScheduleComposition();
     }
     if (mWrBridge && sIndirectLayerTrees[child].mWrBridge) {
       sIndirectLayerTrees[child].mWrBridge->UpdateWebRender(mWrBridge->CompositorScheduler(),
                                                             mWrBridge->GetWebRenderAPI(),
                                                             mWrBridge->CompositableHolder(),
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
@@ -83,24 +83,25 @@ CrossProcessCompositorBridgeParent::Allo
   LayerTreeMap::iterator itr = sIndirectLayerTrees.find(aId);
   if (sIndirectLayerTrees.end() != itr) {
     state = &itr->second;
   }
 
   if (state && state->mLayerManager) {
     state->mCrossProcessParent = this;
     HostLayerManager* lm = state->mLayerManager;
-    LayerTransactionParent* p = new LayerTransactionParent(lm, this, aId);
+    CompositorAnimationStorage* animStorage = state->mParent ? state->mParent->GetAnimationStorage(0) : nullptr;
+    LayerTransactionParent* p = new LayerTransactionParent(lm, this, animStorage, aId);
     p->AddIPDLReference();
     sIndirectLayerTrees[aId].mLayerTree = p;
     return p;
   }
 
   NS_WARNING("Created child without a matching parent?");
-  LayerTransactionParent* p = new LayerTransactionParent(nullptr, this, aId);
+  LayerTransactionParent* p = new LayerTransactionParent(/* aManager */ nullptr, this, /* aAnimStorage */ nullptr, aId);
   p->AddIPDLReference();
   return p;
 }
 
 bool
 CrossProcessCompositorBridgeParent::DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers)
 {
   LayerTransactionParent* slp = static_cast<LayerTransactionParent*>(aLayers);
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -46,40 +46,50 @@ using mozilla::layout::RenderFrameParent
 
 namespace mozilla {
 namespace layers {
 
 //--------------------------------------------------
 // LayerTransactionParent
 LayerTransactionParent::LayerTransactionParent(HostLayerManager* aManager,
                                                CompositorBridgeParentBase* aBridge,
+                                               CompositorAnimationStorage* aAnimStorage,
                                                uint64_t aId)
   : mLayerManager(aManager)
   , mCompositorBridge(aBridge)
+  , mAnimStorage(aAnimStorage)
   , mId(aId)
   , mChildEpoch(0)
   , mParentEpoch(0)
   , mPendingTransaction(0)
   , mDestroyed(false)
   , mIPCOpen(false)
 {
 }
 
 LayerTransactionParent::~LayerTransactionParent()
 {
 }
 
 void
-LayerTransactionParent::SetLayerManager(HostLayerManager* aLayerManager)
+LayerTransactionParent::SetLayerManager(HostLayerManager* aLayerManager, CompositorAnimationStorage* aAnimStorage)
 {
+  if (mDestroyed) {
+    return;
+  }
   mLayerManager = aLayerManager;
   for (auto iter = mLayerMap.Iter(); !iter.Done(); iter.Next()) {
     auto layer = iter.Data();
+    if (mAnimStorage &&
+        layer->GetCompositorAnimationsId()) {
+      mAnimStorage->ClearById(layer->GetCompositorAnimationsId());
+    }
     layer->AsHostLayer()->SetLayerManager(aLayerManager);
   }
+  mAnimStorage = aAnimStorage;
 }
 
 mozilla::ipc::IPCResult
 LayerTransactionParent::RecvShutdown()
 {
   Destroy();
   IProtocol* mgr = Manager();
   if (!Send__delete__(this)) {
@@ -96,17 +106,26 @@ LayerTransactionParent::RecvShutdownSync
 
 void
 LayerTransactionParent::Destroy()
 {
   if (mDestroyed) {
     return;
   }
   mDestroyed = true;
+  if (mAnimStorage) {
+    for (auto iter = mLayerMap.Iter(); !iter.Done(); iter.Next()) {
+      auto layer = iter.Data();
+      if (layer->GetCompositorAnimationsId()) {
+        mAnimStorage->ClearById(layer->GetCompositorAnimationsId());
+      }
+    }
+  }
   mCompositables.clear();
+  mAnimStorage = nullptr;
 }
 
 class MOZ_STACK_CLASS AutoLayerTransactionParentAsyncMessageSender
 {
 public:
   explicit AutoLayerTransactionParentAsyncMessageSender(LayerTransactionParent* aLayerTransaction,
                                                         const InfallibleTArray<OpDestroy>* aDestroyActors = nullptr)
     : mLayerTransaction(aLayerTransaction)
@@ -530,24 +549,20 @@ LayerTransactionParent::SetLayerAttribut
   if (LayerHandle maskLayer = common.maskLayer()) {
     layer->SetMaskLayer(AsLayer(maskLayer));
   } else {
     layer->SetMaskLayer(nullptr);
   }
   layer->SetCompositorAnimations(common.compositorAnimations());
   // Clean up the Animations by id in the CompositorAnimationStorage
   // if there are no active animations on the layer
-  if (layer->GetCompositorAnimationsId() &&
+  if (mAnimStorage &&
+      layer->GetCompositorAnimationsId() &&
       layer->GetAnimations().IsEmpty()) {
-    CompositorAnimationStorage* storage =
-      mCompositorBridge->GetAnimationStorage(GetId());
-
-    if (storage) {
-      storage->ClearById(layer->GetCompositorAnimationsId());
-    }
+    mAnimStorage->ClearById(layer->GetCompositorAnimationsId());
   }
   if (common.scrollMetadata() != layer->GetAllScrollMetadata()) {
     UpdateHitTestingTree(layer, "scroll metadata changed");
     layer->SetScrollMetadata(common.scrollMetadata());
   }
   layer->SetDisplayListLog(common.displayListLog().get());
 
   // The updated invalid region is added to the existing one, since we can
@@ -722,24 +737,21 @@ LayerTransactionParent::RecvGetAnimation
 {
   *aHasAnimationOpacity = false;
   if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) {
     return IPC_FAIL_NO_REASON(this);
   }
 
   mCompositorBridge->ApplyAsyncProperties(this);
 
-  CompositorAnimationStorage* storage =
-    mCompositorBridge->GetAnimationStorage(GetId());
-
-  if (!storage) {
+  if (!mAnimStorage) {
     return IPC_FAIL_NO_REASON(this);
   }
 
-  Maybe<float> opacity = storage->GetAnimationOpacity(aCompositorAnimationsId);
+  Maybe<float> opacity = mAnimStorage->GetAnimationOpacity(aCompositorAnimationsId);
   if (opacity) {
     *aOpacity = *opacity;
     *aHasAnimationOpacity = true;
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
@@ -751,24 +763,21 @@ LayerTransactionParent::RecvGetAnimation
   }
 
   // Make sure we apply the latest animation style or else we can end up with
   // a race between when we temporarily clear the animation transform (in
   // CompositorBridgeParent::SetShadowProperties) and when animation recalculates
   // the value.
   mCompositorBridge->ApplyAsyncProperties(this);
 
-  CompositorAnimationStorage* storage =
-    mCompositorBridge->GetAnimationStorage(GetId());
-
-  if (!storage) {
+  if (!mAnimStorage) {
     return IPC_FAIL_NO_REASON(this);
   }
 
-  Maybe<Matrix4x4> transform = storage->GetAnimationTransform(aCompositorAnimationsId);
+  Maybe<Matrix4x4> transform = mAnimStorage->GetAnimationTransform(aCompositorAnimationsId);
   if (transform) {
     *aTransform = *transform;
   } else {
     *aTransform = mozilla::void_t();
   }
   return IPC_OK();
 }
 
@@ -1003,16 +1012,20 @@ LayerTransactionParent::RecvNewComposita
 
 mozilla::ipc::IPCResult
 LayerTransactionParent::RecvReleaseLayer(const LayerHandle& aHandle)
 {
   RefPtr<Layer> layer;
   if (!aHandle || !mLayerMap.Remove(aHandle.Value(), getter_AddRefs(layer))) {
     return IPC_FAIL_NO_REASON(this);
   }
+  if (mAnimStorage &&
+      layer->GetCompositorAnimationsId()) {
+    mAnimStorage->ClearById(layer->GetCompositorAnimationsId());
+  }
   layer->Disconnect();
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 LayerTransactionParent::RecvReleaseCompositable(const CompositableHandle& aHandle)
 {
   ReleaseCompositable(aHandle);
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -28,42 +28,44 @@ class RenderFrameParent;
 } // namespace layout
 
 namespace layers {
 
 class Layer;
 class HostLayerManager;
 class ShadowLayerParent;
 class CompositableParent;
+class CompositorAnimationStorage;
 class CompositorBridgeParentBase;
 
 class LayerTransactionParent final : public PLayerTransactionParent,
                                      public CompositableParentManager,
                                      public ShmemAllocator
 {
   typedef mozilla::layout::RenderFrameParent RenderFrameParent;
   typedef InfallibleTArray<Edit> EditArray;
   typedef InfallibleTArray<OpDestroy> OpDestroyArray;
   typedef InfallibleTArray<PluginWindowData> PluginsArray;
   typedef InfallibleTArray<ReadLockInit> ReadLockArray;
 
 public:
   LayerTransactionParent(HostLayerManager* aManager,
                          CompositorBridgeParentBase* aBridge,
+                         CompositorAnimationStorage* aAnimStorage,
                          uint64_t aId);
 
 protected:
   ~LayerTransactionParent();
 
 public:
   void Destroy();
 
   HostLayerManager* layer_manager() const { return mLayerManager; }
 
-  void SetLayerManager(HostLayerManager* aLayerManager);
+  void SetLayerManager(HostLayerManager* aLayerManager, CompositorAnimationStorage* aAnimStorage);
 
   uint64_t GetId() const { return mId; }
   Layer* GetRoot() const { return mRoot; }
 
   uint64_t GetChildEpoch() const { return mChildEpoch; }
   bool ShouldParentObserveEpoch();
 
   virtual ShmemAllocator* AsShmemAllocator() override { return this; }
@@ -169,16 +171,17 @@ private:
   // testing tree changes are made.
   void UpdateHitTestingTree(Layer* aLayer, const char* aWhy) {
     mUpdateHitTestingTree = true;
   }
 
 private:
   RefPtr<HostLayerManager> mLayerManager;
   CompositorBridgeParentBase* mCompositorBridge;
+  RefPtr<CompositorAnimationStorage> mAnimStorage;
 
   // Hold the root because it might be grafted under various
   // containers in the "real" layer tree
   RefPtr<Layer> mRoot;
 
   // Mapping from LayerHandles to Layers.
   nsRefPtrHashtable<nsUint64HashKey, Layer> mLayerMap;
 
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -759,16 +759,20 @@ ShadowLayerForwarder::EndTransaction(con
     if (locks.Length()) {
       if (!mShadowManager->SendInitReadLocks(locks)) {
         MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending read locks failed!"));
         return false;
       }
     }
   }
 
+  // We delay at the last possible minute, to give the paint thread a chance to
+  // finish. If it does we don't have to delay messages at all.
+  GetCompositorBridgeChild()->PostponeMessagesIfAsyncPainting();
+
   MOZ_LAYERS_LOG(("[LayersForwarder] sending transaction..."));
   RenderTraceScope rendertrace3("Forward Transaction", "000093");
   if (!mShadowManager->SendUpdate(info)) {
     MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!"));
     return false;
   }
 
   if (startTime) {
--- a/gfx/layers/mlgpu/RenderPassMLGPU.cpp
+++ b/gfx/layers/mlgpu/RenderPassMLGPU.cpp
@@ -343,16 +343,20 @@ ShaderRenderPass::SetupPSBuffer0(float a
 
   MaskInformation cb(aOpacity, HasMask());
   return mDevice->GetSharedPSBuffer()->Allocate(&mPSBuffer0, cb);
 }
 
 void
 ShaderRenderPass::ExecuteRendering()
 {
+  if (mVertices.IsEmpty() && mInstances.IsEmpty()) {
+    return;
+  }
+
   mDevice->SetPSConstantBuffer(0, &mPSBuffer0);
   if (MaskOperation* mask = GetMask()) {
     mDevice->SetPSTexture(kMaskLayerTextureSlot, mask->GetTexture());
     mDevice->SetSamplerMode(kMaskSamplerSlot, SamplerMode::LinearClampToZero);
   }
 
   SetupPipeline();
 
@@ -876,16 +880,20 @@ RenderViewPass::AddToPass(LayerMLGPU* aL
 {
   // We bake in the layer ahead of time, which also guarantees the blend mode
   // is baked in, as well as the geometry requirement.
   if (mAssignedLayer != aLayer) {
     return false;
   }
 
   mSource = mAssignedLayer->GetRenderTarget();
+  if (!mSource) {
+    return false;
+  }
+
   mParentView = aInfo.view;
 
   Txn txn(this);
 
   IntPoint offset = mAssignedLayer->GetTargetOffset();
   IntSize size = mAssignedLayer->GetTargetSize();
 
   // Clamp the visible region to the texture size.
--- a/gfx/thebes/gfxFT2FontList.h
+++ b/gfx/thebes/gfxFT2FontList.h
@@ -122,32 +122,32 @@ class gfxFT2FontList : public gfxPlatfor
 {
 public:
     gfxFT2FontList();
     virtual ~gfxFT2FontList();
 
     virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
                                           uint16_t aWeight,
                                           int16_t aStretch,
-                                          uint8_t aStyle);
+                                          uint8_t aStyle) override;
 
     virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
                                            uint16_t aWeight,
                                            int16_t aStretch,
                                            uint8_t aStyle,
                                            const uint8_t* aFontData,
-                                           uint32_t aLength);
+                                           uint32_t aLength) override;
 
     void GetSystemFontList(InfallibleTArray<FontListEntry>* retValue);
 
     static gfxFT2FontList* PlatformFontList() {
         return static_cast<gfxFT2FontList*>(gfxPlatformFontList::PlatformFontList());
     }
 
-    virtual void GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily> >& aFamilyArray);
+    virtual void GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily> >& aFamilyArray) override;
 
     void WillShutdown();
 
 protected:
     typedef enum {
         kUnknown,
         kStandard
     } StandardFile;
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -580,16 +580,17 @@ private:
   DECL_GFX_PREF(Once, "layers.mlgpu.enable-clear-view",        AdvancedLayersEnableClearView, bool, true);
   DECL_GFX_PREF(Once, "layers.mlgpu.enable-cpu-occlusion",     AdvancedLayersEnableCPUOcclusion, bool, true);
   DECL_GFX_PREF(Once, "layers.mlgpu.enable-depth-buffer",      AdvancedLayersEnableDepthBuffer, bool, false);
   DECL_GFX_PREF(Live, "layers.mlgpu.enable-invalidation",      AdvancedLayersUseInvalidation, bool, true);
   DECL_GFX_PREF(Once, "layers.mlgpu.enable-on-windows7",       AdvancedLayersEnableOnWindows7, bool, false);
   DECL_GFX_PREF(Once, "layers.mlgpu.enable-container-resizing", AdvancedLayersEnableContainerResizing, bool, true);
   DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.force-disabled", LayersOffMainThreadCompositionForceDisabled, bool, false);
   DECL_GFX_PREF(Live, "layers.offmainthreadcomposition.frame-rate", LayersCompositionFrameRate, int32_t,-1);
+  DECL_GFX_PREF(Live, "layers.omtp.force-sync",                LayersOMTPForceSync, bool, true);
   DECL_GFX_PREF(Live, "layers.orientation.sync.timeout",       OrientationSyncMillis, uint32_t, (uint32_t)0);
   DECL_GFX_PREF(Once, "layers.prefer-opengl",                  LayersPreferOpenGL, bool, false);
   DECL_GFX_PREF(Live, "layers.progressive-paint",              ProgressivePaint, bool, false);
   DECL_GFX_PREF(Live, "layers.shared-buffer-provider.enabled", PersistentBufferProviderSharedEnabled, bool, false);
   DECL_GFX_PREF(Live, "layers.single-tile.enabled",            LayersSingleTileEnabled, bool, true);
   DECL_GFX_PREF(Once, "layers.stereo-video.enabled",           StereoVideoEnabled, bool, false);
   DECL_GFX_PREF(Live, "layers.force-synchronous-resize",       LayersForceSynchronousResize, bool, false);
 
--- a/image/imgLoader.h
+++ b/image/imgLoader.h
@@ -536,17 +536,17 @@ class imgCacheValidator : public nsIStre
 {
 public:
   imgCacheValidator(nsProgressNotificationProxy* progress, imgLoader* loader,
                     imgRequest* aRequest, nsISupports* aContext,
                     bool forcePrincipalCheckForCacheEntry);
 
   void AddProxy(imgRequestProxy* aProxy);
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSICHANNELEVENTSINK
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
 
 private:
--- a/ipc/mscom/MainThreadRuntime.cpp
+++ b/ipc/mscom/MainThreadRuntime.cpp
@@ -1,21 +1,23 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 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/mscom/MainThreadRuntime.h"
 
+#if defined(ACCESSIBILITY)
+#include "mozilla/a11y/Compatibility.h"
+#endif
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
-#include "mozilla/WindowsVersion.h"
 #include "nsWindowsHelpers.h"
 #include "nsXULAppAPI.h"
 
 #include <accctrl.h>
 #include <aclapi.h>
 #include <objbase.h>
 #include <objidl.h>
 
@@ -29,48 +31,25 @@ struct LocalFreeDeleter
   }
 };
 
 } // anonymous namespace
 
 // This API from oleaut32.dll is not declared in Windows SDK headers
 extern "C" void __cdecl SetOaNoCache(void);
 
-#if defined(ACCESSIBILITY)
-static WORD
-GetActCtxResourceId()
-{
-  // The manifest for 32-bit Windows is embedded with resource ID 32.
-  // The manifest for 64-bit Windows is embedded with resource ID 64.
-  // Beginning with Windows 10 Creators Update, 32-bit builds use the 64-bit
-  // manifest.
-  WORD actCtxResourceId;
-#if defined(HAVE_64BIT_BUILD)
-  actCtxResourceId = 64;
-#else
-  if (mozilla::IsWin10CreatorsUpdateOrLater()) {
-    actCtxResourceId = 64;
-  } else {
-    actCtxResourceId = 32;
-  }
-#endif // defined(HAVE_64BIT_BUILD)
-
-  return actCtxResourceId;
-}
-#endif // defined(ACCESSIBILITY)
-
 namespace mozilla {
 namespace mscom {
 
 MainThreadRuntime* MainThreadRuntime::sInstance = nullptr;
 
 MainThreadRuntime::MainThreadRuntime()
   : mInitResult(E_UNEXPECTED)
 #if defined(ACCESSIBILITY)
-  , mActCtxRgn(::GetActCtxResourceId())
+  , mActCtxRgn(a11y::Compatibility::GetActCtxResourceId())
 #endif // defined(ACCESSIBILITY)
 {
   // We must be the outermost COM initialization on this thread. The COM runtime
   // cannot be configured once we start manipulating objects
   MOZ_ASSERT(mStaRegion.IsValidOutermost());
   if (NS_WARN_IF(!mStaRegion.IsValidOutermost())) {
     return;
   }
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/coverage/getLcovInfo_twice.js
@@ -0,0 +1,2 @@
+getLcovInfo();
+getLcovInfo();
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -7164,19 +7164,16 @@ PresShell::HandleEvent(nsIFrame* aFrame,
   }
 #endif
 
   NS_ASSERTION(aFrame, "aFrame should be not null");
 
   // Update the latest focus sequence number with this new sequence number
   if (mAPZFocusSequenceNumber < aEvent->mFocusSequenceNumber) {
     mAPZFocusSequenceNumber = aEvent->mFocusSequenceNumber;
-
-    // Schedule an empty transaction to transmit this focus update
-    aFrame->SchedulePaint(nsIFrame::PAINT_COMPOSITE_ONLY);
   }
 
   if (sPointerEventEnabled) {
     AutoWeakFrame weakFrame(aFrame);
     nsCOMPtr<nsIContent> targetContent;
     DispatchPointerFromMouseOrTouch(this, aFrame, aEvent, aDontRetargetEvents,
                                     aEventStatus,
                                     getter_AddRefs(targetContent));
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -852,18 +852,20 @@ AddAndRemoveImageAssociations(nsFrame* a
       if (i >= aNewLayers->mImageCount ||
           !aOldLayers->mLayers[i].mImage.ImageDataEquals(
             aNewLayers->mLayers[i].mImage)) {
         const nsStyleImage& oldImage = aOldLayers->mLayers[i].mImage;
         if (oldImage.GetType() != eStyleImageType_Image) {
           continue;
         }
 
-        if (imgRequestProxy* req = oldImage.GetImageData()) {
-          imageLoader->DisassociateRequestFromFrame(req, aFrame);
+        if (aFrame->HasImageRequest()) {
+          if (imgRequestProxy* req = oldImage.GetImageData()) {
+            imageLoader->DisassociateRequestFromFrame(req, aFrame);
+          }
         }
       }
     }
   }
 
   NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, (*aNewLayers)) {
     // If there is an image in newBG that's not in oldBG, add it.
     if (!aOldLayers || i >= aOldLayers->mImageCount ||
@@ -967,17 +969,17 @@ nsFrame::DidSetStyleContext(nsStyleConte
   // we'll never know that it's finished loading.  Likewise, we want to
   // do this for freshly-created frames to prevent a similar race if the
   // image loads between reflow (which can depend on whether the image
   // is loaded) and paint.  We also don't really care about any callers
   // who try to paint borders with a different style context, because
   // they won't have the correct size for the border either.
   if (oldBorderImage != newBorderImage) {
     // stop and restart the image loading/notification
-    if (oldBorderImage) {
+    if (oldBorderImage && HasImageRequest()) {
       imageLoader->DisassociateRequestFromFrame(oldBorderImage, this);
     }
     if (newBorderImage) {
       imageLoader->AssociateRequestToFrame(newBorderImage, this);
     }
   }
 
   // If the page contains markup that overrides text direction, and
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -4744,16 +4744,17 @@ nsGridContainerFrame::Tracks::AlignJusti
       break;
     case NS_STYLE_ALIGN_SPACE_EVENLY:
       roundingError = NSCoordDivRem(space, mSizes.Length() + 1, &between);
       pos = between;
       break;
     default:
       MOZ_ASSERT_UNREACHABLE("unknown align-/justify-content value");
       between = 0; // just to avoid a compiler warning
+      roundingError = 0; // just to avoid a compiler warning
   }
   between += mGridGap;
   for (TrackSize& sz : mSizes) {
     sz.mPosition = pos;
     nscoord spacing = between;
     if (roundingError) {
       roundingError -= 1;
       spacing += 1;
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -5132,18 +5132,17 @@ nsDisplayText::nsDisplayText(nsDisplayLi
     // a layer here. We have to deal with the problem that the ScreenReferenceDrawTarget
     // might not be compatible with the DT used for layer rendering.
 
     GlyphArray* g = mGlyphs.AppendElement();
     std::vector<Glyph> glyphs;
     Color color;
     if (!capture->ContainsOnlyColoredGlyphs(mFont, color, glyphs)
         || !mFont
-        || !mFont->CanSerialize()
-        || XRE_IsParentProcess()) {
+        || !mFont->CanSerialize()) {
       mFont = nullptr;
       mGlyphs.Clear();
     } else {
       g->glyphs().SetLength(glyphs.size());
       PodCopy(g->glyphs().Elements(), glyphs.data(), glyphs.size());
       g->color() = color;
     }
   }
--- a/layout/style/RuleNodeCacheConditions.h
+++ b/layout/style/RuleNodeCacheConditions.h
@@ -90,16 +90,21 @@ public:
              eHaveWritingMode;
   }
 
   void SetUncacheable()
   {
     mBits |= eUncacheable;
   }
 
+  void Clear()
+  {
+    *this = RuleNodeCacheConditions();
+  }
+
   bool Cacheable() const
   {
     return !(mBits & eUncacheable);
   }
 
   bool CacheableWithDependencies() const
   {
     return !(mBits & eUncacheable) &&
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -2673,16 +2673,52 @@ nsRuleNode::WalkRuleTree(const nsStyleSt
   if (!highestNode)
     highestNode = rootNode;
 
   MOZ_ASSERT(!(aSID == eStyleStruct_Variables && startStruct),
              "if we start caching Variables structs in the rule tree, then "
              "not forcing detail to eRulePartialMixed just below is no "
              "longer valid");
 
+  if (detail == eRuleNone && isReset) {
+    // We specified absolutely no rule information for a reset struct, and we
+    // may or may not have found a parent rule in the tree that specified all
+    // the rule information.  Regardless, we don't need to use any cache
+    // conditions if we cache this struct in the rule tree.
+    //
+    // Normally ruleData.mConditions would already indicate that the struct
+    // is cacheable without conditions if detail is eRuleNone, but because
+    // of the UnsetPropertiesWithoutFlags call above, we may have encountered
+    // some rules with dependencies, which we then cleared out of ruleData.
+    //
+    // ruleData.mConditions could also indicate we are not cacheable at all,
+    // such as when AnimValuesStyleRule prevents us from caching structs
+    // when attempting to apply animations to pseudos.
+    //
+    // So if we we are uncacheable, we leave it, but if we are cacheable
+    // with dependencies, we convert that to cacheable without dependencies.
+    if (ruleData.mConditions.CacheableWithDependencies()) {
+      MOZ_ASSERT(pseudoRestriction,
+                 "should only be cacheable with dependencies if we had a "
+                 "pseudo restriction");
+      ruleData.mConditions.Clear();
+    } else {
+      // XXXheycam We shouldn't have `|| GetLevel() == SheetType::Transition`
+      // in the assertion condition, but rule nodes created by
+      // ResolveStyleByAddingRules don't call SetIsAnimationRule().
+      MOZ_ASSERT(ruleData.mConditions.CacheableWithoutDependencies() ||
+                 ((HasAnimationData() ||
+                   GetLevel() == SheetType::Transition) &&
+                  aContext->GetParent() &&
+                  aContext->GetParent()->HasPseudoElementData()),
+                 "should only be uncacheable if we had an animation rule "
+                 "and we're inside a pseudo");
+    }
+  }
+
   if (!ruleData.mConditions.CacheableWithoutDependencies() &&
       aSID != eStyleStruct_Variables) {
     // Treat as though some data is specified to avoid the optimizations and
     // force data computation.
     //
     // We don't need to do this for Variables structs since we know those are
     // never cached in the rule tree, and it avoids wasteful computation of a
     // new Variables struct when we have no additional variable declarations,
--- a/layout/style/nsRuleNode.h
+++ b/layout/style/nsRuleNode.h
@@ -188,30 +188,35 @@ private:
   void* GetConditionalStyleData(nsStyleStructID aSID,
                                 mozilla::GeckoStyleContext* aStyleContext) const;
 
 public:
   void SetStyleData(nsStyleStructID aSID, void* aStyleStruct) {
     MOZ_ASSERT(!(mConditionalBits & GetBitForSID(aSID)),
                "rule node should not have unconditional and conditional style "
                "data for a given struct");
+    mConditionalBits &= ~GetBitForSID(aSID);
     mEntries[aSID] = aStyleStruct;
   }
 
   void SetStyleData(nsStyleStructID aSID,
                     nsPresContext* aPresContext,
                     void* aStyleStruct,
                     const mozilla::RuleNodeCacheConditions& aConditions) {
-    MOZ_ASSERT((mConditionalBits & GetBitForSID(aSID)) ||
-               !mEntries[aSID],
-               "rule node should not have unconditional and conditional style "
-               "data for a given struct");
+    if (!(mConditionalBits & GetBitForSID(aSID))) {
+      MOZ_ASSERT(!mEntries[aSID],
+                 "rule node should not have unconditional and conditional "
+                 "style data for a given struct");
+      mEntries[aSID] = nullptr;
+    }
+
     MOZ_ASSERT(aConditions.CacheableWithDependencies(),
                "don't call SetStyleData with a cache key that has no "
                "conditions or is uncacheable");
+
 #ifdef DEBUG
     for (Entry* e = static_cast<Entry*>(mEntries[aSID]); e; e = e->mNext) {
       NS_WARNING_ASSERTION(e->mConditions != aConditions,
                            "wasteful to have duplicate conditional style data");
     }
 #endif
 
     mConditionalBits |= GetBitForSID(aSID);
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -3346,17 +3346,17 @@ var DesktopUserAgent = {
 
 
 function nsBrowserAccess() {
 }
 
 nsBrowserAccess.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserDOMWindow]),
 
-  _getBrowser: function _getBrowser(aURI, aOpener, aWhere, aFlags) {
+  _getBrowser: function _getBrowser(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
     let isExternal = !!(aFlags & Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
     if (isExternal && aURI && aURI.schemeIs("chrome"))
       return null;
 
     let loadflags = isExternal ?
                       Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL :
                       Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
     if (aWhere == Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW) {
@@ -3422,44 +3422,49 @@ nsBrowserAccess.prototype = {
       // BrowserApp.addTab calls loadURIWithFlags with the appropriate params
       let tab = BrowserApp.addTab(aURI ? aURI.spec : "about:blank", { flags: loadflags,
                                                                       referrerURI: referrer,
                                                                       external: isExternal,
                                                                       parentId: parentId,
                                                                       opener: openerWindow,
                                                                       selected: true,
                                                                       isPrivate: isPrivate,
-                                                                      pinned: pinned });
+                                                                      pinned: pinned,
+                                                                      triggeringPrincipal: aTriggeringPrincipal});
 
       return tab.browser;
     }
 
     // OPEN_CURRENTWINDOW and illegal values
     let browser = BrowserApp.selectedBrowser;
     if (aURI && browser) {
-      browser.loadURIWithFlags(aURI.spec, loadflags, referrer, null, null);
+      browser.loadURIWithFlags(aURI.spec, {
+        flags: loadflags,
+        referrerURI: referrer,
+        triggeringPrincipal: aTriggeringPrincipal,
+      });
     }
 
     return browser;
   },
 
-  openURI: function browser_openURI(aURI, aOpener, aWhere, aFlags) {
-    let browser = this._getBrowser(aURI, aOpener, aWhere, aFlags);
+  openURI: function browser_openURI(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
+    let browser = this._getBrowser(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal);
     return browser ? browser.contentWindow : null;
   },
 
   openURIInFrame: function browser_openURIInFrame(aURI, aParams, aWhere, aFlags,
                                                   aNextTabParentId, aName) {
     // We currently ignore aNextTabParentId on mobile.  This needs to change
     // when Fennec starts to support e10s.  Assertions will fire if this code
     // isn't fixed by then.
     //
     // We also ignore aName if it is set, as it is currently only used on the
     // e10s codepath.
-    let browser = this._getBrowser(aURI, null, aWhere, aFlags);
+    let browser = this._getBrowser(aURI, null, aWhere, aFlags, null);
     if (browser)
       return browser.QueryInterface(Ci.nsIFrameLoaderOwner);
     return null;
   },
 
   isTabContentWindow: function(aWindow) {
     return BrowserApp.getBrowserForWindow(aWindow) != null;
   },
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -3157,19 +3157,16 @@ pref("dom.ipc.plugins.flash.disable-prot
 
 pref("dom.ipc.plugins.flash.subprocess.crashreporter.enabled", true);
 pref("dom.ipc.plugins.reportCrashURL", true);
 
 // How long we wait before unloading an idle plugin process.
 // Defaults to 30 seconds.
 pref("dom.ipc.plugins.unloadTimeoutSecs", 30);
 
-// Asynchronous plugin initialization is on hold.
-pref("dom.ipc.plugins.asyncInit.enabled", false);
-
 // Allow Flash async drawing mode in 64-bit release builds
 pref("dom.ipc.plugins.asyncdrawing.enabled", true);
 // Force the accelerated direct path for a subset of Flash wmode values
 pref("dom.ipc.plugins.forcedirect.enabled", true);
 
 // Enable multi by default for Nightly and DevEdition only.
 // For Beta and Release builds, multi is controlled by the e10srollout addon.
 #if defined(RELEASE_OR_BETA) && !defined(MOZ_DEV_EDITION)
--- a/mozglue/build/WindowsDllBlocklist.cpp
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -774,48 +774,16 @@ continue_loading:
   // Prevent the stack walker from suspending this thread when LdrLoadDll
   // holds the RtlLookupFunctionEntry lock.
   AutoSuppressStackWalking suppress;
 #endif
 
   return stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
 }
 
-#ifdef _M_AMD64
-typedef NTSTATUS (NTAPI *LdrUnloadDll_func)(HMODULE module);
-static LdrUnloadDll_func stub_LdrUnloadDll;
-
-static NTSTATUS NTAPI
-patched_LdrUnloadDll(HMODULE module)
-{
-  // Prevent the stack walker from suspending this thread when LdrUnloadDll
-  // holds the RtlLookupFunctionEntry lock.
-  AutoSuppressStackWalking suppress;
-  return stub_LdrUnloadDll(module);
-}
-
-// These pointers are disguised as PVOID to avoid pulling in obscure headers
-typedef PVOID (WINAPI *LdrResolveDelayLoadedAPI_func)(PVOID ParentModuleBase,
-  PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
-  PVOID ThunkAddress, ULONG Flags);
-static LdrResolveDelayLoadedAPI_func stub_LdrResolveDelayLoadedAPI;
-
-static PVOID WINAPI patched_LdrResolveDelayLoadedAPI(PVOID ParentModuleBase,
-  PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
-  PVOID ThunkAddress, ULONG Flags)
-{
-  // Prevent the stack walker from suspending this thread when
-  // LdrResolveDelayLoadAPI holds the RtlLookupFunctionEntry lock.
-  AutoSuppressStackWalking suppress;
-  return stub_LdrResolveDelayLoadedAPI(ParentModuleBase, DelayloadDescriptor,
-                                       FailureDllHook, FailureSystemHook,
-                                       ThunkAddress, Flags);
-}
-#endif
-
 #ifdef _M_IX86
 static bool
 ShouldBlockThread(void* aStartAddress)
 {
   // Allows crashfirefox.exe to continue to work. Also if your threadproc is null, this crash is intentional.
   if (aStartAddress == 0)
     return false;
 
@@ -885,24 +853,16 @@ DllBlocklist_Initialize(uint32_t aInitFl
 #ifdef DEBUG
     printf_stderr("LdrLoadDll hook failed, no dll blocklisting active\n");
 #endif
   }
 
   Kernel32Intercept.Init("kernel32.dll");
 
 #ifdef _M_AMD64
-  NtDllIntercept.AddHook("LdrUnloadDll",
-                         reinterpret_cast<intptr_t>(patched_LdrUnloadDll),
-                         (void**)&stub_LdrUnloadDll);
-  if (IsWin8OrLater()) { // LdrResolveDelayLoadedAPI was introduced in Win8
-    NtDllIntercept.AddHook("LdrResolveDelayLoadedAPI",
-                           reinterpret_cast<intptr_t>(patched_LdrResolveDelayLoadedAPI),
-                           (void**)&stub_LdrResolveDelayLoadedAPI);
-  }
   if (!IsWin8OrLater()) {
     // The crash that this hook works around is only seen on Win7.
     Kernel32Intercept.AddHook("RtlInstallFunctionTableCallback",
                               reinterpret_cast<intptr_t>(patched_RtlInstallFunctionTableCallback),
                               (void**)&stub_RtlInstallFunctionTableCallback);
   }
 #endif
 
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -1593,36 +1593,38 @@ HttpChannelChild::SetupRedirect(nsIURI* 
   mRedirectChannelChild = do_QueryInterface(newChannel);
   newChannel.forget(outChannel);
 
   return NS_OK;
 }
 
 void
 HttpChannelChild::Redirect1Begin(const uint32_t& registrarId,
-                                 const URIParams& newUri,
+                                 const URIParams& newOriginalURI,
                                  const uint32_t& redirectFlags,
                                  const nsHttpResponseHead& responseHead,
                                  const nsACString& securityInfoSerialization,
                                  const uint64_t& channelId)
 {
+  nsresult rv;
+
   LOG(("HttpChannelChild::Redirect1Begin [this=%p]\n", this));
 
-  nsCOMPtr<nsIURI> uri = DeserializeURI(newUri);
+  nsCOMPtr<nsIURI> uri = DeserializeURI(newOriginalURI);
 
   if (!securityInfoSerialization.IsEmpty()) {
     NS_DeserializeObject(securityInfoSerialization,
                          getter_AddRefs(mSecurityInfo));
   }
 
   nsCOMPtr<nsIChannel> newChannel;
-  nsresult rv = SetupRedirect(uri,
-                              &responseHead,
-                              redirectFlags,
-                              getter_AddRefs(newChannel));
+  rv = SetupRedirect(uri,
+                      &responseHead,
+                      redirectFlags,
+                      getter_AddRefs(newChannel));
 
   if (NS_SUCCEEDED(rv)) {
     if (mRedirectChannelChild) {
       // Set the channelId allocated in parent to the child instance
       nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mRedirectChannelChild);
       if (httpChannel) {
         rv = httpChannel->SetChannelId(channelId);
         MOZ_ASSERT(NS_SUCCEEDED(rv));
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -1749,39 +1749,46 @@ HttpChannelParent::Delete()
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpChannelParent::StartRedirect(uint32_t registrarId,
                                  nsIChannel* newChannel,
                                  uint32_t redirectFlags,
                                  nsIAsyncVerifyRedirectCallback* callback)
 {
+  nsresult rv;
+
   LOG(("HttpChannelParent::StartRedirect [this=%p, registrarId=%" PRIu32 " "
        "newChannel=%p callback=%p]\n", this, registrarId, newChannel,
        callback));
 
   if (mIPCClosed)
     return NS_BINDING_ABORTED;
 
-  nsCOMPtr<nsIURI> newURI;
-  newChannel->GetURI(getter_AddRefs(newURI));
+  // Sending down the original URI, because that is the URI we have
+  // to construct the channel from - this is the URI we've been actually
+  // redirected to.  URI of the channel may be an inner channel URI.
+  // URI of the channel will be reconstructed by the protocol handler
+  // on the child process, no need to send it then.
+  nsCOMPtr<nsIURI> newOriginalURI;
+  newChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
 
   URIParams uriParams;
-  SerializeURI(newURI, uriParams);
+  SerializeURI(newOriginalURI, uriParams);
 
   nsCString secInfoSerialization;
   UpdateAndSerializeSecurityInfo(secInfoSerialization);
 
   // If the channel is a HTTP channel, we also want to inform the child
   // about the parent's channelId attribute, so that both parent and child
   // share the same ID. Useful for monitoring channel activity in devtools.
   uint64_t channelId;
   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
   if (httpChannel) {
-    nsresult rv = httpChannel->GetChannelId(&channelId);
+    rv = httpChannel->GetChannelId(&channelId);
     NS_ENSURE_SUCCESS(rv, NS_BINDING_ABORTED);
   }
 
   nsHttpResponseHead *responseHead = mChannel->GetResponseHead();
   bool result = false;
   if (!mIPCClosed) {
     result = SendRedirect1Begin(registrarId, uriParams, redirectFlags,
                                 responseHead ? *responseHead
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -112,17 +112,17 @@ child:
 
   // Used to cancel child channel if we hit errors during creating and
   // AsyncOpen of nsHttpChannel on the parent.
   async FailedAsyncOpen(nsresult status);
 
   // Called to initiate content channel redirect, starts talking to sinks
   // on the content process and reports result via Redirect2Verify above
   async Redirect1Begin(uint32_t           registrarId,
-                       URIParams          newUri,
+                       URIParams          newOriginalUri,
                        uint32_t           redirectFlags,
                        nsHttpResponseHead responseHead,
                        nsCString          securityInfoSerialization,
                        uint64_t           channelId,
                        NetAddr            oldPeerAddr);
 
   // Called if redirect successful so that child can complete setup.
   async Redirect3Complete();
--- a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc
+++ b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc
@@ -78,17 +78,21 @@ DWORD CreateRestrictedToken(TokenLevel s
       restricted_token.AddRestrictingSidLogonSession();
       break;
     }
     case USER_LIMITED: {
       sid_exceptions.push_back(WinBuiltinUsersSid);
       sid_exceptions.push_back(WinWorldSid);
       sid_exceptions.push_back(WinInteractiveSid);
       privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME);
-      restricted_token.AddUserSidForDenyOnly();
+      // This breaks web audio, so we don't want to do this in the restricting
+      // SIDs (normal) case. See bug 1378061.
+      if (!gUseRestricting) {
+        restricted_token.AddUserSidForDenyOnly();
+      }
       restricted_token.AddRestrictingSid(WinBuiltinUsersSid);
       restricted_token.AddRestrictingSid(WinWorldSid);
       restricted_token.AddRestrictingSid(WinRestrictedCodeSid);
 
       // This token has to be able to create objects in BNO.
       // Unfortunately, on Vista+, it needs the current logon sid
       // in the token to achieve this. You should also set the process to be
       // low integrity level so it can't access object created by other
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win32_clang.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_win32_clang.py
@@ -65,14 +65,14 @@ config = {
         'MSYSTEM': 'MINGW32',
     },
     'upload_env': {
         'UPLOAD_HOST': 'localhost',
         'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win32\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps',
+        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'src_mozconfig': 'browser\\config\\mozconfigs\\win32\\clang',
     'artifact_flag_build_variant_in_try': None,
     #########################################################################
 }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win32_clang_debug.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_win32_clang_debug.py
@@ -67,14 +67,14 @@ config = {
         'MSYSTEM': 'MINGW32',
     },
     'upload_env': {
         'UPLOAD_HOST': 'localhost',
         'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win32\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps',
+        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'src_mozconfig': 'browser\\config\\mozconfigs\\win32\\clang-debug',
     'artifact_flag_build_variant_in_try': None,
     #########################################################################
 }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win32_noopt_debug.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_win32_noopt_debug.py
@@ -69,14 +69,14 @@ config = {
         'MSYSTEM': 'MINGW32',
     },
     'upload_env': {
         'UPLOAD_HOST': 'localhost',
         'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win32\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps',
+        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'src_mozconfig': 'browser\\config\\mozconfigs\\win32\\noopt-debug',
     'artifact_flag_build_variant_in_try': None,
     #########################################################################
 }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win64_asan_debug.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_win64_asan_debug.py
@@ -63,13 +63,13 @@ config = {
         'MSYSTEM': 'MINGW32',
     },
     'upload_env': {
         'UPLOAD_HOST': 'localhost',
         'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps',
+        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'src_mozconfig': 'browser\\config\\mozconfigs\\win64\\debug-asan',
     #########################################################################
 }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win64_asan_opt.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_win64_asan_opt.py
@@ -61,13 +61,13 @@ config = {
         'MSYSTEM': 'MINGW32',
     },
     'upload_env': {
         'UPLOAD_HOST': 'localhost',
         'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps',
+        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'src_mozconfig': 'browser\\config\\mozconfigs\\win64\\nightly-asan',
     #########################################################################
 }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win64_clang.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_win64_clang.py
@@ -61,14 +61,14 @@ config = {
         'MSYSTEM': 'MINGW32',
     },
     'upload_env': {
         'UPLOAD_HOST': 'localhost',
         'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps',
+        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'src_mozconfig': 'browser\\config\\mozconfigs\\win64\\clang',
     'artifact_flag_build_variant_in_try': None,
     #########################################################################
 }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win64_clang_debug.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_win64_clang_debug.py
@@ -63,14 +63,14 @@ config = {
         'MSYSTEM': 'MINGW32',
     },
     'upload_env': {
         'UPLOAD_HOST': 'localhost',
         'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps',
+        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'src_mozconfig': 'browser\\config\\mozconfigs\\win64\\clang-debug',
     'artifact_flag_build_variant_in_try': None,
     #########################################################################
 }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win64_noopt_debug.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_win64_noopt_debug.py
@@ -63,14 +63,14 @@ config = {
         'MSYSTEM': 'MINGW32',
     },
     'upload_env': {
         'UPLOAD_HOST': 'localhost',
         'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps',
+        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'src_mozconfig': 'browser\\config\\mozconfigs\\win64\\noopt-debug',
     'artifact_flag_build_variant_in_try': None,
     #########################################################################
 }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_addondevel.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_addondevel.py
@@ -65,13 +65,13 @@ config = {
         'MSYSTEM': 'MINGW32',
     },
     'upload_env': {
         'UPLOAD_HOST': 'localhost',
         'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win32\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps',
+        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'src_mozconfig': 'browser/config/mozconfigs/win32/add-on-devel',
     #########################################################################
 }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_debug.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_debug.py
@@ -67,13 +67,13 @@ config = {
         'MSYSTEM': 'MINGW32',
     },
     'upload_env': {
         'UPLOAD_HOST': 'localhost',
         'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win32\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps',
+        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'src_mozconfig': 'browser\\config\\mozconfigs\\win32\\debug',
     #########################################################################
 }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_opt.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_opt.py
@@ -65,13 +65,13 @@ config = {
         'MSYSTEM': 'MINGW32',
     },
     'upload_env': {
         'UPLOAD_HOST': 'localhost',
         'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win32\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps',
+        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'src_mozconfig': 'browser\\config\\mozconfigs\\win32\\nightly',
     #########################################################################
 }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_addondevel.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_addondevel.py
@@ -62,13 +62,13 @@ config = {
         'MSYSTEM': 'MINGW32',
     },
     'upload_env': {
         'UPLOAD_HOST': 'localhost',
         'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps',
+        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'src_mozconfig': 'browser/config/mozconfigs/win64/add-on-devel',
     #########################################################################
 }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_debug.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_debug.py
@@ -63,13 +63,13 @@ config = {
         'MSYSTEM': 'MINGW32',
     },
     'upload_env': {
         'UPLOAD_HOST': 'localhost',
         'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps',
+        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'src_mozconfig': 'browser\\config\\mozconfigs\\win64\\debug',
     #########################################################################
 }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_opt.py
+++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_opt.py
@@ -61,13 +61,13 @@ config = {
         'MSYSTEM': 'MINGW32',
     },
     'upload_env': {
         'UPLOAD_HOST': 'localhost',
         'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     "check_test_env": {
         'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe',
-        'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps',
+        'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'),
     },
     'src_mozconfig': 'browser\\config\\mozconfigs\\win64\\nightly',
     #########################################################################
 }
--- a/toolkit/components/telemetry/TelemetryEnvironment.jsm
+++ b/toolkit/components/telemetry/TelemetryEnvironment.jsm
@@ -182,17 +182,16 @@ const DEFAULT_ENVIRONMENT_PREFS = new Ma
   ["browser.startup.homepage", {what: RECORD_PREF_STATE}],
   ["browser.startup.page", {what: RECORD_PREF_VALUE}],
   ["toolkit.cosmeticAnimations.enabled", {what: RECORD_PREF_VALUE}],
   ["browser.urlbar.suggest.searches", {what: RECORD_PREF_VALUE}],
   ["browser.urlbar.userMadeSearchSuggestionsChoice", {what: RECORD_PREF_VALUE}],
   ["devtools.chrome.enabled", {what: RECORD_PREF_VALUE}],
   ["devtools.debugger.enabled", {what: RECORD_PREF_VALUE}],
   ["devtools.debugger.remote-enabled", {what: RECORD_PREF_VALUE}],
-  ["dom.ipc.plugins.asyncInit.enabled", {what: RECORD_PREF_VALUE}],
   ["dom.ipc.plugins.enabled", {what: RECORD_PREF_VALUE}],
   ["dom.ipc.processCount", {what: RECORD_PREF_VALUE}],
   ["dom.max_script_run_time", {what: RECORD_PREF_VALUE}],
   ["experiments.manifest.uri", {what: RECORD_PREF_VALUE}],
   ["extensions.allow-non-mpc-extensions", {what: RECORD_PREF_VALUE}],
   ["extensions.autoDisableScopes", {what: RECORD_PREF_VALUE}],
   ["extensions.enabledScopes", {what: RECORD_PREF_VALUE}],
   ["extensions.blocklist.enabled", {what: RECORD_PREF_VALUE}],
--- a/toolkit/components/telemetry/TelemetrySession.jsm
+++ b/toolkit/components/telemetry/TelemetrySession.jsm
@@ -53,17 +53,16 @@ const MS_IN_ONE_HOUR  = 60 * 60 * 1000;
 const MIN_SUBSESSION_LENGTH_MS = Preferences.get("toolkit.telemetry.minSubsessionLength", 5 * 60) * 1000;
 
 const LOGGER_NAME = "Toolkit.Telemetry";
 const LOGGER_PREFIX = "TelemetrySession" + (Utils.isContentProcess ? "#content::" : "::");
 
 const PREF_BRANCH = "toolkit.telemetry.";
 const PREF_PREVIOUS_BUILDID = PREF_BRANCH + "previousBuildID";
 const PREF_FHR_UPLOAD_ENABLED = "datareporting.healthreport.uploadEnabled";
-const PREF_ASYNC_PLUGIN_INIT = "dom.ipc.plugins.asyncInit.enabled";
 const PREF_UNIFIED = PREF_BRANCH + "unified";
 const PREF_SHUTDOWN_PINGSENDER = PREF_BRANCH + "shutdownPingSender.enabled";
 
 const MESSAGE_TELEMETRY_PAYLOAD = "Telemetry:Payload";
 const MESSAGE_TELEMETRY_THREAD_HANGS = "Telemetry:ChildThreadHangs";
 const MESSAGE_TELEMETRY_GET_CHILD_THREAD_HANGS = "Telemetry:GetChildThreadHangs";
 const MESSAGE_TELEMETRY_USS = "Telemetry:USS";
 const MESSAGE_TELEMETRY_GET_CHILD_USS = "Telemetry:GetChildUSS";
@@ -1069,17 +1068,16 @@ var Impl = {
   getMetadata: function getMetadata(reason) {
     const sessionStartDate = Utils.toLocalTimeISOString(Utils.truncateToHours(this._sessionStartDate));
     const subsessionStartDate = Utils.toLocalTimeISOString(Utils.truncateToHours(this._subsessionStartDate));
     const monotonicNow = Policy.monotonicNow();
 
     let ret = {
       reason,
       revision: AppConstants.SOURCE_REVISION_URL,
-      asyncPluginInit: Preferences.get(PREF_ASYNC_PLUGIN_INIT, false),
 
       // Date.getTimezoneOffset() unintuitively returns negative values if we are ahead of
       // UTC and vice versa (e.g. -60 for UTC+1). We invert the sign here.
       timezoneOffset: -this._subsessionStartDate.getTimezoneOffset(),
       previousBuildId: this._previousBuildId,
 
       sessionId: this._sessionId,
       subsessionId: this._subsessionId,
@@ -1170,27 +1168,35 @@ var Impl = {
     if (!Telemetry.canRecordExtended) {
       return;
     }
 
     b("MEMORY_VSIZE", "vsize");
     b("MEMORY_VSIZE_MAX_CONTIGUOUS", "vsizeMaxContiguous");
     b("MEMORY_RESIDENT_FAST", "residentFast");
     b("MEMORY_UNIQUE", "residentUnique");
-    b("MEMORY_HEAP_ALLOCATED", "heapAllocated");
     p("MEMORY_HEAP_OVERHEAD_FRACTION", "heapOverheadFraction");
     b("MEMORY_JS_GC_HEAP", "JSMainRuntimeGCHeap");
     c("MEMORY_JS_COMPARTMENTS_SYSTEM", "JSMainRuntimeCompartmentsSystem");
     c("MEMORY_JS_COMPARTMENTS_USER", "JSMainRuntimeCompartmentsUser");
     b("MEMORY_IMAGES_CONTENT_USED_UNCOMPRESSED", "imagesContentUsedUncompressed");
     b("MEMORY_STORAGE_SQLITE", "storageSQLite");
     cc("LOW_MEMORY_EVENTS_VIRTUAL", "lowMemoryEventsVirtual");
     cc("LOW_MEMORY_EVENTS_PHYSICAL", "lowMemoryEventsPhysical");
     cc("PAGE_FAULTS_HARD", "pageFaultsHard");
 
+    try {
+      mgr.getHeapAllocatedAsync(heapAllocated => {
+        boundHandleMemoryReport("MEMORY_HEAP_ALLOCATED",
+                                Ci.nsIMemoryReporter.UNITS_BYTES,
+                                heapAllocated);
+      });
+    } catch (e) {
+    }
+
     if (!Utils.isContentProcess && !this._totalMemoryTimeout) {
       // Only the chrome process should gather total memory
       // total = parent RSS + sum(child USS)
       this._totalMemory = mgr.residentFast;
       if (ppmm.childCount > 1) {
         // Do not report If we time out waiting for the children to call
         this._totalMemoryTimeout = setTimeout(
           () => {
--- a/toolkit/components/timermanager/nsUpdateTimerManager.js
+++ b/toolkit/components/timermanager/nsUpdateTimerManager.js
@@ -1,17 +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/. */
 
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm", this);
-Components.utils.import("resource://gre/modules/Services.jsm", this);
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
-const Cc = Components.classes;
-const Ci = Components.interfaces;
+Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
+Cu.import("resource://gre/modules/Services.jsm", this);
 
 const PREF_APP_UPDATE_LASTUPDATETIME_FMT  = "app.update.lastUpdateTime.%ID%";
 const PREF_APP_UPDATE_TIMERMINIMUMDELAY   = "app.update.timerMinimumDelay";
 const PREF_APP_UPDATE_TIMERFIRSTINTERVAL  = "app.update.timerFirstInterval";
 const PREF_APP_UPDATE_LOG                 = "app.update.log";
 
 const CATEGORY_UPDATE_TIMER               = "update-timer";
 
@@ -303,16 +302,24 @@ TimerManager.prototype = {
     }
   },
 
   /**
    * See nsIUpdateTimerManager.idl
    */
   registerTimer: function TM_registerTimer(id, callback, interval) {
     LOG("TimerManager:registerTimer - id: " + id);
+    if (this._timers === null) {
+      // Use normal logging since reportError is not available while shutting
+      // down.
+      gLogEnabled = true;
+      LOG("TimerManager:registerTimer called after profile-before-change " +
+          "notification. Ignoring timer registration for id: " + id);
+      return;
+    }
     if (id in this._timers && callback != this._timers[id].callback) {
       LOG("TimerManager:registerTimer - Ignoring second registration for " + id);
       return;
     }
     let prefLastUpdate = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, id);
     // Initialize the last update time to 0 when the preference isn't set so
     // the timer will be notified soon after a new profile's first use.
     let lastUpdateTime = getPref("getIntPref", prefLastUpdate, 0);
@@ -326,21 +333,22 @@ TimerManager.prototype = {
     this._timers[id] = {callback,
                         interval,
                         lastUpdateTime};
 
     this._ensureTimer(interval * 1000);
   },
 
   unregisterTimer: function TM_unregisterTimer(id) {
-    LOG(`TimerManager:unregisterTimer - id: ${id}`);
+    LOG("TimerManager:unregisterTimer - id: " + id);
     if (id in this._timers) {
       delete this._timers[id];
     } else {
-      LOG(`TimerManager:registerTimer - Ignoring unregistration request for unknown id: ${id}`);
+      LOG("TimerManager:unregisterTimer - Ignoring unregistration request for " +
+          "unknown id: " + id);
     }
   },
 
   classID: Components.ID("{B322A5C0-A419-484E-96BA-D7182163899F}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdateTimerManager,
                                          Ci.nsITimerCallback,
                                          Ci.nsIObserver])
 };
--- a/toolkit/xre/nsNativeAppSupportWin.cpp
+++ b/toolkit/xre/nsNativeAppSupportWin.cpp
@@ -1,16 +1,17 @@
 /* -*- 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 "nsNativeAppSupportBase.h"
 #include "nsNativeAppSupportWin.h"
 #include "nsAppRunner.h"
+#include "nsContentUtils.h"
 #include "nsXULAppAPI.h"
 #include "nsString.h"
 #include "nsIBrowserDOMWindow.h"
 #include "nsICommandLineRunner.h"
 #include "nsCOMPtr.h"
 #include "nsXPIDLString.h"
 #include "nsIComponentManager.h"
 #include "nsIServiceManager.h"
@@ -1458,16 +1459,17 @@ nsNativeAppSupportWin::OpenBrowserWindow
         if ( bwin ) {
           nsCOMPtr<nsIURI> uri;
           NS_NewURI( getter_AddRefs( uri ), NS_LITERAL_CSTRING("about:blank"), 0, 0 );
           if ( uri ) {
             nsCOMPtr<mozIDOMWindowProxy> container;
             rv = bwin->OpenURI( uri, 0,
                                 nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW,
                                 nsIBrowserDOMWindow::OPEN_EXTERNAL,
+                                nsContentUtils::GetSystemPrincipal(),
                                 getter_AddRefs( container ) );
             if ( NS_SUCCEEDED( rv ) )
               return NS_OK;
           }
         }
 
         NS_ERROR("failed to hand off external URL to extant window");
     } while ( false );
--- a/tools/profiler/core/platform-win32.cpp
+++ b/tools/profiler/core/platform-win32.cpp
@@ -27,16 +27,20 @@
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 // SUCH DAMAGE.
 
 #include <windows.h>
 #include <mmsystem.h>
 #include <process.h>
 
+#include "nsWindowsDllInterceptor.h"
+#include "mozilla/StackWalk_windows.h"
+#include "mozilla/WindowsVersion.h"
+
 /* static */ Thread::tid_t
 Thread::GetCurrentId()
 {
   return GetCurrentThreadId();
 }
 
 static void
 PopulateRegsFromContext(Registers& aRegs, CONTEXT* aContext)
@@ -277,8 +281,63 @@ void
 Registers::SyncPopulate()
 {
   CONTEXT context;
   RtlCaptureContext(&context);
   PopulateRegsFromContext(*this, &context);
 }
 #endif
 
+#if defined(GP_PLAT_amd64_windows)
+static WindowsDllInterceptor NtDllIntercept;
+
+typedef NTSTATUS (NTAPI *LdrUnloadDll_func)(HMODULE module);
+static LdrUnloadDll_func stub_LdrUnloadDll;
+
+static NTSTATUS NTAPI
+patched_LdrUnloadDll(HMODULE module)
+{
+  // Prevent the stack walker from suspending this thread when LdrUnloadDll
+  // holds the RtlLookupFunctionEntry lock.
+  AutoSuppressStackWalking suppress;
+  return stub_LdrUnloadDll(module);
+}
+
+// These pointers are disguised as PVOID to avoid pulling in obscure headers
+typedef PVOID (WINAPI *LdrResolveDelayLoadedAPI_func)(PVOID ParentModuleBase,
+  PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
+  PVOID ThunkAddress, ULONG Flags);
+static LdrResolveDelayLoadedAPI_func stub_LdrResolveDelayLoadedAPI;
+
+static PVOID WINAPI
+patched_LdrResolveDelayLoadedAPI(PVOID ParentModuleBase,
+  PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
+  PVOID ThunkAddress, ULONG Flags)
+{
+  // Prevent the stack walker from suspending this thread when
+  // LdrResolveDelayLoadAPI holds the RtlLookupFunctionEntry lock.
+  AutoSuppressStackWalking suppress;
+  return stub_LdrResolveDelayLoadedAPI(ParentModuleBase, DelayloadDescriptor,
+                                       FailureDllHook, FailureSystemHook,
+                                       ThunkAddress, Flags);
+}
+
+void
+InitializeWin64ProfilerHooks()
+{
+  static bool initialized = false;
+  if (initialized) {
+    return;
+  }
+  initialized = true;
+
+  NtDllIntercept.Init("ntdll.dll");
+  NtDllIntercept.AddHook("LdrUnloadDll",
+                         reinterpret_cast<intptr_t>(patched_LdrUnloadDll),
+                         (void**)&stub_LdrUnloadDll);
+  if (IsWin8OrLater()) { // LdrResolveDelayLoadedAPI was introduced in Win8
+    NtDllIntercept.AddHook("LdrResolveDelayLoadedAPI",
+                           reinterpret_cast<intptr_t>(patched_LdrResolveDelayLoadedAPI),
+                           (void**)&stub_LdrResolveDelayLoadedAPI);
+  }
+}
+#endif // defined(GP_PLAT_amd64_windows)
+
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -2418,16 +2418,20 @@ locked_profiler_start(PSLockRef aLock, i
 
     for (uint32_t i = 0; i < aFilterCount; i++) {
       LOG("- threads  = %s", aFilters[i]);
     }
   }
 
   MOZ_RELEASE_ASSERT(CorePS::Exists() && !ActivePS::Exists(aLock));
 
+#if defined(GP_PLAT_amd64_windows)
+  InitializeWin64ProfilerHooks();
+#endif
+
   // Fall back to the default values if the passed-in values are unreasonable.
   int entries = aEntries > 0 ? aEntries : PROFILER_DEFAULT_ENTRIES;
   double interval = aInterval > 0 ? aInterval : PROFILER_DEFAULT_INTERVAL;
 
   ActivePS::Create(aLock, entries, interval, aFeatures, aFilters, aFilterCount);
 
   // Set up profiling for each registered thread, if appropriate.
   Thread::tid_t tid = Thread::GetCurrentId();
--- a/uriloader/exthandler/nsWebHandlerApp.js
+++ b/uriloader/exthandler/nsWebHandlerApp.js
@@ -7,16 +7,17 @@
 
 const Ci = Components.interfaces;
 const Cr = Components.results;
 const Cc = Components.classes;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
+Cu.import('resource://gre/modules/Services.jsm');
 
 ////////////////////////////////////////////////////////////////////////////////
 //// nsWebHandler class
 
 function nsWebHandlerApp() {}
 
 nsWebHandlerApp.prototype = {
   //////////////////////////////////////////////////////////////////////////////
@@ -138,17 +139,18 @@ nsWebHandlerApp.prototype = {
     //
     // it's not clear how one would differentiate between the three cases
     // above, so for now we don't catch the exception
 
     // openURI
     browserDOMWin.openURI(uriToSend,
                           null, // no window.opener
                           Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW,
-                          Ci.nsIBrowserDOMWindow.OPEN_NEW);
+                          Ci.nsIBrowserDOMWindow.OPEN_NEW,
+                          Services.scriptSecurityManager.getSystemPrincipal());
       
     return;
   },
 
   //////////////////////////////////////////////////////////////////////////////
   //// nsIWebHandlerApp
 
   get uriTemplate() {
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -39,16 +39,17 @@ using mozilla::Unused;
 #include "nsIXULWindow.h"
 
 #include "nsAppShell.h"
 #include "nsFocusManager.h"
 #include "nsIdleService.h"
 #include "nsLayoutUtils.h"
 #include "nsViewManager.h"
 
+#include "nsContentUtils.h"
 #include "WidgetUtils.h"
 
 #include "nsIDOMSimpleGestureEvent.h"
 
 #include "nsGkAtoms.h"
 #include "nsWidgetsCID.h"
 #include "nsGfxCIID.h"
 
@@ -1404,16 +1405,17 @@ nsWindow::GeckoViewSupport::LoadUri(jni:
                         nsIBrowserDOMWindow::OPEN_NEWTAB :
                       aFlags == GeckoView::LOAD_SWITCH_TAB ?
                         nsIBrowserDOMWindow::OPEN_SWITCHTAB :
                         nsIBrowserDOMWindow::OPEN_CURRENTWINDOW;
     nsCOMPtr<mozIDOMWindowProxy> newWin;
 
     if (NS_FAILED(browserWin->OpenURI(
             uri, nullptr, flags, nsIBrowserDOMWindow::OPEN_EXTERNAL,
+            nsContentUtils::GetSystemPrincipal(),
             getter_AddRefs(newWin)))) {
         NS_WARNING("Failed to open URI");
     }
 }
 
 void
 nsWindow::InitNatives()
 {
--- a/widget/windows/nsWidgetFactory.cpp
+++ b/widget/windows/nsWidgetFactory.cpp
@@ -70,17 +70,17 @@ WindowConstructor(nsISupports *aOuter, R
 static nsresult
 ChildWindowConstructor(nsISupports *aOuter, REFNSIID aIID,
                        void **aResult)
 {
   *aResult = nullptr;
   if (aOuter != nullptr) {
     return NS_ERROR_NO_AGGREGATION;
   }
-  nsCOMPtr<nsIWidget> widget = new ChildWindow;
+  nsCOMPtr<nsIWidget> widget = new nsWindow(true);
   return widget->QueryInterface(aIID, aResult);
 }
 
 static nsresult
 FilePickerConstructor(nsISupports *aOuter, REFNSIID aIID,
                       void **aResult)
 {
   *aResult = nullptr;
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -589,19 +589,20 @@ StaticAutoPtr<TIPMessageHandler> TIPMess
  **************************************************************/
 
 /**************************************************************
  *
  * SECTION: nsWindow construction and destruction
  *
  **************************************************************/
 
-nsWindow::nsWindow()
+nsWindow::nsWindow(bool aIsChildWindow)
   : nsWindowBase()
   , mResizeState(NOT_RESIZING)
+  , mIsChildWindow(aIsChildWindow)
 {
   mIconSmall            = nullptr;
   mIconBig              = nullptr;
   mWnd                  = nullptr;
   mTransitionWnd        = nullptr;
   mPaintDC              = nullptr;
   mPrevWndProc          = nullptr;
   mNativeDragTarget     = nullptr;
@@ -1144,16 +1145,23 @@ DWORD nsWindow::WindowStyle()
     if (IsPopupWithTitleBar()) {
       style |= WS_CAPTION;
       if (mBorderStyle & eBorderStyle_close) {
         style |= WS_SYSMENU;
       }
     }
   }
 
+  if (mIsChildWindow) {
+    style |= WS_CLIPCHILDREN;
+    if (!(style & WS_POPUP)) {
+      style |= WS_CHILD; // WS_POPUP and WS_CHILD are mutually exclusive.
+    }
+  }
+
   VERIFY_WINDOW_STYLE(style);
   return style;
 }
 
 // Return nsWindow extended styles
 DWORD nsWindow::WindowExStyle()
 {
   switch (mWindowType)
@@ -8339,36 +8347,16 @@ bool nsWindow::OnPointerEvents(UINT msg,
   LPARAM newLParam = lParamToClient(aLParam);
   DispatchMouseEvent(message, aWParam, newLParam, false, button,
                      nsIDOMMouseEvent::MOZ_SOURCE_PEN, &pointerInfo);
   // Consume WM_POINTER* to stop Windows fires WM_*BUTTONDOWN / WM_*BUTTONUP
   // WM_MOUSEMOVE.
   return true;
 }
 
-/**************************************************************
- **************************************************************
- **
- ** BLOCK: ChildWindow impl.
- **
- ** Child window overrides.
- **
- **************************************************************
- **************************************************************/
-
-// return the style for a child nsWindow
-DWORD ChildWindow::WindowStyle()
-{
-  DWORD style = WS_CLIPCHILDREN | nsWindow::WindowStyle();
-  if (!(style & WS_POPUP))
-    style |= WS_CHILD; // WS_POPUP and WS_CHILD are mutually exclusive.
-  VERIFY_WINDOW_STYLE(style);
-  return style;
-}
-
 void
 nsWindow::GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData)
 {
   aInitData->hWnd() = reinterpret_cast<uintptr_t>(mWnd);
   aInitData->widgetKey() = reinterpret_cast<uintptr_t>(static_cast<nsIWidget*>(this));
   aInitData->transparencyMode() = mTransparencyMode;
 }
 
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -62,28 +62,28 @@ class WinCompositorWidget;
 struct MSGResult;
 } // namespace widget
 } // namespacw mozilla;
 
 /**
  * Native WIN32 window wrapper.
  */
 
-class nsWindow : public nsWindowBase
+class nsWindow final : public nsWindowBase
 {
   typedef mozilla::TimeStamp TimeStamp;
   typedef mozilla::TimeDuration TimeDuration;
   typedef mozilla::widget::WindowHook WindowHook;
   typedef mozilla::widget::TaskbarWindowPreview TaskbarWindowPreview;
   typedef mozilla::widget::NativeKey NativeKey;
   typedef mozilla::widget::MSGResult MSGResult;
   typedef mozilla::widget::IMEContext IMEContext;
 
 public:
-  nsWindow();
+  explicit nsWindow(bool aIsChildWindow = false);
 
   NS_DECL_ISUPPORTS_INHERITED
 
   friend class nsWindowGfx;
 
   // nsWindowBase
   virtual void InitEvent(mozilla::WidgetGUIEvent& aEvent,
                          LayoutDeviceIntPoint* aPoint = nullptr) override;
@@ -630,16 +630,19 @@ protected:
 
   // Indicates that mouse events should be ignored and pass through to the
   // window below. This is currently only used for popups.
   bool                  mMouseTransparent;
 
   // Whether we're in the process of sending a WM_SETTEXT ourselves
   bool                  mSendingSetText;
 
+  // Whether we we're created as a NS_CHILD_CID window (aka ChildWindow) or not.
+  bool                  mIsChildWindow : 1;
+
   // The point in time at which the last paint completed. We use this to avoid
   //  painting too rapidly in response to frequent input events.
   TimeStamp mLastPaintEndTime;
 
   // Caching for hit test results
   POINT mCachedHitTestPoint;
   TimeStamp mCachedHitTestTime;
   int32_t mCachedHitTestResult;
@@ -657,21 +660,9 @@ protected:
   // associated with a particular widget (since we exited the widget).
   static WPARAM sMouseExitwParam;
   static LPARAM sMouseExitlParamScreen;
 
   // Pointer events processing and management
   WinPointerEvents mPointerEvents;
 };
 
-/**
- * A child window is a window with different style.
- */
-class ChildWindow : public nsWindow {
-
-public:
-  ChildWindow() {}
-
-protected:
-  virtual DWORD WindowStyle();
-};
-
 #endif // Window_h__
--- a/xpcom/base/ErrorList.py
+++ b/xpcom/base/ErrorList.py
@@ -460,17 +460,16 @@ with modules["NETWORK"]:
 # 7: NS_ERROR_MODULE_PLUGINS
 # =======================================================================
 with modules["PLUGINS"]:
     errors["NS_ERROR_PLUGINS_PLUGINSNOTCHANGED"] = FAILURE(1000)
     errors["NS_ERROR_PLUGIN_DISABLED"] = FAILURE(1001)
     errors["NS_ERROR_PLUGIN_BLOCKLISTED"] = FAILURE(1002)
     errors["NS_ERROR_PLUGIN_TIME_RANGE_NOT_SUPPORTED"] = FAILURE(1003)
     errors["NS_ERROR_PLUGIN_CLICKTOPLAY"] = FAILURE(1004)
-    errors["NS_PLUGIN_INIT_PENDING"] = SUCCESS(1005)
 
 
 
 # =======================================================================
 # 8: NS_ERROR_MODULE_LAYOUT
 # =======================================================================
 with modules["LAYOUT"]:
     # Return code for nsITableLayout
--- a/xpcom/base/StaticPtr.h
+++ b/xpcom/base/StaticPtr.h
@@ -62,16 +62,23 @@ public:
   T* operator->() const
   {
     MOZ_ASSERT(mRawPtr);
     return get();
   }
 
   T& operator*() const { return *get(); }
 
+  T* forget()
+  {
+    T* temp = mRawPtr;
+    mRawPtr = nullptr;
+    return temp;
+  }
+
 private:
   // Disallow copy constructor, but only in debug mode.  We only define
   // a default constructor in debug mode (see above); if we declared
   // this constructor always, the compiler wouldn't generate a trivial
   // default constructor for us in non-debug mode.
 #ifdef DEBUG
   StaticAutoPtr(StaticAutoPtr<T>& aOther);
 #endif
--- a/xpcom/base/nsIMemoryReporter.idl
+++ b/xpcom/base/nsIMemoryReporter.idl
@@ -200,16 +200,22 @@ interface nsIMemoryReporter : nsISupport
 };
 
 [scriptable, function, uuid(548b3909-c04d-4ca6-8466-b8bee3837457)]
 interface nsIFinishReportingCallback : nsISupports
 {
   void callback(in nsISupports data);
 };
 
+[scriptable, function, uuid(1a80cd0f-0d9e-4397-be69-68ad28fe5175)]
+interface nsIHeapAllocatedCallback : nsISupports
+{
+  void callback(in int64_t bytesAllocated);
+};
+
 [scriptable, builtinclass, uuid(2998574d-8993-407a-b1a5-8ad7417653e1)]
 interface nsIMemoryReporterManager : nsISupports
 {
   /*
    * Initialize.
    */
   [must_use] void init();
 
@@ -407,16 +413,22 @@ interface nsIMemoryReporterManager : nsI
   /*
    * These attributes indicate DMD's status. "Enabled" means enabled at
    * build-time.
    */
   [infallible] readonly attribute boolean isDMDEnabled;
   [infallible] readonly attribute boolean isDMDRunning;
 
   /*
+   * Asynchronously gets attribute 'heapAllocated'. The value is returned in
+   * the callback argument.
+   */
+  [must_use] void getHeapAllocatedAsync(in nsIHeapAllocatedCallback callback);
+
+  /*
    * Run a series of GC/CC's in an attempt to minimize the application's memory
    * usage.  When we're finished, we invoke the given runnable if it's not
    * null.
    */
   [must_use] void minimizeMemoryUsage(in nsIRunnable callback);
 
   /*
    * Measure the memory that is known to be owned by this tab, split up into
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -4,28 +4,30 @@
  * 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 "nsAtomTable.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "nsPrintfCString.h"
+#include "nsProxyRelease.h"
 #include "nsServiceManagerUtils.h"
 #include "nsMemoryReporterManager.h"
 #include "nsITimer.h"
 #include "nsThreadUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsIObserverService.h"
 #include "nsIGlobalObject.h"
 #include "nsIXPConnect.h"
 #include "GeckoProfilerReporter.h"
 #if defined(XP_UNIX) || defined(MOZ_DMD)
 #include "nsMemoryInfoDumper.h"
 #endif
+#include "nsNetCID.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReportingProcess.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/UniquePtrExtensions.h"
 #include "mozilla/dom/MemoryReportTypes.h"
@@ -1590,16 +1592,19 @@ nsMemoryReporterManager::nsMemoryReporte
   , mIsRegistrationBlocked(false)
   , mStrongReporters(new StrongReportersTable())
   , mWeakReporters(new WeakReportersTable())
   , mSavedStrongReporters(nullptr)
   , mSavedWeakReporters(nullptr)
   , mNextGeneration(1)
   , mPendingProcessesState(nullptr)
   , mPendingReportersState(nullptr)
+#ifdef HAVE_JEMALLOC_STATS
+  , mThreadPool(do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID))
+#endif
 {
 }
 
 nsMemoryReporterManager::~nsMemoryReporterManager()
 {
   delete mStrongReporters;
   delete mWeakReporters;
   NS_ASSERTION(!mSavedStrongReporters, "failed to restore strong reporters");
@@ -2368,16 +2373,59 @@ nsMemoryReporterManager::GetHeapAllocate
   *aAmount = stats.allocated;
   return NS_OK;
 #else
   *aAmount = 0;
   return NS_ERROR_NOT_AVAILABLE;
 #endif
 }
 
+NS_IMETHODIMP
+nsMemoryReporterManager::GetHeapAllocatedAsync(nsIHeapAllocatedCallback *aCallback)
+{
+#ifdef HAVE_JEMALLOC_STATS
+  if (!mThreadPool) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  RefPtr<nsIMemoryReporterManager> self{this};
+  nsMainThreadPtrHandle<nsIHeapAllocatedCallback> mainThreadCallback(
+    new nsMainThreadPtrHolder<nsIHeapAllocatedCallback>("HeapAllocatedCallback",
+                                                        aCallback));
+
+  nsCOMPtr<nsIRunnable> getHeapAllocatedRunnable = NS_NewRunnableFunction(
+    "nsMemoryReporterManager::GetHeapAllocatedAsync",
+    [self, mainThreadCallback]() mutable {
+      MOZ_ASSERT(!NS_IsMainThread());
+
+      int64_t heapAllocated = 0;
+      nsresult rv = self->GetHeapAllocated(&heapAllocated);
+
+      nsCOMPtr<nsIRunnable> resultCallbackRunnable = NS_NewRunnableFunction(
+        "nsMemoryReporterManager::GetHeapAllocatedAsync",
+        [mainThreadCallback, heapAllocated, rv]() mutable {
+          MOZ_ASSERT(NS_IsMainThread());
+
+          if (NS_FAILED(rv)) {
+            mainThreadCallback->Callback(0);
+            return;
+          }
+
+          mainThreadCallback->Callback(heapAllocated);
+        });  // resultCallbackRunnable.
+
+      Unused << NS_DispatchToMainThread(resultCallbackRunnable);
+    }); // getHeapAllocatedRunnable.
+
+  return mThreadPool->Dispatch(getHeapAllocatedRunnable, NS_DISPATCH_NORMAL);
+#else
+  return NS_ERROR_NOT_AVAILABLE;
+#endif
+}
+
 // This has UNITS_PERCENTAGE, so it is multiplied by 100x.
 NS_IMETHODIMP
 nsMemoryReporterManager::GetHeapOverheadFraction(int64_t* aAmount)
 {
 #ifdef HAVE_JEMALLOC_STATS
   jemalloc_stats_t stats;
   jemalloc_stats(&stats);
   *aAmount = HeapOverheadFraction(&stats);
--- a/xpcom/base/nsMemoryReporterManager.h
+++ b/xpcom/base/nsMemoryReporterManager.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsMemoryReporterManager_h__
 #define nsMemoryReporterManager_h__
 
 #include "mozilla/Mutex.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
+#include "nsIEventTarget.h"
 #include "nsIMemoryReporter.h"
 #include "nsITimer.h"
 #include "nsServiceManagerUtils.h"
 #include "nsDataHashtable.h"
 
 namespace mozilla {
 class MemoryReportingProcess;
 namespace dom {
@@ -271,16 +272,19 @@ private:
   // When this is non-null, a request is in flight.  Note: We use manual
   // new/delete for this because its lifetime doesn't match block scope or
   // anything like that.
   PendingProcessesState* mPendingProcessesState;
 
   // This is reinitialized each time a call to GetReports is initiated.
   PendingReportersState* mPendingReportersState;
 
+  // Used in GetHeapAllocatedAsync() to run jemalloc_stats async.
+  nsCOMPtr<nsIEventTarget> mThreadPool;
+
   PendingProcessesState* GetStateForGeneration(uint32_t aGeneration);
   static MOZ_MUST_USE bool
   StartChildReport(mozilla::MemoryReportingProcess* aChild,
                    const PendingProcessesState* aState);
 };
 
 #define NS_MEMORY_REPORTER_MANAGER_CID \
 { 0xfb97e4f5, 0x32dd, 0x497a, \
--- a/xpfe/appshell/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/nsContentTreeOwner.cpp
@@ -30,16 +30,17 @@
 #include "nsIURIFixup.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIWebNavigation.h"
 #include "nsDocShellCID.h"
 #include "nsIExternalURLHandlerService.h"
 #include "nsIMIMEInfo.h"
 #include "nsIWidget.h"
 #include "nsWindowWatcher.h"
+#include "NullPrincipal.h"
 #include "mozilla/BrowserElementParent.h"
 
 #include "nsIDOMDocument.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIURI.h"
 #include "nsIDocument.h"
 #if defined(XP_MACOSX)
 #include "nsThreadUtils.h"
@@ -918,23 +919,25 @@ nsContentTreeOwner::ProvideWindow(mozIDO
     dom::AutoNoJSAPI nojsapi;
 
     uint32_t flags = nsIBrowserDOMWindow::OPEN_NEW;
     if (aForceNoOpener) {
       flags |= nsIBrowserDOMWindow::OPEN_NO_OPENER;
     }
 
     // Get a new rendering area from the browserDOMWin.  We don't want
-    // to be starting any loads here, so get it with a null URI.
+    // to be starting any loads here, so get it with a null URI. Since/
+    // we are not loading any URI, we follow the principle of least privlege
+    // and use a nullPrincipal as the triggeringPrincipal.
     //
     // This method handles setting the opener for us, so we don't need to set it
     // ourselves.
-    return browserDOMWin->OpenURI(nullptr, aParent,
-                                  openLocation,
-                                  flags, aReturn);
+    RefPtr<NullPrincipal> nullPrincipal = NullPrincipal::Create();
+    return browserDOMWin->OpenURI(nullptr, aParent, openLocation,
+                                  flags, nullPrincipal, aReturn);
   }
 }
 
 //*****************************************************************************
 // nsContentTreeOwner: Accessors
 //*****************************************************************************
 
 #if defined(XP_MACOSX)