merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Thu, 03 Aug 2017 11:46:00 +0200
changeset 620338 63e261ce8cb04c913d2e6b19ea451b7078d24dc1
parent 620317 681a2489f6a92a09f87336c4ebfcd55030ffcda1 (current diff)
parent 620337 d1ba080ed5b0a365444c00cc038f4e8732f1f33e (diff)
child 620339 a5a317b76db3db3b6092b81c7e4aecffb42ed9af
child 620407 32659556571acb887f85b922731489f91fcd9075
child 620413 2a3dd84b5bedc25d0d053b76023d43d82afcbc0d
child 620421 a66e444f03ad45ff9d9a0e622d1951cff5964082
child 620422 2f4c29bf033d798fba4ab10fa80000eeaa633acb
child 620426 60d2bd8b124cc022696f34786b78bd9abcb918a8
child 620427 7b2e62d57b56974b795cfb9a34adf2177287bbe2
child 620451 6a5dcf9eecfe00d14aea28212c6166e09cee4dfc
child 620469 e857c25d6f7f8f07c29a207454454276ae38abf7
child 620472 edf686bc3d7f56a156ec85ad85781203f57ef52f
child 620476 991f3fbeb7e7ca0c541fcd4c9ce28675f5cbbb38
child 620478 55b0c4bd0117993f1592e3ef71008a6fa9e10688
child 620483 b2caa01f75e5dd26078a7679fd7caa319a65af14
child 620492 02a037ce3c200b91c8121da9a59f4f4f0ad13d1a
child 620493 778b020671d811de57181085528adaaaf55b3d58
child 620494 fa1da3c0b200abbd9cfab3cab19962824314044e
child 620496 fe508424df690f3a7fda8f1aed3dd1ee8c3fb7b4
child 620497 1f7893c391287c7e6697f3cf1ae9b051cfdd4de1
child 620499 e4bb40969e083d95cbb9b783f91ee9456604614f
child 620500 80ed6acaa9df10b45d1ec4c3a6a7539d9f7ac0b5
child 620520 6f8b609ce54d3c74fa7c124397ed74a3617b5438
child 620522 b5afdf8db0e27bf6bfcea1870d2ab06d13c100d3
child 620524 f9e4fae1224e6fc442e58ed415743faaece99cef
child 620527 e93e1fea1229f8b8edf0798c30555f9e5ccff820
child 620529 97c87a1b4ea145a12164da19322754b1f6a50963
child 620549 3be62a3de45869c5aefb6ab7953dc93b7238de15
child 620556 684a79dcef6478385ed2ad0381f75f961f839747
child 620562 3a67b84065c94275b6c8f1a730d60b4d5fce4e83
child 620584 3e01e40718ddb829ddef00ac433d9af480fb1f14
child 620602 b85bcbc13e635a90f3375128b31af6b2c8dd7795
child 620603 3cd67eeb7e83d2d0f9e32a93183a6969069d092b
child 620766 91e0e0f018683ceade9d8da7fc3fe3a457605f5c
child 621016 5135336cbd1d1a8d671e158e0a795583182bb973
child 621073 311a5d4664ca935d5769a2fbdc2e71210da8191e
child 621097 42d2240a98146327a32bb9992a7f6205ff0989a5
child 641113 693263e24261bd956a362339b103731454a9117f
push id71999
push usertimdream@gmail.com
push dateThu, 03 Aug 2017 09:58:17 +0000
reviewersmerge, merge
milestone57.0a1
merge mozilla-inbound to mozilla-central. r=merge a=merge MozReview-Commit-ID: 5MywkQxECqB
browser/themes/linux/browser.css
browser/themes/osx/browser.css
browser/themes/windows/browser.css
gfx/layers/CopyableCanvasLayer.cpp
gfx/layers/CopyableCanvasLayer.h
gfx/layers/ShareableCanvasLayer.cpp
gfx/layers/ShareableCanvasLayer.h
testing/web-platform/tests/old-tests/submission/Opera/script_scheduling/100.html
testing/web-platform/tests/old-tests/submission/Opera/script_scheduling/scripts/include-12.js
--- a/accessible/windows/msaa/Compatibility.cpp
+++ b/accessible/windows/msaa/Compatibility.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Compatibility.h"
 
 #include "mozilla/WindowsVersion.h"
 #if defined(MOZ_CRASHREPORTER)
 #include "nsExceptionHandler.h"
+#include "nsPrintfCString.h"
 #endif // defined(MOZ_CRASHREPORTER)
 #include "nsUnicharUtils.h"
 #include "nsWindowsDllInterceptor.h"
 #include "nsWinUtils.h"
 #include "Statistics.h"
 
 #include "mozilla/Preferences.h"
 
@@ -169,16 +170,22 @@ Compatibility::Init()
   if (::GetModuleHandleW(L"uiautomation") ||
       ::GetModuleHandleW(L"uiautomationcore"))
     sConsumers |= UIAUTOMATION;
 
   // If we have a known consumer remove the unknown bit.
   if (sConsumers != Compatibility::UNKNOWN)
     sConsumers ^= Compatibility::UNKNOWN;
 
+#ifdef MOZ_CRASHREPORTER
+  CrashReporter::
+    AnnotateCrashReport(NS_LITERAL_CSTRING("AccessibilityInProcClient"),
+                        nsPrintfCString("0x%X", sConsumers));
+#endif
+
   // Gather telemetry
   uint32_t temp = sConsumers;
   for (int i = 0; temp; i++) {
     if (temp & 0x1)
       statistics::A11yConsumers(i);
 
     temp >>= 1;
   }
--- a/accessible/windows/msaa/LazyInstantiator.cpp
+++ b/accessible/windows/msaa/LazyInstantiator.cpp
@@ -19,16 +19,20 @@
 #include "nsXPCOM.h"
 #include "RootAccessibleWrap.h"
 #include "WinUtils.h"
 
 #if defined(MOZ_TELEMETRY_REPORTING)
 #include "mozilla/Telemetry.h"
 #endif // defined(MOZ_TELEMETRY_REPORTING)
 
+#ifdef MOZ_CRASHREPORTER
+#include "nsExceptionHandler.h"
+#endif
+
 #include <oaidl.h>
 
 #if !defined(STATE_SYSTEM_NORMAL)
 #define STATE_SYSTEM_NORMAL (0)
 #endif // !defined(STATE_SYSTEM_NORMAL)
 
 /**
  * Because our wrapped accessible is cycle-collected, we can't safely AddRef()
@@ -253,34 +257,35 @@ LazyInstantiator::ShouldInstantiate(cons
 
   // Blocklist checks should go here. return false if we should not instantiate.
   /*
   if (ClientShouldBeBlocked(clientExe)) {
     return false;
   }
   */
 
-#if defined(MOZ_TELEMETRY_REPORTING)
+#if defined(MOZ_TELEMETRY_REPORTING) || defined(MOZ_CRASHREPORTER)
   if (!mTelemetryThread) {
     // Call GatherTelemetry on a background thread because it does I/O on
     // the executable file to retrieve version information.
     nsCOMPtr<nsIRunnable> runnable(
         NewRunnableMethod<nsCOMPtr<nsIFile>, RefPtr<AccumulateRunnable>>(
                                              "LazyInstantiator::GatherTelemetry",
                                              this,
                                              &LazyInstantiator::GatherTelemetry,
                                              clientExe,
                                              new AccumulateRunnable(this)));
     NS_NewThread(getter_AddRefs(mTelemetryThread), runnable);
   }
-#endif // defined(MOZ_TELEMETRY_REPORTING)
+#endif // defined(MOZ_TELEMETRY_REPORTING) || defined(MOZ_CRASHREPORTER)
+
   return true;
 }
 
-#if defined(MOZ_TELEMETRY_REPORTING)
+#if defined(MOZ_TELEMETRY_REPORTING) || defined(MOZ_CRASHREPORTER)
 /**
  * Appends version information in the format "|a.b.c.d".
  * If there is no version information, we append nothing.
  */
 void
 LazyInstantiator::AppendVersionInfo(nsIFile* aClientExe,
                                     nsAString& aStrToAppend)
 {
@@ -349,25 +354,33 @@ LazyInstantiator::GatherTelemetry(nsIFil
 }
 
 void
 LazyInstantiator::AccumulateTelemetry(const nsString& aValue)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!aValue.IsEmpty()) {
-    Telemetry::ScalarSet(Telemetry::ScalarID::A11Y_INSTANTIATORS, aValue);
+#if defined(MOZ_TELEMETRY_REPORTING)
+    Telemetry::ScalarSet(Telemetry::ScalarID::A11Y_INSTANTIATORS,
+                         aValue);
+#endif // defined(MOZ_TELEMETRY_REPORTING)
+#if defined(MOZ_CRASHREPORTER)
+    CrashReporter::
+      AnnotateCrashReport(NS_LITERAL_CSTRING("AccessibilityClient"),
+                          NS_ConvertUTF16toUTF8(aValue));
+#endif // defined(MOZ_CRASHREPORTER)
   }
 
   if (mTelemetryThread) {
     mTelemetryThread->Shutdown();
     mTelemetryThread = nullptr;
   }
 }
-#endif // defined(MOZ_TELEMETRY_REPORTING)
+#endif // defined(MOZ_TELEMETRY_REPORTING) || defined(MOZ_CRASHREPORTER)
 
 RootAccessibleWrap*
 LazyInstantiator::ResolveRootAccWrap()
 {
   Accessible* acc = widget::WinUtils::GetRootAccessibleForHWND(mHwnd);
   if (!acc || !acc->IsRoot()) {
     return nullptr;
   }
--- a/accessible/windows/msaa/LazyInstantiator.h
+++ b/accessible/windows/msaa/LazyInstantiator.h
@@ -81,17 +81,17 @@ public:
 
 private:
   explicit LazyInstantiator(HWND aHwnd);
   ~LazyInstantiator();
 
   bool ShouldInstantiate(const DWORD aClientTid);
 
   bool GetClientExecutableName(const DWORD aClientTid, nsIFile** aOutClientExe);
-#if defined(MOZ_TELEMETRY_REPORTING)
+#if defined(MOZ_TELEMETRY_REPORTING) || defined(MOZ_CRASHREPORTER)
   class AccumulateRunnable final : public Runnable
   {
   public:
     explicit AccumulateRunnable(LazyInstantiator* aObj)
       : Runnable("mozilla::a11y::LazyInstantiator::AccumulateRunnable")
       , mObj(aObj)
     {
       MOZ_ASSERT(NS_IsMainThread());
@@ -114,17 +114,17 @@ private:
     nsString                              mData;
   };
 
   friend class AccumulateRunnable;
 
   void AppendVersionInfo(nsIFile* aClientExe, nsAString& aStrToAppend);
   void GatherTelemetry(nsIFile* aClientExe, AccumulateRunnable* aRunnable);
   void AccumulateTelemetry(const nsString& aValue);
-#endif // defined(MOZ_TELEMETRY_REPORTING)
+#endif // defined(MOZ_TELEMETRY_REPORTING) || defined(MOZ_CRASHREPORTER)
 
   /**
    * @return S_OK if we have a valid mRealRoot to invoke methods on
    */
   HRESULT MaybeResolveRoot();
 
   /**
    * @return S_OK if we have a valid mWeakDispatch to invoke methods on
@@ -146,18 +146,18 @@ private:
    * are interfaces that come from objects that we aggregate. Aggregated object
    * interfaces share refcount methods with ours, so if we were to hold strong
    * references to them, we would be holding strong references to ourselves,
    * creating a cycle.
    */
   RootAccessibleWrap* mWeakRootAccWrap;
   IAccessible*        mWeakAccessible;
   IDispatch*          mWeakDispatch;
-#if defined(MOZ_TELEMETRY_REPORTING)
+#if defined(MOZ_TELEMETRY_REPORTING) || defined(MOZ_CRASHREPORTER)
   nsCOMPtr<nsIThread> mTelemetryThread;
-#endif // defined(MOZ_TELEMETRY_REPORTING)
+#endif // defined(MOZ_TELEMETRY_REPORTING) || defined(MOZ_CRASHREPORTER)
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif // mozilla_a11y_LazyInstantiator_h
 
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -113,16 +113,19 @@ var whitelist = [
   {file: "resource://gre/chrome/en-US/locale/en-US/global-platform/win/intl.properties",
    platforms: ["linux", "macosx"]},
   {file: "resource://gre/chrome/en-US/locale/en-US/global-platform/win/platformKeys.properties",
    platforms: ["linux", "macosx"]},
 
   // browser/extensions/pdfjs/content/web/viewer.js#7450
   {file: "resource://pdf.js/web/debugger.js"},
 
+  // Needed by Normandy
+  {file: "resource://gre/modules/IndexedDB.jsm"},
+
   // Starting from here, files in the whitelist are bugs that need fixing.
   // Bug 1339420
   {file: "chrome://branding/content/icon128.png"},
   // Bug 1339424 (wontfix?)
   {file: "chrome://browser/locale/taskbar.properties",
    platforms: ["linux", "macosx"]},
   // Bug 1316187
   {file: "chrome://global/content/customizeToolbar.xul"},
--- a/browser/base/content/webext-panels.js
+++ b/browser/base/content/webext-panels.js
@@ -19,16 +19,19 @@ var {
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 function getBrowser(sidebar) {
   let browser = document.getElementById("webext-panels-browser");
   if (browser) {
     return Promise.resolve(browser);
   }
 
+  let stack = document.createElementNS(XUL_NS, "stack");
+  stack.setAttribute("flex", "1");
+
   browser = document.createElementNS(XUL_NS, "browser");
   browser.setAttribute("id", "webext-panels-browser");
   browser.setAttribute("type", "content");
   browser.setAttribute("flex", "1");
   browser.setAttribute("disableglobalhistory", "true");
   browser.setAttribute("webextension-view-type", "sidebar");
   browser.setAttribute("context", "contentAreaContextMenu");
   browser.setAttribute("tooltip", "aHTMLTooltip");
@@ -45,17 +48,19 @@ function getBrowser(sidebar) {
 
     window.messageManager.addMessageListener("contextmenu", openContextMenu);
     window.addEventListener("unload", () => {
       window.messageManager.removeMessageListener("contextmenu", openContextMenu);
     }, {once: true});
   } else {
     readyPromise = Promise.resolve();
   }
-  document.documentElement.appendChild(browser);
+
+  stack.appendChild(browser);
+  document.documentElement.appendChild(stack);
 
   return readyPromise.then(() => {
     browser.messageManager.loadFrameScript("chrome://browser/content/content.js", false);
     ExtensionParent.apiManager.emit("extension-browser-inserted", browser);
 
     if (sidebar.browserStyle) {
       browser.messageManager.loadFrameScript(
         "chrome://extensions/content/ext-browser-content.js", false);
@@ -63,16 +68,30 @@ function getBrowser(sidebar) {
       browser.messageManager.sendAsyncMessage("Extension:InitBrowser", {
         stylesheets: ExtensionParent.extensionStylesheets,
       });
     }
     return browser;
   });
 }
 
+// Stub tabbrowser implementation for use by the tab-modal alert code.
+var gBrowser = {
+  getTabForBrowser(browser) {
+    return null;
+  },
+
+  getTabModalPromptBox(browser) {
+    if (!browser.tabModalPromptBox) {
+      browser.tabModalPromptBox = new TabModalPromptBox(browser);
+    }
+    return browser.tabModalPromptBox;
+  },
+};
+
 function loadWebPanel() {
   let sidebarURI = new URL(location);
   let sidebar = {
     uri: sidebarURI.searchParams.get("panel"),
     remote: sidebarURI.searchParams.get("remote"),
     browserStyle: sidebarURI.searchParams.get("browser-style"),
   };
   getBrowser(sidebar).then(browser => {
--- a/browser/components/extensions/ExtensionPopups.jsm
+++ b/browser/components/extensions/ExtensionPopups.jsm
@@ -112,31 +112,35 @@ class BasePopup {
 
     BasePopup.instances.get(this.window).delete(this.extension);
 
     return this.browserReady.then(() => {
       if (this.browser) {
         this.destroyBrowser(this.browser, true);
         this.browser.remove();
       }
+      if (this.stack) {
+        this.stack.remove();
+      }
 
       if (this.viewNode) {
         this.viewNode.removeEventListener(this.DESTROY_EVENT, this);
         this.viewNode.style.maxHeight = "";
         delete this.viewNode.customRectGetter;
       }
 
       let {panel} = this;
       if (panel) {
         panel.style.removeProperty("--arrowpanel-background");
         panel.style.removeProperty("--panel-arrow-image-vertical");
         panel.removeAttribute("remote");
       }
 
       this.browser = null;
+      this.stack = null;
       this.viewNode = null;
     });
   }
 
   destroyBrowser(browser, finalize = false) {
     let mm = browser.messageManager;
     // If the browser has already been removed from the document, because the
     // popup was closed externally, there will be no message manager here, so
@@ -215,16 +219,20 @@ class BasePopup {
           this.destroy();
         }
         break;
     }
   }
 
   createBrowser(viewNode, popupURL = null) {
     let document = viewNode.ownerDocument;
+
+    let stack = document.createElementNS(XUL_NS, "stack");
+    stack.setAttribute("class", "webextension-popup-stack");
+
     let browser = document.createElementNS(XUL_NS, "browser");
     browser.setAttribute("type", "content");
     browser.setAttribute("disableglobalhistory", "true");
     browser.setAttribute("transparent", "true");
     browser.setAttribute("class", "webextension-popup-browser");
     browser.setAttribute("webextension-view-type", "popup");
     browser.setAttribute("tooltip", "aHTMLTooltip");
     browser.setAttribute("contextmenu", "contentAreaContextMenu");
@@ -237,32 +245,35 @@ class BasePopup {
       browser.setAttribute("remote", "true");
       browser.setAttribute("remoteType", E10SUtils.EXTENSION_REMOTE_TYPE);
     }
 
     // We only need flex sizing for the sake of the slide-in sub-views of the
     // main menu panel, so that the browser occupies the full width of the view,
     // and also takes up any extra height that's available to it.
     browser.setAttribute("flex", "1");
+    stack.setAttribute("flex", "1");
 
     // Note: When using noautohide panels, the popup manager will add width and
     // height attributes to the panel, breaking our resize code, if the browser
     // starts out smaller than 30px by 10px. This isn't an issue now, but it
     // will be if and when we popup debugging.
 
     this.browser = browser;
+    this.stack = stack;
 
     let readyPromise;
     if (this.extension.remote) {
       readyPromise = promiseEvent(browser, "XULFrameLoaderCreated");
     } else {
       readyPromise = promiseEvent(browser, "load");
     }
 
-    viewNode.appendChild(browser);
+    stack.appendChild(browser);
+    viewNode.appendChild(stack);
 
     ExtensionParent.apiManager.emit("extension-browser-inserted", browser);
 
     let setupBrowser = browser => {
       let mm = browser.messageManager;
       mm.addMessageListener("DOMTitleChanged", this);
       mm.addMessageListener("Extension:BrowserBackgroundChanged", this);
       mm.addMessageListener("Extension:BrowserContentLoaded", this);
--- a/browser/components/extensions/ext-browserAction.js
+++ b/browser/components/extensions/ext-browserAction.js
@@ -18,18 +18,16 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource://gre/modules/TelemetryStopwatch.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ViewPopup",
                                   "resource:///modules/ExtensionPopups.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "DOMUtils",
                                    "@mozilla.org/inspector/dom-utils;1",
                                    "inIDOMUtils");
 
-Cu.import("resource://gre/modules/EventEmitter.jsm");
-
 XPCOMUtils.defineLazyPreferenceGetter(this, "gPhotonStructure", "browser.photon.structure.enabled");
 
 var {
   DefaultWeakMap,
 } = ExtensionUtils;
 
 Cu.import("resource://gre/modules/ExtensionParent.jsm");
 
--- a/browser/components/extensions/ext-c-devtools-panels.js
+++ b/browser/components/extensions/ext-c-devtools-panels.js
@@ -1,17 +1,15 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 // The ext-* files are imported into the same scopes.
 /* import-globals-from ../../../toolkit/components/extensions/ext-c-toolkit.js */
 
-Cu.import("resource://gre/modules/Services.jsm");
-
 XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
                                   "resource://gre/modules/EventEmitter.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionChildDevToolsUtils",
                                   "resource://gre/modules/ExtensionChildDevToolsUtils.jsm");
 
 var {
   promiseDocumentLoaded,
 } = ExtensionUtils;
--- a/browser/components/extensions/ext-sidebarAction.js
+++ b/browser/components/extensions/ext-sidebarAction.js
@@ -1,17 +1,15 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 // The ext-* files are imported into the same scopes.
 /* import-globals-from ext-utils.js */
 
-XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
-                                  "resource://gre/modules/AppConstants.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
                                   "resource:///modules/CustomizableUI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 
 Cu.import("resource://gre/modules/ExtensionParent.jsm");
 
 var {
--- a/browser/components/extensions/ext-tabs.js
+++ b/browser/components/extensions/ext-tabs.js
@@ -5,20 +5,16 @@
 // The ext-* files are imported into the same scopes.
 /* import-globals-from ext-utils.js */
 
 XPCOMUtils.defineLazyGetter(this, "strBundle", function() {
   const stringSvc = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
   return stringSvc.createBundle("chrome://global/locale/extensions.properties");
 });
 
-XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
-                                   "@mozilla.org/browser/aboutnewtab-service;1",
-                                   "nsIAboutNewTabService");
-
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
                                   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
                                   "resource://gre/modules/PromiseUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 
 let tabListener = {
--- a/browser/components/extensions/ext-utils.js
+++ b/browser/components/extensions/ext-utils.js
@@ -7,20 +7,16 @@
           makeWidgetId:false, tabTracker:true, windowTracker:true */
 /* import-globals-from ../../../toolkit/components/extensions/ext-toolkit.js */
 
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
                                   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 Cu.import("resource://gre/modules/ExtensionTabs.jsm");
 
-XPCOMUtils.defineLazyServiceGetter(this, "styleSheetService",
-                                   "@mozilla.org/content/style-sheet-service;1",
-                                   "nsIStyleSheetService");
-
 var {
   ExtensionError,
   defineLazyGetter,
 } = ExtensionUtils;
 
 let tabTracker;
 let windowTracker;
 
--- a/browser/components/extensions/ext-windows.js
+++ b/browser/components/extensions/ext-windows.js
@@ -3,18 +3,16 @@
 "use strict";
 
 // The ext-* files are imported into the same scopes.
 /* import-globals-from ext-utils.js */
 
 XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
                                    "@mozilla.org/browser/aboutnewtab-service;1",
                                    "nsIAboutNewTabService");
-XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
-                                  "resource://gre/modules/AppConstants.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
                                   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 var {
   promiseObserved,
 } = ExtensionUtils;
 
 const onXULFrameLoaderCreated = ({target}) => {
--- a/browser/components/extensions/test/browser/browser_ext_popup_corners.js
+++ b/browser/components/extensions/test/browser/browser_ext_popup_corners.js
@@ -36,17 +36,18 @@ add_task(async function testPopupBorderR
   await extension.startup();
 
   async function testPanel(browser, standAlone = true) {
     let panel = getPanelForNode(browser);
     let arrowContent = document.getAnonymousElementByAttribute(panel, "class", "panel-arrowcontent");
 
     let panelStyle = getComputedStyle(arrowContent);
 
-    let viewNode = browser.parentNode === panel ? browser : browser.parentNode;
+    let stack = browser.parentNode;
+    let viewNode = stack.parentNode === panel ? browser : stack.parentNode;
     let viewStyle = getComputedStyle(viewNode);
 
     let props = ["borderTopLeftRadius", "borderTopRightRadius",
                  "borderBottomRightRadius", "borderBottomLeftRadius"];
 
     /* eslint-disable mozilla/no-cpows-in-tests */
     let bodyStyle = await ContentTask.spawn(browser, props, async function(props) {
       let bodyStyle = content.getComputedStyle(content.document.body);
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -1229,16 +1229,17 @@ notification.pluginVulnerable > .notific
   margin-inline-end: 0 !important;
 }
 
 .browser-extension-panel > .panel-arrowcontainer > .panel-arrowcontent {
   padding: 0;
   overflow: hidden;
 }
 
-.webextension-popup-browser {
+.webextension-popup-browser,
+.webextension-popup-stack {
   border-radius: inherit;
 }
 
 /* Prevent movement in the restore-tabs-button when it's clicked. */
 .restore-tabs-button:hover:active:not([disabled="true"]) {
   padding: 3px;
 }
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -2057,11 +2057,12 @@ html|*.addon-webext-perm-list {
   padding: 0;
   overflow: hidden;
 }
 
 .cui-widget-panelview[id^=PanelUI-webext-] {
   border-radius: 3.5px;
 }
 
-.webextension-popup-browser {
+.webextension-popup-browser,
+.webextension-popup-stack {
   border-radius: inherit;
 }
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -1899,17 +1899,18 @@ panel[touchmode] .PanelUI-subView #appMe
 }
 
 @media (-moz-os-version: windows-win7) {
   .cui-widget-panelview[id^=PanelUI-webext-] {
     border-radius: 4px;
   }
 }
 
-.webextension-popup-browser {
+.webextension-popup-browser,
+.webextension-popup-stack {
   border-radius: inherit;
 }
 
 .contentSelectDropdown-ingroup > .menu-iconic-text {
   padding-inline-start: 20px;
 }
 
 #ContentSelectDropdown > menupopup {
--- a/docshell/test/browser/browser.ini
+++ b/docshell/test/browser/browser.ini
@@ -72,16 +72,17 @@ support-files =
 [browser_bug503832.js]
 [browser_bug554155.js]
 [browser_bug655270.js]
 [browser_bug655273.js]
 [browser_bug670318.js]
 [browser_bug673467.js]
 [browser_bug852909.js]
 [browser_bug92473.js]
+[browser_dataURI_unique_opaque_origin.js]
 [browser_uriFixupIntegration.js]
 [browser_uriFixupAlternateRedirects.js]
 support-files =
   redirect_to_example.sjs
 [browser_loadDisallowInherit.js]
 [browser_loadURI.js]
 [browser_multiple_pushState.js]
 [browser_onbeforeunload_navigation.js]
new file mode 100644
--- /dev/null
+++ b/docshell/test/browser/browser_dataURI_unique_opaque_origin.js
@@ -0,0 +1,29 @@
+add_task(async function setup() {
+  Services.prefs.setBoolPref("security.data_uri.unique_opaque_origin", true);
+
+  registerCleanupFunction(function() {
+    Services.prefs.clearUserPref("security.data_uri.unique_opaque_origin");
+  });
+});
+
+add_task(async function test_dataURI_unique_opaque_origin() {
+  let tab = BrowserTestUtils.addTab(gBrowser, "http://example.com");
+  let browser = tab.linkedBrowser;
+  await BrowserTestUtils.browserLoaded(browser);
+
+  let pagePrincipal = browser.contentPrincipal;
+  info("pagePrincial " + pagePrincipal.origin);
+
+  browser.loadURIWithFlags("data:text/html,hi", 0, null, null, null);
+  await BrowserTestUtils.browserLoaded(browser);
+
+  await ContentTask.spawn(browser, { principal: pagePrincipal }, async function(args) {
+    info("data URI principal: " + content.document.nodePrincipal.origin);
+    Assert.ok(content.document.nodePrincipal.isNullPrincipal,
+              "data: URI should have NullPrincipal.");
+    Assert.ok(!content.document.nodePrincipal.equals(args.principal),
+              "data: URI should have unique opaque origin.");
+  });
+
+  gBrowser.removeTab(tab);
+});
--- a/docshell/test/browser/browser_loadDisallowInherit.js
+++ b/docshell/test/browser/browser_loadDisallowInherit.js
@@ -1,19 +1,26 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function test() {
   waitForExplicitFinish();
 
-  let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
+  // data: URI will only inherit principal only when the pref is false.
+  Services.prefs.setBoolPref("security.data_uri.unique_opaque_origin", false);
   registerCleanupFunction(function () {
-    gBrowser.removeTab(tab);
+    Services.prefs.clearUserPref("security.data_uri.unique_opaque_origin");
   });
 
+  executeSoon(startTest);
+}
+
+function startTest() {
+  let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
+
   let browser = gBrowser.getBrowserForTab(tab);
 
   function loadURL(url, flags, func) {
     browser.addEventListener("load", function loadListener(e) {
       if (browser.currentURI.spec != url)
         return;
       browser.removeEventListener(e.type, loadListener, true);
       func();
@@ -33,33 +40,35 @@ function test() {
 
         // Now load the URL and disallow inheriting the principal
         let webNav = Components.interfaces.nsIWebNavigation;
         loadURL(url, webNav.LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL, function () {
           let newPrincipal = browser.contentPrincipal;
           ok(newPrincipal, "got inner principal");
           ok(!newPrincipal.equals(pagePrincipal),
              url + " should not inherit principal when loaded with DISALLOW_INHERIT_OWNER");
-  
+
           func();
         });
       });
     });
   }
 
   let urls = [
     "data:text/html,<body>hi",
     // We used to test javascript: here as well, but now that we no longer run
     // javascript: in a sandbox, we end up not running it at all in the
     // DISALLOW_INHERIT_OWNER case, so never actually do a load for it at all.
   ];
 
   function nextTest() {
     let url = urls.shift();
-    if (url)
+    if (url) {
       testURL(url, nextTest);
-    else
+    } else {
+      gBrowser.removeTab(tab);
       finish();
+    }
   }
-  
+
   nextTest();
 }
 
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -19,16 +19,17 @@
 #include "nsIDocShellLoadInfo.h"
 #include "nsIDocument.h"
 #include "nsIDOMCustomEvent.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLObjectElement.h"
 #include "nsIExternalProtocolHandler.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIObjectFrame.h"
+#include "nsIOService.h"
 #include "nsIPermissionManager.h"
 #include "nsPluginHost.h"
 #include "nsPluginInstanceOwner.h"
 #include "nsJSNPRuntime.h"
 #include "nsINestedURI.h"
 #include "nsIPresShell.h"
 #include "nsScriptSecurityManager.h"
 #include "nsIScriptSecurityManager.h"
@@ -2476,18 +2477,24 @@ nsObjectLoadingContent::OpenChannel()
   RefPtr<ObjectInterfaceRequestorShim> shim =
     new ObjectInterfaceRequestorShim(this);
 
   bool isSandBoxed = doc->GetSandboxFlags() & SANDBOXED_ORIGIN;
   bool inherit = nsContentUtils::ChannelShouldInheritPrincipal(thisContent->NodePrincipal(),
                                                                mURI,
                                                                true,   // aInheritForAboutBlank
                                                                false); // aForceInherit
-  nsSecurityFlags securityFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
-  if (inherit) {
+  nsSecurityFlags securityFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
+
+  bool isData;
+  bool isURIUniqueOrigin = nsIOService::IsDataURIUniqueOpaqueOrigin() &&
+                           NS_SUCCEEDED(mURI->SchemeIs("data", &isData)) &&
+                           isData;
+
+  if (inherit && !isURIUniqueOrigin) {
     securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
   }
   if (isSandBoxed) {
     securityFlags |= nsILoadInfo::SEC_SANDBOXED;
   }
 
   nsContentPolicyType contentPolicyType = GetContentPolicyType();
 
--- a/dom/base/test/test_data_uri.html
+++ b/dom/base/test/test_data_uri.html
@@ -1,23 +1,23 @@
 <html>
 <head>
   <title>Tests for Data URI</title>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
 
 <script>
+SimpleTest.waitForExplicitFinish();
+
 SpecialPowers.setBoolPref("security.data_uri.unique_opaque_origin", true);
 SimpleTest.registerCleanupFunction(() => {
   SpecialPowers.clearUserPref("security.data_uri.unique_opaque_origin");
 });
 
-SimpleTest.waitForExplicitFinish();
-
 function imgListener(img) {
   return new Promise((resolve, reject) => {
     img.addEventListener("load", () => resolve());
     img.addEventListener("error", () => reject());
   });
 }
 
 function runTests()
@@ -83,17 +83,39 @@ function runTests()
       }});
   }).then(() => {
     document.fonts.add(new FontFace("test", "url(data:font/opentype;base64,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AC4AIABDAG8AcAB5AHIAaQBnAGgAdAAgAGkAbgBmAG8AIABwAGUAbgBkAGkAbgBnAC4AbABvAGEAZAB0AGUAcwB0AFIAZQBnAHUAbABhAHIAdwBlAGIAZgBvAG4AdABsAG8AYQBkAHQAZQBzAHQAIABSAGUAZwB1AGwAYQByAFYAZQByAHMAaQBvAG4AIAAwADAAMQAuADAAMAAxAEIAYQBzAGUAZAAgAG8AbgAgAEwAZQBhAGcAdQBlACAARwBvAHQAaABpAGMAIABiAHkAIABMAGUAYQBnAHUAZQAgAG8AZgAgAE0AbwB2AGUAYQBiAGwAZQAgAFQAeQBwAGUALAAgAG0AbwBkAGkAZgBpAGUAZAAgAGIAeQAgAEoAbwBoAG4AIABEAGEAZwBnAGUAdAB0AGgAdAB0AHAAOgAvAC8AdwB3AHcALgB0AGgAZQBsAGUAYQBnAHUAZQBvAGYAbQBvAHYAZQBhAGIAbABlAHQAeQBwAGUALgBjAG8AbQAvAGwAZQBhAGcAdQBlAC0AZwBvAHQAaABpAGMAQQBsAGwAIABmAG8AbgB0AHMAIABmAHIAbwBtACAAVABoAGUAIABMAGUAYQBnAHUAZQAgAG8AZgAgAE0AbwB2AGUAYQBiAGwAZQAgAFQAeQBwAGUAIABhAHIAZQAgAHMAdQBiAGoAZQBjAHQAIAB0AG8AIAB0AGgAZQAgAE8AcABlAG4AIABGAG8AbgB0ACAATABpAGMAZQBuAHMAZQBoAHQAdABwADoALwAvAHMAYwByAGkAcAB0AHMALgBzAGkAbAAuAG8AcgBnAC8ATwBGAEwAAgAAAAAAAP9nAGYAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyADMANAA1ADYANwA4ADkAOgA7ADwAPQA+AD8AQABBAEIAQwBEAEUARgBHAEgASQBKAEsATABNAE4ATwBQAFEAUgBTAFQAVQBWAFcAWABZAFoAWwBcAF0AXgBfAGAAYQECAKMAhACFAJYAjgCLAQMAigDaAI0AwwDeAKIArQDJAMcArgBiAGMAkABkAMsAZQDIAMoAzwDMAM0AzgDpAGYA0wDQANEArwBnAJEA1gDUANUAaADrAO0AiQBqAGkAawBtAGwAbgCgAG8AcQBwAHIAcwB1AHQAdgB3AOoAeAB6AHkAewB9AHwAoQB/AH4AgACBAOwA7gC6ANcA4gDjALAAsQDkAOUAuwDmAOcA2ADhANsA3ADdAOAA2QDfAQQBBQEGAQcBCAEJAQoBCwEMAQ0BDgEPARABEQCyALMAtgC3AMQAtAC1AMUAhwCrARIBEwEUAIwA7wEVARYBFwd1bmkwMEEwB3VuaTAwQUQHdW5pMjAwMAd1bmkyMDAxB3VuaTIwMDIHdW5pMjAwMwd1bmkyMDA0B3VuaTIwMDUHdW5pMjAwNgd1bmkyMDA3B3VuaTIwMDgHdW5pMjAwOQd1bmkyMDBBB3VuaTIwMTAHdW5pMjAxMQpmaWd1cmVkYXNoB3VuaTIwMkYHdW5pMjA1RgRFdXJvB3VuaUUwMDAHdW5pRkIwMQd1bmlGQjAyAAAAAQAB//8ADwAAAAEAAAAAyYlvMQAAAADGp3m3AAAAAMrhKHcAAQAAAAwAAAAWAAAAAgABAAEA3wABAAQAAAABAAAAAAABAAAACgAuADwAAkRGTFQADmxhdG4AGAAEAAAAAP//AAAABAAAAAD//wABAAAAAVRTVDEACAAAAAEAAAABAAQAAQAAAAEACAACAA4ABABEADMANgBWAAEABAAkACkALAAvAAA=)"));
     return document.fonts.ready;
   }).then(() => {
     is(document.fonts.size, 1, "should load data:font");
   });
 
-  Promise.all([p1, p2, p3]).then(() => {
+  var obj_doc = document.getElementById("obj_doc");
+  obj_doc.data="data:text/html,%3Cbody%3E%3Cbutton%3EChild%3C/button%3E%3C/body%3E"
+  let p4 = new Promise((resolve, reject) => {
+    obj_doc.onload = function() {
+      ok(SpecialPowers.wrap(obj_doc).contentDocument.nodePrincipal.isNullPrincipal,
+         "obj_doc.document should have NullPrincipal.");
+      resolve();
+    }
+  });
+
+  var obj_svg = document.getElementById("obj_svg");
+  obj_svg.data='data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 200 200"><circle cx="100" cy="100" r="100" fill="green" fill-opacity="0.8"/></svg>'
+  let p5 = new Promise((resolve, reject) => {
+    obj_svg.onload = function() {
+      ok(SpecialPowers.wrap(obj_svg).contentDocument.nodePrincipal.isNullPrincipal,
+         "obj_svg.contentDocument should have NullPrincipal.");
+      ok(SpecialPowers.wrap(obj_svg).getSVGDocument().nodePrincipal.isNullPrincipal,
+         "obj_svg.getSVGDocument() should have NullPrincipal.");
+      resolve();
+    }
+  });
+
+  Promise.all([p1, p2, p3, p4, p5]).then(() => {
     SimpleTest.finish();
   }).catch((e) => {
     ok(false, "throwing " + e);
     SimpleTest.finish();
   });
 }
 </script>
 
@@ -102,11 +124,15 @@ function runTests()
       onerror="ok(false, 'data:text/css should be same origin');">
 
 <body onload="runTests()">
 <img style="width: 100px; height: 100px;"
      src="data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%18%00%00%00%18%02%03%00%00%00%9D%19%D5k%00%00%00%04gAMA%00%00%B1%8F%0B%FCa%05%00%00%00%0CPLTE%FF%FF%FF%FF%FF%FF%F7%DC%13%00%00%00%03%80%01X%00%00%00%01tRNS%08N%3DPT%00%00%00%01bKGD%00%88%05%1DH%00%00%00%09pHYs%00%00%0B%11%00%00%0B%11%01%7Fd_%91%00%00%00%07tIME%07%D2%05%0C%14%0C%0D%D8%3F%1FQ%00%00%00%5CIDATx%9C%7D%8E%CB%09%C0%20%10D%07r%B7%20%2F%E9wV0%15h%EA%D9%12D4%BB%C1x%CC%5C%1E%0C%CC%07%C0%9C0%9Dd7()%C0A%D3%8D%E0%B8%10%1DiCHM%D0%AC%D2d%C3M%F1%B4%E7%FF%10%0BY%AC%25%93%CD%CBF%B5%B2%C0%3Alh%CD%AE%13%DF%A5%F7%E0%03byW%09A%B4%F3%E2%00%00%00%00IEND%AEB%60%82"
      id="img">
 <iframe id="iframe"></iframe>
 <iframe id="iframe1" ></iframe>
-<canvas id="canvas" class="output" width="100" height="50">
+<canvas id="canvas" class="output" width="100" height="50"></canvas>
+
+<object id="obj_doc"></object>
+<object id="obj_svg"></object>
+
 </body>
 </html>
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -927,33 +927,32 @@ public:
   {
     if (mContext) {
       mContext->mUserDatas.RemoveElement(this);
     }
   }
 
   static void PreTransactionCallback(void* aData)
   {
-    auto self = static_cast<CanvasRenderingContext2DUserData*>(aData);
-    CanvasRenderingContext2D* context = self->mContext;
+    CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(aData);
     if (!context || !context->mTarget)
       return;
 
     context->OnStableState();
   }
 
   static void DidTransactionCallback(void* aData)
   {
-    auto self = static_cast<CanvasRenderingContext2DUserData*>(aData);
-    if (self->mContext) {
-      self->mContext->MarkContextClean();
-      if (self->mContext->mDrawObserver) {
-        if (self->mContext->mDrawObserver->FrameEnd()) {
+    CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(aData);
+    if (context) {
+      context->MarkContextClean();
+      if (context->mDrawObserver) {
+        if (context->mDrawObserver->FrameEnd()) {
           // Note that this call deletes and nulls out mDrawObserver:
-          self->mContext->RemoveDrawObserver();
+          context->RemoveDrawObserver();
         }
       }
     }
   }
   bool IsForContext(CanvasRenderingContext2D* aContext)
   {
     return mContext == aContext;
   }
@@ -6230,33 +6229,33 @@ CanvasRenderingContext2D::GetCanvasLayer
     return nullptr;
   }
 
   if (!mResetLayer && aOldLayer) {
     auto userData =
       static_cast<CanvasRenderingContext2DUserData*>(
         aOldLayer->GetUserData(&g2DContextLayerUserData));
 
-    CanvasLayer::Data data;
+    CanvasInitializeData data;
 
     if (mIsSkiaGL) {
       GLuint skiaGLTex = SkiaGLTex();
       if (skiaGLTex) {
         SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
         MOZ_ASSERT(glue);
         data.mGLContext = glue->GetGLContext();
         data.mFrontbufferGLTex = skiaGLTex;
       }
     }
 
     data.mBufferProvider = mBufferProvider;
 
     if (userData &&
         userData->IsForContext(this) &&
-        static_cast<CanvasLayer*>(aOldLayer)->IsDataValid(data)) {
+        static_cast<CanvasLayer*>(aOldLayer)->CreateOrGetCanvasRenderer()->IsDataValid(data)) {
       RefPtr<Layer> ret = aOldLayer;
       return ret.forget();
     }
   }
 
   RefPtr<CanvasLayer> canvasLayer = aManager->CreateCanvasLayer();
   if (!canvasLayer) {
     NS_WARNING("CreateCanvasLayer returned null!");
@@ -6273,48 +6272,55 @@ CanvasRenderingContext2D::GetCanvasLayer
   // notifications after this paint.
 
   // The layer will be destroyed when we tear down the presentation
   // (at the latest), at which time this userData will be destroyed,
   // releasing the reference to the element.
   // The userData will receive DidTransactionCallbacks, which flush the
   // the invalidation state to indicate that the canvas is up to date.
   userData = new CanvasRenderingContext2DUserData(this);
-  canvasLayer->SetDidTransactionCallback(
-          CanvasRenderingContext2DUserData::DidTransactionCallback, userData);
   canvasLayer->SetUserData(&g2DContextLayerUserData, userData);
 
-  CanvasLayer::Data data;
+  CanvasRenderer* canvasRenderer = canvasLayer->CreateOrGetCanvasRenderer();
+  InitializeCanvasRenderer(aBuilder, canvasRenderer, aMirror);
+  uint32_t flags = mOpaque ? Layer::CONTENT_OPAQUE : 0;
+  canvasLayer->SetContentFlags(flags);
+
+  mResetLayer = false;
+
+  return canvasLayer.forget();
+}
+
+void
+CanvasRenderingContext2D::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+                                                   CanvasRenderer* aRenderer,
+                                                   bool aMirror)
+{
+  CanvasInitializeData data;
   data.mSize = GetSize();
   data.mHasAlpha = !mOpaque;
-
-  canvasLayer->SetPreTransactionCallback(
-          CanvasRenderingContext2DUserData::PreTransactionCallback, userData);
-
+  data.mPreTransCallback = CanvasRenderingContext2DUserData::PreTransactionCallback;
+  data.mPreTransCallbackData = this;
+  data.mDidTransCallback = CanvasRenderingContext2DUserData::DidTransactionCallback;
+  data.mDidTransCallbackData = this;
 
   if (mIsSkiaGL) {
       GLuint skiaGLTex = SkiaGLTex();
       if (skiaGLTex) {
         SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
         MOZ_ASSERT(glue);
         data.mGLContext = glue->GetGLContext();
         data.mFrontbufferGLTex = skiaGLTex;
       }
   }
 
   data.mBufferProvider = mBufferProvider;
 
-  canvasLayer->Initialize(data);
-  uint32_t flags = mOpaque ? Layer::CONTENT_OPAQUE : 0;
-  canvasLayer->SetContentFlags(flags);
-  canvasLayer->Updated();
-
-  mResetLayer = false;
-
-  return canvasLayer.forget();
+  aRenderer->Initialize(data);
+  aRenderer->SetDirty();
 }
 
 void
 CanvasRenderingContext2D::MarkContextClean()
 {
   if (mInvalidateCount > 0) {
     mPredictManyRedrawCalls = mInvalidateCount > kCanvasMaxInvalidateCount;
   }
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -463,16 +463,19 @@ public:
 
   virtual void SetIsOpaque(bool aIsOpaque) override;
   bool GetIsOpaque() override { return mOpaque; }
   NS_IMETHOD Reset() override;
   already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                          Layer* aOldLayer,
                                          LayerManager* aManager,
                                          bool aMirror = false) override;
+  void InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+                                CanvasRenderer* aRenderer,
+                                bool aMirror = false) override;
   virtual bool ShouldForceInactiveLayer(LayerManager* aManager) override;
   void MarkContextClean() override;
   void MarkContextCleanForFrameCapture() override;
   bool IsContextCleanForFrameCapture() override;
   NS_IMETHOD SetIsIPC(bool aIsIPC) override;
   // this rect is in canvas device space
   void Redraw(const mozilla::gfx::Rect& aR);
   NS_IMETHOD Redraw(const gfxRect& aR) override { Redraw(ToRect(aR)); return NS_OK; }
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -1282,31 +1282,27 @@ public:
     explicit WebGLContextUserData(HTMLCanvasElement* canvas)
         : mCanvas(canvas)
     {}
 
     /* PreTransactionCallback gets called by the Layers code every time the
      * WebGL canvas is going to be composited.
      */
     static void PreTransactionCallback(void* data) {
-        WebGLContextUserData* userdata = static_cast<WebGLContextUserData*>(data);
-        HTMLCanvasElement* canvas = userdata->mCanvas;
-        WebGLContext* webgl = static_cast<WebGLContext*>(canvas->GetContextAtIndex(0));
+        WebGLContext* webgl = static_cast<WebGLContext*>(data);
 
         // Prepare the context for composition
         webgl->BeginComposition();
     }
 
     /** DidTransactionCallback gets called by the Layers code everytime the WebGL canvas gets composite,
       * so it really is the right place to put actions that have to be performed upon compositing
       */
     static void DidTransactionCallback(void* data) {
-        WebGLContextUserData* userdata = static_cast<WebGLContextUserData*>(data);
-        HTMLCanvasElement* canvas = userdata->mCanvas;
-        WebGLContext* webgl = static_cast<WebGLContext*>(canvas->GetContextAtIndex(0));
+        WebGLContext* webgl = static_cast<WebGLContext*>(data);
 
         // Clean up the context after composition
         webgl->EndComposition();
     }
 
 private:
     RefPtr<HTMLCanvasElement> mCanvas;
 };
@@ -1329,56 +1325,68 @@ WebGLContext::GetCanvasLayer(nsDisplayLi
     RefPtr<CanvasLayer> canvasLayer = manager->CreateCanvasLayer();
     if (!canvasLayer) {
         NS_WARNING("CreateCanvasLayer returned null!");
         return nullptr;
     }
 
     WebGLContextUserData* userData = nullptr;
     if (builder->IsPaintingToWindow() && mCanvasElement && !aMirror) {
+        userData = new WebGLContextUserData(mCanvasElement);
+    }
+
+    canvasLayer->SetUserData(aMirror ? &gWebGLMirrorLayerUserData : &gWebGLLayerUserData, userData);
+
+    CanvasRenderer* canvasRenderer = canvasLayer->CreateOrGetCanvasRenderer();
+    InitializeCanvasRenderer(builder, canvasRenderer, aMirror);
+    uint32_t flags = gl->Caps().alpha ? 0 : Layer::CONTENT_OPAQUE;
+    canvasLayer->SetContentFlags(flags);
+
+    mResetLayer = false;
+    // We only wish to update mLayerIsMirror when a new layer is returned.
+    // If a cached layer is returned above, aMirror is not changing since
+    // the last cached layer was created and mLayerIsMirror is still valid.
+    mLayerIsMirror = aMirror;
+
+    return canvasLayer.forget();
+}
+
+void
+WebGLContext::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+                                       CanvasRenderer* aRenderer,
+                                       bool aMirror)
+{
+    CanvasInitializeData data;
+    if (aBuilder->IsPaintingToWindow() && mCanvasElement && !aMirror) {
         // Make the layer tell us whenever a transaction finishes (including
         // the current transaction), so we can clear our invalidation state and
         // start invalidating again. We need to do this for the layer that is
         // being painted to a window (there shouldn't be more than one at a time,
         // and if there is, flushing the invalidation state more often than
         // necessary is harmless).
 
         // The layer will be destroyed when we tear down the presentation
         // (at the latest), at which time this userData will be destroyed,
         // releasing the reference to the element.
         // The userData will receive DidTransactionCallbacks, which flush the
         // the invalidation state to indicate that the canvas is up to date.
-        userData = new WebGLContextUserData(mCanvasElement);
-        canvasLayer->SetDidTransactionCallback(
-            WebGLContextUserData::DidTransactionCallback, userData);
-        canvasLayer->SetPreTransactionCallback(
-            WebGLContextUserData::PreTransactionCallback, userData);
+        data.mPreTransCallback = WebGLContextUserData::PreTransactionCallback;
+        data.mPreTransCallbackData = this;
+        data.mDidTransCallback = WebGLContextUserData::DidTransactionCallback;
+        data.mDidTransCallbackData = this;
     }
 
-    canvasLayer->SetUserData(aMirror ? &gWebGLMirrorLayerUserData : &gWebGLLayerUserData, userData);
-
-    CanvasLayer::Data data;
     data.mGLContext = gl;
     data.mSize = nsIntSize(mWidth, mHeight);
     data.mHasAlpha = gl->Caps().alpha;
     data.mIsGLAlphaPremult = IsPremultAlpha() || !data.mHasAlpha;
     data.mIsMirror = aMirror;
 
-    canvasLayer->Initialize(data);
-    uint32_t flags = gl->Caps().alpha ? 0 : Layer::CONTENT_OPAQUE;
-    canvasLayer->SetContentFlags(flags);
-    canvasLayer->Updated();
-
-    mResetLayer = false;
-    // We only wish to update mLayerIsMirror when a new layer is returned.
-    // If a cached layer is returned above, aMirror is not changing since
-    // the last cached layer was created and mLayerIsMirror is still valid.
-    mLayerIsMirror = aMirror;
-
-    return canvasLayer.forget();
+    aRenderer->Initialize(data);
+    aRenderer->SetDirty();
 }
 
 layers::LayersBackend
 WebGLContext::GetCompositorBackendType() const
 {
     if (mCanvasElement) {
         return mCanvasElement->GetCompositorBackendType();
     } else if (mOffscreenCanvas) {
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -457,16 +457,20 @@ public:
     }
 
     void InvalidateResolveCacheForTextureWithTexUnit(const GLuint);
 
     already_AddRefed<Layer>
     GetCanvasLayer(nsDisplayListBuilder* builder, Layer* oldLayer,
                    LayerManager* manager,
                    bool aMirror = false) override;
+    void
+    InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+                             CanvasRenderer* aRenderer,
+                             bool aMirror = false) override;
 
     // Note that 'clean' here refers to its invalidation state, not the
     // contents of the buffer.
     void MarkContextClean() override { mInvalidated = false; }
 
     void MarkContextCleanForFrameCapture() override { mCapturedFrameInvalidated = false; }
 
     bool IsContextCleanForFrameCapture() override { return !mCapturedFrameInvalidated; }
--- a/dom/canvas/nsICanvasRenderingContextInternal.h
+++ b/dom/canvas/nsICanvasRenderingContextInternal.h
@@ -21,30 +21,32 @@
 { 0xb84f2fed, 0x9d4b, 0x430b, \
   { 0xbd, 0xfb, 0x85, 0x57, 0x8a, 0xc2, 0xb4, 0x4b } }
 
 class nsDisplayListBuilder;
 
 namespace mozilla {
 namespace layers {
 class CanvasLayer;
+class CanvasRenderer;
 class Layer;
 class LayerManager;
 } // namespace layers
 namespace gfx {
 class SourceSurface;
 } // namespace gfx
 } // namespace mozilla
 
 class nsICanvasRenderingContextInternal :
   public nsISupports,
   public nsAPostRefreshObserver
 {
 public:
   typedef mozilla::layers::CanvasLayer CanvasLayer;
+  typedef mozilla::layers::CanvasRenderer CanvasRenderer;
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayerManager LayerManager;
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
 
   void SetCanvasElement(mozilla::dom::HTMLCanvasElement* parentCanvas)
   {
     RemovePostRefreshObserver();
@@ -134,16 +136,19 @@ public:
   NS_IMETHOD Reset() = 0;
 
   // Return the CanvasLayer for this context, creating
   // one for the given layer manager if not available.
   virtual already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* builder,
                                                  Layer *oldLayer,
                                                  LayerManager *manager,
                                                  bool aMirror = false) = 0;
+  virtual void InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+                                        CanvasRenderer* aRenderer,
+                                        bool aMirror = false) { };
 
   // Return true if the canvas should be forced to be "inactive" to ensure
   // it can be drawn to the screen even if it's too large to be blitted by
   // an accelerated CanvasLayer.
   virtual bool ShouldForceInactiveLayer(LayerManager *manager) { return false; }
 
   virtual void MarkContextClean() = 0;
 
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -1,16 +1,17 @@
 /* -*- 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/dom/HTMLCanvasElement.h"
 
+#include "gfxPrefs.h"
 #include "ImageEncoder.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "Layers.h"
 #include "MediaSegment.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Base64.h"
 #include "mozilla/CheckedInt.h"
@@ -19,16 +20,17 @@
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/HTMLCanvasElementBinding.h"
 #include "mozilla/dom/MediaStreamTrack.h"
 #include "mozilla/dom/MouseEvent.h"
 #include "mozilla/dom/OffscreenCanvas.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/layers/AsyncCanvasRenderer.h"
+#include "mozilla/layers/WebRenderCanvasRenderer.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "nsAttrValueInlines.h"
 #include "nsContentUtils.h"
 #include "nsDisplayList.h"
 #include "nsDOMJSUtils.h"
 #include "nsIScriptSecurityManager.h"
@@ -1054,28 +1056,48 @@ HTMLCanvasElement::InvalidateCanvasConte
   // We don't need to flush anything here; if there's no frame or if
   // we plan to reframe we don't need to invalidate it anyway.
   nsIFrame *frame = GetPrimaryFrame();
   if (!frame)
     return;
 
   ActiveLayerTracker::NotifyContentChange(frame);
 
-  Layer* layer = nullptr;
-  if (damageRect) {
-    nsIntSize size = GetWidthHeight();
-    if (size.width != 0 && size.height != 0) {
-      gfx::IntRect invalRect = gfx::IntRect::Truncate(*damageRect);
-      layer = frame->InvalidateLayer(nsDisplayItem::TYPE_CANVAS, &invalRect);
+  // When using layers-free WebRender, we cannot invalidate the layer (because there isn't one).
+  // Instead, we mark the CanvasRenderer dirty and scheduling an empty transaction
+  // which is effectively equivalent.
+  CanvasRenderer* renderer = nullptr;
+  if (gfxPrefs::WebRenderLayersFree() && frame->HasProperty(nsIFrame::WebRenderUserDataProperty())) {
+    nsIFrame::WebRenderUserDataTable* userDataTable =
+      frame->GetProperty(nsIFrame::WebRenderUserDataProperty());
+    RefPtr<WebRenderUserData> data;
+    userDataTable->Get(nsDisplayItem::TYPE_CANVAS, getter_AddRefs(data));
+    if (data && data->AsCanvasData()) {
+      renderer = data->AsCanvasData()->GetCanvasRenderer();
     }
+  }
+
+  if (renderer) {
+    renderer->SetDirty();
+    frame->SchedulePaint(nsIFrame::PAINT_COMPOSITE_ONLY);
   } else {
-    layer = frame->InvalidateLayer(nsDisplayItem::TYPE_CANVAS);
-  }
-  if (layer) {
-    static_cast<CanvasLayer*>(layer)->Updated();
+    Layer* layer = nullptr;
+    if (damageRect) {
+      nsIntSize size = GetWidthHeight();
+      if (size.width != 0 && size.height != 0) {
+        gfx::IntRect invalRect = gfx::IntRect::Truncate(*damageRect);
+        layer = frame->InvalidateLayer(nsDisplayItem::TYPE_CANVAS, &invalRect);
+      }
+    } else {
+      layer = frame->InvalidateLayer(nsDisplayItem::TYPE_CANVAS);
+    }
+
+    if (layer) {
+      static_cast<CanvasLayer*>(layer)->Updated();
+    }
   }
 
   /*
    * Treat canvas invalidations as animation activity for JS. Frequently
    * invalidating a canvas will feed into heuristics and cause JIT code to be
    * kept around longer, for smoother animations.
    */
   nsCOMPtr<nsIGlobalObject> global =
@@ -1160,28 +1182,42 @@ HTMLCanvasElement::GetCanvasLayer(nsDisp
     if (!layer) {
       NS_WARNING("CreateCanvasLayer failed!");
       return nullptr;
     }
 
     LayerUserData* userData = nullptr;
     layer->SetUserData(&sOffscreenCanvasLayerUserDataDummy, userData);
 
-    CanvasLayer::Data data;
-    data.mRenderer = GetAsyncCanvasRenderer();
-    data.mSize = GetWidthHeight();
-    layer->Initialize(data);
+    CanvasRenderer* canvasRenderer = layer->CreateOrGetCanvasRenderer();
+    InitializeCanvasRenderer(aBuilder, canvasRenderer);
 
     layer->Updated();
     return layer.forget();
   }
 
   return nullptr;
 }
 
+void
+HTMLCanvasElement::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+                                            CanvasRenderer* aRenderer)
+{
+  if (mCurrentContext) {
+    mCurrentContext->InitializeCanvasRenderer(aBuilder, aRenderer);
+  }
+
+  if (mOffscreenCanvas) {
+    CanvasInitializeData data;
+    data.mRenderer = GetAsyncCanvasRenderer();
+    data.mSize = GetWidthHeight();
+    aRenderer->Initialize(data);
+  }
+}
+
 bool
 HTMLCanvasElement::ShouldForceInactiveLayer(LayerManager* aManager)
 {
   if (mCurrentContext) {
     return mCurrentContext->ShouldForceInactiveLayer(aManager);
   }
 
   if (mOffscreenCanvas) {
--- a/dom/html/HTMLCanvasElement.h
+++ b/dom/html/HTMLCanvasElement.h
@@ -25,16 +25,17 @@ class nsICanvasRenderingContextInternal;
 class nsITimerCallback;
 
 namespace mozilla {
 
 class WebGLContext;
 
 namespace layers {
 class AsyncCanvasRenderer;
+class CanvasRenderer;
 class CanvasLayer;
 class Image;
 class Layer;
 class LayerManager;
 class SharedSurfaceTextureClient;
 } // namespace layers
 namespace gfx {
 class SourceSurface;
@@ -119,16 +120,17 @@ class HTMLCanvasElement final : public n
                                 public CanvasRenderingContextHelper
 {
   enum {
     DEFAULT_CANVAS_WIDTH = 300,
     DEFAULT_CANVAS_HEIGHT = 150
   };
 
   typedef layers::AsyncCanvasRenderer AsyncCanvasRenderer;
+  typedef layers::CanvasRenderer CanvasRenderer;
   typedef layers::CanvasLayer CanvasLayer;
   typedef layers::Layer Layer;
   typedef layers::LayerManager LayerManager;
 
 public:
   explicit HTMLCanvasElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLCanvasElement, canvas)
@@ -303,16 +305,18 @@ public:
 
   /*
    * Helpers called by various users of Canvas
    */
 
   already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                          Layer *aOldLayer,
                                          LayerManager *aManager);
+  void InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+                                CanvasRenderer* aRenderer);
   // Should return true if the canvas layer should always be marked inactive.
   // We should return true here if we can't do accelerated compositing with
   // a non-BasicCanvasLayer.
   bool ShouldForceInactiveLayer(LayerManager *aManager);
 
   // Call this whenever we need future changes to the canvas
   // to trigger fresh invalidation requests. This needs to be called
   // whenever we render the canvas contents to the screen, or whenever we
--- a/gfx/gl/GLContextEGL.h
+++ b/gfx/gl/GLContextEGL.h
@@ -128,14 +128,18 @@ protected:
     bool mIsDoubleBuffered;
     bool mCanBindToTexture;
     bool mShareWithEGLImage;
     bool mOwnsContext;
 
     static EGLSurface CreatePBufferSurfaceTryingPowerOfTwo(EGLConfig config,
                                                            EGLenum bindToTextureFormat,
                                                            gfx::IntSize& pbsize);
+#if defined(MOZ_WIDGET_ANDROID)
+public:
+    EGLSurface CreateCompatibleSurface(void* aWindow);
+#endif // defined(MOZ_WIDGET_ANDROID)
 };
 
 } // namespace gl
 } // namespace mozilla
 
 #endif // GLCONTEXTEGL_H_
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -763,43 +763,52 @@ GLContextProviderEGL::CreateForWindow(ns
                                       bool aWebRender,
                                       bool aForceAccelerated)
 {
     MOZ_ASSERT(aWidget);
     return GLContextEGLFactory::Create(GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget),
                                        aWebRender);
 }
 
-#if defined(ANDROID)
+#if defined(MOZ_WIDGET_ANDROID)
 EGLSurface
-GLContextProviderEGL::CreateEGLSurface(void* aWindow)
+GLContextEGL::CreateCompatibleSurface(void* aWindow)
+{
+    if (mConfig == EGL_NO_CONFIG) {
+        MOZ_CRASH("GFX: Failed with invalid EGLConfig 2!\n");
+    }
+
+    return GLContextProviderEGL::CreateEGLSurface(aWindow, mConfig);
+}
+
+/* static */ EGLSurface
+GLContextProviderEGL::CreateEGLSurface(void* aWindow, EGLConfig aConfig)
 {
     // NOTE: aWindow is an ANativeWindow
     nsCString discardFailureId;
     if (!sEGLLibrary.EnsureInitialized(false, &discardFailureId)) {
         MOZ_CRASH("GFX: Failed to load EGL library 4!\n");
     }
-
-    EGLConfig config;
-    if (!CreateConfig(&config, /* aEnableDepthBuffer */ false)) {
+    EGLConfig config = aConfig;
+    if (!config && !CreateConfig(&config, /* aEnableDepthBuffer */ false)) {
         MOZ_CRASH("GFX: Failed to create EGLConfig 2!\n");
     }
 
     MOZ_ASSERT(aWindow);
 
     EGLSurface surface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config, aWindow,
                                                           0);
     if (surface == EGL_NO_SURFACE) {
         MOZ_CRASH("GFX: Failed to create EGLSurface 2!\n");
     }
 
     return surface;
 }
 
-void
+/* static */ void
 GLContextProviderEGL::DestroyEGLSurface(EGLSurface surface)
 {
     nsCString discardFailureId;
     if (!sEGLLibrary.EnsureInitialized(false, &discardFailureId)) {
         MOZ_CRASH("GFX: Failed to load EGL library 5!\n");
     }
 
     sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
@@ -975,16 +984,22 @@ GLContextProviderEGL::CreateOffscreen(co
     }
 
     bool canOffscreenUseHeadless = true;
     if (sEGLLibrary.IsANGLE()) {
         // ANGLE needs to use PBuffers.
         canOffscreenUseHeadless = false;
     }
 
+#if defined(MOZ_WIDGET_ANDROID)
+    // Using a headless context loses the SurfaceCaps
+    // which can cause a loss of depth and/or stencil
+    canOffscreenUseHeadless = false;
+#endif //  defined(MOZ_WIDGET_ANDROID)
+
     RefPtr<GLContext> gl;
     SurfaceCaps minOffscreenCaps = minCaps;
 
     if (canOffscreenUseHeadless) {
         gl = CreateHeadless(flags, out_failureId);
         if (!gl) {
             return nullptr;
         }
--- a/gfx/gl/GLContextProviderImpl.h
+++ b/gfx/gl/GLContextProviderImpl.h
@@ -5,19 +5,19 @@
 
 #ifndef IN_GL_CONTEXT_PROVIDER_H
 #error GLContextProviderImpl.h must only be included from GLContextProvider.h
 #endif
 
 #ifndef GL_CONTEXT_PROVIDER_NAME
 #error GL_CONTEXT_PROVIDER_NAME not defined
 #endif
-#if defined(ANDROID)
-typedef void* EGLSurface;
-#endif // defined(ANDROID)
+#if defined(MOZ_WIDGET_ANDROID)
+#include "GLTypes.h" // for EGLSurface and EGLConfig
+#endif // defined(MOZ_WIDGET_ANDROID)
 
 class GL_CONTEXT_PROVIDER_NAME
 {
 public:
     /**
      * Create a context that renders to the surface of the widget represented by
      * the compositor widget that is passed in. The context is always created
      * with an RGB pixel format, with no alpha, depth or stencil.
@@ -107,20 +107,20 @@ public:
      * @param aContext External context which will be wrapped by Gecko GLContext.
      * @param aSurface External surface which is used for external context.
      *
      * @return Wrapping Context to use for rendering
      */
     static already_AddRefed<GLContext>
     CreateWrappingExisting(void* aContext, void* aSurface);
 
-#if defined(ANDROID)
-    static EGLSurface CreateEGLSurface(void* aWindow);
+#if defined(MOZ_WIDGET_ANDROID)
+    static EGLSurface CreateEGLSurface(void* aWindow, EGLConfig aConfig = nullptr);
     static void DestroyEGLSurface(EGLSurface surface);
-#endif // defined(ANDROID)
+#endif // defined(MOZ_WIDGET_ANDROID)
 
     /**
      * Get a pointer to the global context, creating it if it doesn't exist.
      */
     static GLContext*
     GetGlobalContext();
 
     /**
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -86,17 +86,17 @@ GLScreenBuffer::CreateFactory(GLContext*
 #if defined(XP_MACOSX)
                 factory = SurfaceFactory_IOSurface::Create(gl, caps, ipcChannel, flags);
 #elif defined(GL_PROVIDER_GLX)
                 if (sGLXLibrary.UseTextureFromPixmap())
                   factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags);
 #elif defined(MOZ_WIDGET_UIKIT)
                 factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, caps, ipcChannel, mFlags);
 #elif defined(MOZ_WIDGET_ANDROID)
-                if (XRE_IsParentProcess()) {
+                if (XRE_IsParentProcess() && !gfxPrefs::WebGLSurfaceTextureEnabled()) {
                     factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
                 } else {
                     factory = SurfaceFactory_SurfaceTexture::Create(gl, caps, ipcChannel, flags);
                 }
 #else
                 if (gl->GetContextType() == GLContextType::EGL) {
                     if (XRE_IsParentProcess()) {
                         factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
--- a/gfx/gl/SharedSurfaceEGL.cpp
+++ b/gfx/gl/SharedSurfaceEGL.cpp
@@ -191,17 +191,19 @@ SharedSurface_SurfaceTexture::Create(GLC
                                      bool hasAlpha,
                                      java::GeckoSurface::Param surface)
 {
     MOZ_ASSERT(surface);
 
     UniquePtr<SharedSurface_SurfaceTexture> ret;
 
     AndroidNativeWindow window(surface);
-    EGLSurface eglSurface = GLContextProviderEGL::CreateEGLSurface(window.NativeWindow());
+    GLContextEGL* egl = GLContextEGL::Cast(prodGL);
+    MOZ_ASSERT(egl);
+    EGLSurface eglSurface = egl->CreateCompatibleSurface(window.NativeWindow());
     if (!eglSurface) {
         return Move(ret);
     }
 
     ret.reset(new SharedSurface_SurfaceTexture(prodGL, size, hasAlpha,
                                                formats, surface, eglSurface));
     return Move(ret);
 }
new file mode 100644
--- /dev/null
+++ b/gfx/layers/CanvasRenderer.cpp
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "CanvasRenderer.h"
+
+namespace mozilla {
+namespace layers {
+
+CanvasRenderer::CanvasRenderer()
+  : mPreTransCallback(nullptr)
+  , mPreTransCallbackData(nullptr)
+  , mDidTransCallback(nullptr)
+  , mDidTransCallbackData(nullptr)
+  , mDirty(false)
+{
+  MOZ_COUNT_CTOR(CanvasRenderer);
+}
+
+CanvasRenderer::~CanvasRenderer()
+{
+  Destroy();
+  MOZ_COUNT_DTOR(CanvasRenderer);
+}
+
+void
+CanvasRenderer::Initialize(const CanvasInitializeData& aData)
+{
+  mPreTransCallback = aData.mPreTransCallback;
+  mPreTransCallbackData = aData.mPreTransCallbackData;
+  mDidTransCallback = aData.mDidTransCallback;
+  mDidTransCallbackData = aData.mDidTransCallbackData;
+
+  mSize = aData.mSize;
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/CanvasRenderer.h
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFX_CANVASRENDERER_H
+#define GFX_CANVASRENDERER_H
+
+#include <stdint.h>                     // for uint32_t
+#include "GLContextTypes.h"             // for GLContext
+#include "gfxContext.h"                 // for gfxContext, etc
+#include "gfxTypes.h"
+#include "gfxPlatform.h"                // for gfxImageFormat
+#include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
+#include "mozilla/Preferences.h"        // for Preferences
+#include "mozilla/RefPtr.h"             // for RefPtr
+#include "mozilla/gfx/2D.h"             // for DrawTarget
+#include "mozilla/mozalloc.h"           // for operator delete, etc
+#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
+
+namespace mozilla {
+namespace layers {
+
+class AsyncCanvasRenderer;
+class ClientCanvasRenderer;
+class CopyableCanvasRenderer;
+class PersistentBufferProvider;
+class WebRenderCanvasRendererSync;
+class WebRenderCanvasRendererAsync;
+
+struct CanvasInitializeData {
+  CanvasInitializeData()
+    : mBufferProvider(nullptr)
+    , mGLContext(nullptr)
+    , mRenderer(nullptr)
+    , mPreTransCallback(nullptr)
+    , mPreTransCallbackData(nullptr)
+    , mDidTransCallback(nullptr)
+    , mDidTransCallbackData(nullptr)
+    , mFrontbufferGLTex(0)
+    , mSize(0,0)
+    , mHasAlpha(false)
+    , mIsGLAlphaPremult(true)
+    , mIsMirror(false)
+  { }
+
+  // One of these three must be specified for Canvas2D, but never more than one
+  PersistentBufferProvider* mBufferProvider; // A BufferProvider for the Canvas contents
+  mozilla::gl::GLContext* mGLContext; // or this, for GL.
+  AsyncCanvasRenderer* mRenderer; // or this, for OffscreenCanvas
+
+  typedef void (* TransactionCallback)(void* closureData);
+  TransactionCallback mPreTransCallback;
+  void* mPreTransCallbackData;
+  TransactionCallback mDidTransCallback;
+  void* mDidTransCallbackData;
+
+  // Frontbuffer override
+  uint32_t mFrontbufferGLTex;
+
+  // The size of the canvas content
+  gfx::IntSize mSize;
+
+  // Whether the canvas drawingbuffer has an alpha channel.
+  bool mHasAlpha;
+
+  // Whether mGLContext contains data that is alpha-premultiplied.
+  bool mIsGLAlphaPremult;
+
+  // Whether the canvas front buffer is already being rendered somewhere else.
+  // When true, do not swap buffers or Morph() to another factory on mGLContext
+  bool mIsMirror;
+};
+
+// Based class which used for canvas rendering. There are many derived classes for
+// different purposes. such as:
+//
+// CopyableCanvasRenderer provides a utility which readback canvas content to a
+// SourceSurface. BasicCanvasLayer uses CopyableCanvasRenderer.
+//
+// ShareableCanvasRenderer provides IPC capabilities that allow sending canvas
+// content over IPC. This is pure virtual class because the IPC handling is
+// different in different LayerManager. So that we have following classes inherite
+// ShareableCanvasRenderer.
+//
+// ClientCanvasRenderer inherites ShareableCanvasRenderer and be used in
+// ClientCanvasLayer.
+// WebRenderCanvasRenderer inherites ShareableCanvasRenderer and provides all
+// functionality that WebRender uses.
+// WebRenderCanvasRendererSync inherites WebRenderCanvasRenderer and be used in
+// WebRenderCanvasLayer.
+// WebRenderCanvasRendererAsync inherites WebRenderCanvasRenderer and be used in
+// layers-free mode of WebRender.
+//
+// class diagram shows below:
+//
+//                       +--------------+
+//                       |CanvasRenderer|
+//                       +-------+------+
+//                               ^
+//                               |
+//                   +----------------------+
+//                   |CopyableCanvasRenderer|
+//                   +----------------------+
+//                               ^
+//                               |
+//                   +-----------+-----------+
+//                   |ShareableCanvasRenderer|
+//                   +-----+-----------------+
+//                         ^      ^
+//           +-------------+      +-------+
+//           |                            |
+// +--------------------+       +---------+-------------+
+// |ClientCanvasRenderer|       |WebRenderCanvasRenderer|
+// +--------------------+       +--------+--+-----------+
+//                                       ^  ^
+//               +-----------------------+  +----+
+//               |                               |
+// +-------------+-------------+   +-------------+--------------+
+// |WebRenderCanvasRendererSync|   |WebRenderCanvasRendererAsync|
+// +---------------------------+   +----------------------------+
+class CanvasRenderer
+{
+public:
+  CanvasRenderer();
+  virtual ~CanvasRenderer();
+
+public:
+  virtual void Initialize(const CanvasInitializeData& aData);
+  virtual bool IsDataValid(const CanvasInitializeData& aData) { return true; }
+
+  virtual void ClearCachedResources() { }
+  virtual void Destroy() { }
+
+  const gfx::IntSize& GetSize() const { return mSize; }
+
+  void SetDirty() { mDirty = true; }
+  void ResetDirty() { mDirty = false; }
+  bool IsDirty() const { return mDirty; }
+
+  virtual CopyableCanvasRenderer* AsCopyableCanvasRenderer() { return nullptr; }
+  virtual ClientCanvasRenderer* AsClientCanvasRenderer() { return nullptr; }
+  virtual WebRenderCanvasRendererSync* AsWebRenderCanvasRendererSync() { return nullptr; }
+  virtual WebRenderCanvasRendererAsync* AsWebRenderCanvasRendererAsync() { return nullptr; }
+
+protected:
+  void FirePreTransactionCallback()
+  {
+    if (mPreTransCallback) {
+      mPreTransCallback(mPreTransCallbackData);
+    }
+  }
+
+  void FireDidTransactionCallback()
+  {
+    if (mDidTransCallback) {
+      mDidTransCallback(mDidTransCallbackData);
+    }
+  }
+
+  typedef void (* TransactionCallback)(void* closureData);
+  TransactionCallback mPreTransCallback;
+  void* mPreTransCallbackData;
+  TransactionCallback mDidTransCallback;
+  void* mDidTransCallbackData;
+  gfx::IntSize mSize;
+
+private:
+  /**
+   * Set to true in Updated(), cleared during a transaction.
+   */
+  bool mDirty;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif
rename from gfx/layers/CopyableCanvasLayer.cpp
rename to gfx/layers/CopyableCanvasRenderer.cpp
--- a/gfx/layers/CopyableCanvasLayer.cpp
+++ b/gfx/layers/CopyableCanvasRenderer.cpp
@@ -1,14 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "CopyableCanvasLayer.h"
+#include "CopyableCanvasRenderer.h"
 
 #include "BasicLayersImpl.h"            // for FillWithMask, etc
 #include "GLContext.h"                  // for GLContext
 #include "GLScreenBuffer.h"             // for GLScreenBuffer
 #include "SharedSurface.h"              // for SharedSurface
 #include "SharedSurfaceGL.h"              // for SharedSurface
 #include "gfxPattern.h"                 // for gfxPattern, etc
 #include "gfxPlatform.h"                // for gfxPlatform, gfxImageFormat
@@ -27,34 +27,41 @@
 #include "client/TextureClientSharedSurface.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 
-CopyableCanvasLayer::CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData) :
-  CanvasLayer(aLayerManager, aImplData)
+CopyableCanvasRenderer::CopyableCanvasRenderer()
+  : mGLContext(nullptr)
+  , mBufferProvider(nullptr)
   , mGLFrontbuffer(nullptr)
+  , mAsyncRenderer(nullptr)
   , mIsAlphaPremultiplied(true)
   , mOriginPos(gl::OriginPos::TopLeft)
   , mIsMirror(false)
+  , mOpaque(true)
+  , mCachedTempSurface(nullptr)
 {
-  MOZ_COUNT_CTOR(CopyableCanvasLayer);
+  MOZ_COUNT_CTOR(CopyableCanvasRenderer);
 }
 
-CopyableCanvasLayer::~CopyableCanvasLayer()
+CopyableCanvasRenderer::~CopyableCanvasRenderer()
 {
-  MOZ_COUNT_DTOR(CopyableCanvasLayer);
+  Destroy();
+  MOZ_COUNT_DTOR(CopyableCanvasRenderer);
 }
 
 void
-CopyableCanvasLayer::Initialize(const Data& aData)
+CopyableCanvasRenderer::Initialize(const CanvasInitializeData& aData)
 {
+  CanvasRenderer::Initialize(aData);
+
   if (aData.mGLContext) {
     mGLContext = aData.mGLContext;
     mIsAlphaPremultiplied = aData.mIsGLAlphaPremult;
     mOriginPos = gl::OriginPos::BottomLeft;
     mIsMirror = aData.mIsMirror;
 
     MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
 
@@ -65,30 +72,107 @@ CopyableCanvasLayer::Initialize(const Da
       mBufferProvider = aData.mBufferProvider;
     }
   } else if (aData.mBufferProvider) {
     mBufferProvider = aData.mBufferProvider;
   } else if (aData.mRenderer) {
     mAsyncRenderer = aData.mRenderer;
     mOriginPos = gl::OriginPos::BottomLeft;
   } else {
-    MOZ_CRASH("GFX: CanvasLayer created without BufferProvider, DrawTarget or GLContext?");
+    MOZ_CRASH("GFX: CanvasRenderer created without BufferProvider, DrawTarget or GLContext?");
   }
 
-  mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
+  mOpaque = !aData.mHasAlpha;
 }
 
 bool
-CopyableCanvasLayer::IsDataValid(const Data& aData)
+CopyableCanvasRenderer::IsDataValid(const CanvasInitializeData& aData)
 {
   return mGLContext == aData.mGLContext;
 }
 
+void
+CopyableCanvasRenderer::ClearCachedResources()
+{
+  if (mBufferProvider) {
+    mBufferProvider->ClearCachedResources();
+  }
+
+  mCachedTempSurface = nullptr;
+}
+
+void
+CopyableCanvasRenderer::Destroy()
+{
+  if (mBufferProvider) {
+    mBufferProvider->ClearCachedResources();
+  }
+
+  mCachedTempSurface = nullptr;
+}
+
+already_AddRefed<SourceSurface>
+CopyableCanvasRenderer::ReadbackSurface()
+{
+  FirePreTransactionCallback();
+  if (mAsyncRenderer) {
+    MOZ_ASSERT(!mBufferProvider);
+    MOZ_ASSERT(!mGLContext);
+    return mAsyncRenderer->GetSurface();
+  }
+
+  if (!mGLContext) {
+    return nullptr;
+  }
+
+  SharedSurface* frontbuffer = nullptr;
+  if (mGLFrontbuffer) {
+    frontbuffer = mGLFrontbuffer.get();
+  } else {
+    GLScreenBuffer* screen = mGLContext->Screen();
+    const auto& front = screen->Front();
+    if (front) {
+      frontbuffer = front->Surf();
+    }
+  }
+
+  if (!frontbuffer) {
+    NS_WARNING("Null frame received.");
+    return nullptr;
+  }
+
+  IntSize readSize(frontbuffer->mSize);
+  SurfaceFormat format =
+    mOpaque ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8;
+  bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
+
+  RefPtr<DataSourceSurface> resultSurf = GetTempSurface(readSize, format);
+  // There will already be a warning from inside of GetTempSurface, but
+  // it doesn't hurt to complain:
+  if (NS_WARN_IF(!resultSurf)) {
+    return nullptr;
+  }
+
+  // Readback handles Flush/MarkDirty.
+  if (!mGLContext->Readback(frontbuffer, resultSurf)) {
+    NS_WARNING("Failed to read back canvas surface.");
+    return nullptr;
+  }
+  if (needsPremult) {
+    gfxUtils::PremultiplyDataSurface(resultSurf, resultSurf);
+  }
+  MOZ_ASSERT(resultSurf);
+
+  FireDidTransactionCallback();
+
+  return resultSurf.forget();
+}
+
 DataSourceSurface*
-CopyableCanvasLayer::GetTempSurface(const IntSize& aSize,
+CopyableCanvasRenderer::GetTempSurface(const IntSize& aSize,
                                     const SurfaceFormat aFormat)
 {
   if (!mCachedTempSurface ||
       aSize != mCachedTempSurface->GetSize() ||
       aFormat != mCachedTempSurface->GetFormat())
   {
     // Create a surface aligned to 8 bytes since that's the highest alignment WebGL can handle.
     uint32_t stride = GetAlignedStride<8>(aSize.width, BytesPerPixel(aFormat));
rename from gfx/layers/CopyableCanvasLayer.h
rename to gfx/layers/CopyableCanvasRenderer.h
--- a/gfx/layers/CopyableCanvasLayer.h
+++ b/gfx/layers/CopyableCanvasRenderer.h
@@ -1,19 +1,19 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef GFX_COPYABLECANVASLAYER_H
-#define GFX_COPYABLECANVASLAYER_H
+#ifndef GFX_COPYABLECANVASRENDERER_H
+#define GFX_COPYABLECANVASRENDERER_H
 
 #include <stdint.h>                     // for uint32_t
+#include "CanvasRenderer.h"
 #include "GLContextTypes.h"             // for GLContext
-#include "Layers.h"                     // for CanvasLayer, etc
 #include "gfxContext.h"                 // for gfxContext, etc
 #include "gfxTypes.h"
 #include "gfxPlatform.h"                // for gfxImageFormat
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/Preferences.h"        // for Preferences
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/gfx/2D.h"             // for DrawTarget
 #include "mozilla/mozalloc.h"           // for operator delete, etc
@@ -23,43 +23,54 @@ namespace mozilla {
 
 namespace gl {
 class SharedSurface;
 } // namespace gl
 
 namespace layers {
 
 /**
- * A shared CanvasLayer implementation that supports copying
- * its contents into a gfxASurface using UpdateSurface.
+ * A shared CanvasRenderer implementation that supports copying
+ * its contents into a gfxASurface using RebackSurface.
  */
-class CopyableCanvasLayer : public CanvasLayer
+class CopyableCanvasRenderer : public CanvasRenderer
 {
 public:
-  CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData);
-
-protected:
-  virtual ~CopyableCanvasLayer();
+  CopyableCanvasRenderer();
+  virtual ~CopyableCanvasRenderer();
 
 public:
-  virtual void Initialize(const Data& aData) override;
+  void Initialize(const CanvasInitializeData& aData) override;
+  bool IsDataValid(const CanvasInitializeData& aData) override;
+
+  void ClearCachedResources() override;
+  void Destroy() override;
+
+  CopyableCanvasRenderer* AsCopyableCanvasRenderer() override { return this; }
 
-  virtual bool IsDataValid(const Data& aData) override;
+  bool NeedsYFlip() const { return mOriginPos == gl::OriginPos::BottomLeft; }
+  bool HasGLContext() const { return !!mGLContext; }
+  bool IsOpaque() const { return mOpaque; }
 
-  bool IsGLLayer() { return !!mGLContext; }
+  PersistentBufferProvider* GetBufferProvider() { return mBufferProvider; }
+
+  already_AddRefed<gfx::SourceSurface> ReadbackSurface();
 
 protected:
   RefPtr<gl::GLContext> mGLContext;
   RefPtr<PersistentBufferProvider> mBufferProvider;
   UniquePtr<gl::SharedSurface> mGLFrontbuffer;
+  RefPtr<AsyncCanvasRenderer> mAsyncRenderer;
 
   bool mIsAlphaPremultiplied;
   gl::OriginPos mOriginPos;
   bool mIsMirror;
 
+  bool mOpaque;
+
   RefPtr<gfx::DataSourceSurface> mCachedTempSurface;
 
   gfx::DataSourceSurface* GetTempSurface(const gfx::IntSize& aSize,
                                          const gfx::SurfaceFormat aFormat);
 };
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -2143,23 +2143,18 @@ BorderLayer::PrintInfo(std::stringstream
 void
 BorderLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
 {
   Layer::DumpPacket(aPacket, aParent);
 }
 
 CanvasLayer::CanvasLayer(LayerManager* aManager, void* aImplData)
   : Layer(aManager, aImplData)
-  , mPreTransCallback(nullptr)
-  , mPreTransCallbackData(nullptr)
-  , mPostTransCallback(nullptr)
-  , mPostTransCallbackData(nullptr)
-  , mSamplingFilter(gfx::SamplingFilter::GOOD)
-  , mDirty(false)
-{}
+{
+}
 
 CanvasLayer::~CanvasLayer() = default;
 
 void
 CanvasLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
 {
   Layer::PrintInfo(aStream, aPrefix);
   if (mSamplingFilter != SamplingFilter::GOOD) {
@@ -2196,16 +2191,26 @@ CanvasLayer::DumpPacket(layerscope::Laye
   Layer::DumpPacket(aPacket, aParent);
   // Get this layer data
   using namespace layerscope;
   LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
   layer->set_type(LayersPacket::Layer::CanvasLayer);
   DumpFilter(layer, mSamplingFilter);
 }
 
+CanvasRenderer*
+CanvasLayer::CreateOrGetCanvasRenderer()
+{
+  if (!mCanvasRenderer) {
+    mCanvasRenderer.reset(CreateCanvasRendererInternal());
+  }
+
+  return mCanvasRenderer.get();
+}
+
 void
 ImageLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
 {
   Layer::PrintInfo(aStream, aPrefix);
   if (mSamplingFilter != SamplingFilter::GOOD) {
     AppendToString(aStream, mSamplingFilter, " [filter=", "]");
   }
 }
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -30,16 +30,17 @@
 #include "mozilla/gfx/BaseMargin.h"     // for BaseMargin
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/gfx/TiledRegion.h"    // for TiledIntRegion
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat
 #include "mozilla/gfx/UserData.h"       // for UserData, etc
 #include "mozilla/layers/AnimationInfo.h" // for AnimationInfo
 #include "mozilla/layers/BSPTree.h"     // for LayerPolygon
+#include "mozilla/layers/CanvasRenderer.h"
 #include "mozilla/layers/LayerAttributes.h"
 #include "mozilla/layers/LayersTypes.h"
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsAutoPtr.h"                  // for nsAutoPtr, nsRefPtr, etc
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsCSSPropertyID.h"              // for nsCSSPropertyID
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for Layer::Release, etc
@@ -2681,125 +2682,51 @@ protected:
  * if hardware compositing is not available, for reading from the GL
  * buffer into an image surface that we can layer composite.)
  *
  * After Initialize is called, the underlying canvas Surface/GLContext
  * must not be modified during a layer transaction.
  */
 class CanvasLayer : public Layer {
 public:
-  struct Data {
-    Data()
-      : mBufferProvider(nullptr)
-      , mGLContext(nullptr)
-      , mRenderer(nullptr)
-      , mFrontbufferGLTex(0)
-      , mSize(0,0)
-      , mHasAlpha(false)
-      , mIsGLAlphaPremult(true)
-      , mIsMirror(false)
-    { }
-
-    // One of these three must be specified for Canvas2D, but never more than one
-    PersistentBufferProvider* mBufferProvider; // A BufferProvider for the Canvas contents
-    mozilla::gl::GLContext* mGLContext; // or this, for GL.
-    AsyncCanvasRenderer* mRenderer; // or this, for OffscreenCanvas
-
-    // Frontbuffer override
-    uint32_t mFrontbufferGLTex;
-
-    // The size of the canvas content
-    gfx::IntSize mSize;
-
-    // Whether the canvas drawingbuffer has an alpha channel.
-    bool mHasAlpha;
-
-    // Whether mGLContext contains data that is alpha-premultiplied.
-    bool mIsGLAlphaPremult;
-
-    // Whether the canvas front buffer is already being rendered somewhere else.
-    // When true, do not swap buffers or Morph() to another factory on mGLContext
-    bool mIsMirror;
-  };
-
-  /**
-   * CONSTRUCTION PHASE ONLY
-   * Initialize this CanvasLayer with the given data.  The data must
-   * have either mSurface or mGLContext initialized (but not both), as
-   * well as mSize.
-   *
-   * This must only be called once.
-   */
-  virtual void Initialize(const Data& aData) = 0;
-
   void SetBounds(gfx::IntRect aBounds) { mBounds = aBounds; }
 
-  /**
-   * Check the data is owned by this layer is still valid for rendering
-   */
-  virtual bool IsDataValid(const Data& aData) { return true; }
-
   virtual CanvasLayer* AsCanvasLayer() override { return this; }
 
   /**
    * Notify this CanvasLayer that the canvas surface contents have
    * changed (or will change) before the next transaction.
    */
-  void Updated() { mDirty = true; SetInvalidRectToVisibleRegion(); }
+  void Updated() { mCanvasRenderer->SetDirty(); SetInvalidRectToVisibleRegion(); }
 
   /**
    * Notify this CanvasLayer that the canvas surface contents have
    * been painted since the last change.
    */
-  void Painted() { mDirty = false; }
+  void Painted() { mCanvasRenderer->ResetDirty(); }
 
   /**
    * Returns true if the canvas surface contents have changed since the
    * last paint.
    */
   bool IsDirty()
   {
     // We can only tell if we are dirty if we're part of the
     // widget's retained layer tree.
     if (!mManager || !mManager->IsWidgetLayerManager()) {
       return true;
     }
-    return mDirty;
-  }
-
-  /**
-   * Register a callback to be called at the start of each transaction.
-   */
-  typedef void PreTransactionCallback(void* closureData);
-  void SetPreTransactionCallback(PreTransactionCallback* callback, void* closureData)
-  {
-    mPreTransCallback = callback;
-    mPreTransCallbackData = closureData;
+    return mCanvasRenderer->IsDirty();
   }
 
   const nsIntRect& GetBounds() const { return mBounds; }
 
-protected:
-  void FirePreTransactionCallback()
-  {
-    if (mPreTransCallback) {
-      mPreTransCallback(mPreTransCallbackData);
-    }
-  }
+  CanvasRenderer* CreateOrGetCanvasRenderer();
 
 public:
-  /**
-   * Register a callback to be called at the end of each transaction.
-   */
-  typedef void (* DidTransactionCallback)(void* aClosureData);
-  void SetDidTransactionCallback(DidTransactionCallback aCallback, void* aClosureData)
-  {
-    mPostTransCallback = aCallback;
-    mPostTransCallbackData = aClosureData;
-  }
 
   /**
    * CONSTRUCTION PHASE ONLY
    * Set the filter used to resample this image (if necessary).
    */
   void SetSamplingFilter(gfx::SamplingFilter aSamplingFilter)
   {
     if (mSamplingFilter != aSamplingFilter) {
@@ -2820,52 +2747,33 @@ public:
     // transform, then we'd snap again when compositing the PaintedLayer).
     mEffectiveTransform =
         SnapTransform(GetLocalTransform(), gfxRect(0, 0, mBounds.width, mBounds.height),
                       nullptr)*
         SnapTransformTranslation(aTransformToSurface, nullptr);
     ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
   }
 
-  bool GetIsAsyncRenderer() const
-  {
-    return !!mAsyncRenderer;
-  }
-
 protected:
   CanvasLayer(LayerManager* aManager, void* aImplData);
   virtual ~CanvasLayer();
 
   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
 
   virtual void DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent) override;
 
-  void FireDidTransactionCallback()
-  {
-    if (mPostTransCallback) {
-      mPostTransCallback(mPostTransCallbackData);
-    }
-  }
+  virtual CanvasRenderer* CreateCanvasRendererInternal() = 0;
+
+  UniquePtr<CanvasRenderer> mCanvasRenderer;
+  gfx::SamplingFilter mSamplingFilter;
 
   /**
    * 0, 0, canvaswidth, canvasheight
    */
   gfx::IntRect mBounds;
-  PreTransactionCallback* mPreTransCallback;
-  void* mPreTransCallbackData;
-  DidTransactionCallback mPostTransCallback;
-  void* mPostTransCallbackData;
-  gfx::SamplingFilter mSamplingFilter;
-  RefPtr<AsyncCanvasRenderer> mAsyncRenderer;
-
-private:
-  /**
-   * Set to true in Updated(), cleared during a transaction.
-   */
-  bool mDirty;
 };
 
 /**
  * ContainerLayer that refers to a "foreign" layer tree, through an
  * ID.  Usage of RefLayer looks like
  *
  * Construction phase:
  *   allocate ID for layer subtree
rename from gfx/layers/ShareableCanvasLayer.cpp
rename to gfx/layers/ShareableCanvasRenderer.cpp
--- a/gfx/layers/ShareableCanvasLayer.cpp
+++ b/gfx/layers/ShareableCanvasRenderer.cpp
@@ -1,47 +1,43 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "ShareableCanvasLayer.h"
+#include "ShareableCanvasRenderer.h"
 
 #include "GLContext.h"                  // for GLContext
 #include "GLScreenBuffer.h"             // for GLScreenBuffer
 #include "SharedSurfaceGL.h"            // for SurfaceFactory_GLTexture, etc
 #include "mozilla/layers/AsyncCanvasRenderer.h"
 #include "mozilla/layers/TextureClientSharedSurface.h"
 
 namespace mozilla {
 namespace layers {
 
-ShareableCanvasLayer::ShareableCanvasLayer(LayerManager* aLayerManager, void *aImplData)
-  : CopyableCanvasLayer(aLayerManager, aImplData)
+ShareableCanvasRenderer::ShareableCanvasRenderer()
+  : mCanvasClient(nullptr)
+  , mFactory(nullptr)
   , mFlags(TextureFlags::NO_FLAGS)
 {
-  MOZ_COUNT_CTOR(ShareableCanvasLayer);
+  MOZ_COUNT_CTOR(ShareableCanvasRenderer);
 }
 
-ShareableCanvasLayer::~ShareableCanvasLayer()
+ShareableCanvasRenderer::~ShareableCanvasRenderer()
 {
-  MOZ_COUNT_DTOR(ShareableCanvasLayer);
-  if (mBufferProvider) {
-    mBufferProvider->ClearCachedResources();
-  }
-  if (mCanvasClient) {
-    mCanvasClient->OnDetach();
-    mCanvasClient = nullptr;
-  }
+  MOZ_COUNT_DTOR(ShareableCanvasRenderer);
+
+  Destroy();
 }
 
 void
-ShareableCanvasLayer::Initialize(const Data& aData)
+ShareableCanvasRenderer::Initialize(const CanvasInitializeData& aData)
 {
-  CopyableCanvasLayer::Initialize(aData);
+  CopyableCanvasRenderer::Initialize(aData);
 
   mCanvasClient = nullptr;
 
   if (!mGLContext)
     return;
 
   gl::GLScreenBuffer* screen = mGLContext->Screen();
 
@@ -75,18 +71,39 @@ ShareableCanvasLayer::Initialize(const D
       mFactory = MakeUnique<gl::SurfaceFactory_Basic>(mGLContext, caps, mFlags);
     }
   } else {
     if (factory)
       screen->Morph(Move(factory));
   }
 }
 
+void
+ShareableCanvasRenderer::ClearCachedResources()
+{
+  CopyableCanvasRenderer::ClearCachedResources();
+
+  if (mCanvasClient) {
+    mCanvasClient->Clear();
+  }
+}
+
+void
+ShareableCanvasRenderer::Destroy()
+{
+  CopyableCanvasRenderer::Destroy();
+
+  if (mCanvasClient) {
+    mCanvasClient->OnDetach();
+    mCanvasClient = nullptr;
+  }
+}
+
 bool
-ShareableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
+ShareableCanvasRenderer::UpdateTarget(DrawTarget* aDestTarget)
 {
   MOZ_ASSERT(aDestTarget);
   if (!aDestTarget) {
     return false;
   }
 
   RefPtr<SourceSurface> surface;
 
@@ -102,17 +119,17 @@ ShareableCanvasLayer::UpdateTarget(DrawT
     }
 
     MOZ_ASSERT(surface);
     if (!surface) {
       return false;
     }
 
     aDestTarget->CopySurface(surface,
-                             IntRect(0, 0, mBounds.width, mBounds.height),
+                             IntRect(0, 0, mSize.width, mSize.height),
                              IntPoint(0, 0));
     return true;
   }
 
   gl::SharedSurface* frontbuffer = nullptr;
   if (mGLFrontbuffer) {
     frontbuffer = mGLFrontbuffer.get();
   } else {
@@ -124,19 +141,18 @@ ShareableCanvasLayer::UpdateTarget(DrawT
   }
 
   if (!frontbuffer) {
     NS_WARNING("Null frame received.");
     return false;
   }
 
   IntSize readSize(frontbuffer->mSize);
-  SurfaceFormat format = (GetContentFlags() & CONTENT_OPAQUE)
-                          ? SurfaceFormat::B8G8R8X8
-                          : SurfaceFormat::B8G8R8A8;
+  SurfaceFormat format =
+    mOpaque ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8;
   bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
 
   // Try to read back directly into aDestTarget's output buffer
   uint8_t* destData;
   IntSize destSize;
   int32_t destStride;
   SurfaceFormat destFormat;
   if (aDestTarget->LockBits(&destData, &destSize, &destStride, &destFormat)) {
@@ -174,69 +190,53 @@ ShareableCanvasLayer::UpdateTarget(DrawT
   aDestTarget->CopySurface(resultSurf,
                            IntRect(0, 0, readSize.width, readSize.height),
                            IntPoint(0, 0));
 
   return true;
 }
 
 CanvasClient::CanvasClientType
-ShareableCanvasLayer::GetCanvasClientType()
+ShareableCanvasRenderer::GetCanvasClientType()
 {
   if (mAsyncRenderer) {
     return CanvasClient::CanvasClientAsync;
   }
 
   if (mGLContext) {
     return CanvasClient::CanvasClientTypeShSurf;
   }
   return CanvasClient::CanvasClientSurface;
 }
 
 void
-ShareableCanvasLayer::UpdateCompositableClient()
+ShareableCanvasRenderer::UpdateCompositableClient()
 {
-  if (!mCanvasClient) {
-    TextureFlags flags = TextureFlags::DEFAULT;
-    if (mOriginPos == gl::OriginPos::BottomLeft) {
-      flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
-    }
-
-    if (!mIsAlphaPremultiplied) {
-      flags |= TextureFlags::NON_PREMULTIPLIED;
-    }
-
-    mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
-                                                     GetForwarder(),
-                                                     flags);
-    if (!mCanvasClient) {
-      return;
-    }
-
-    AttachCompositable();
+  if (!CreateCompositable()) {
+    return;
   }
 
   if (mCanvasClient && mAsyncRenderer) {
     mCanvasClient->UpdateAsync(mAsyncRenderer);
   }
 
   if (!IsDirty()) {
     return;
   }
-  Painted();
+  ResetDirty();
 
   FirePreTransactionCallback();
   if (mBufferProvider && mBufferProvider->GetTextureClient()) {
-    if (!mBufferProvider->SetForwarder(mManager->AsShadowForwarder())) {
+    if (!mBufferProvider->SetForwarder(GetForwarder()->AsLayerForwarder())) {
       gfxCriticalNote << "BufferProvider::SetForwarder failed";
       return;
     }
     mCanvasClient->UpdateFromTexture(mBufferProvider->GetTextureClient());
   } else {
-    mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this);
+    mCanvasClient->Update(gfx::IntSize(mSize.width, mSize.height), this);
   }
 
   FireDidTransactionCallback();
 
   mCanvasClient->Updated();
 }
 
 } // namespace layers
rename from gfx/layers/ShareableCanvasLayer.h
rename to gfx/layers/ShareableCanvasRenderer.h
--- a/gfx/layers/ShareableCanvasLayer.h
+++ b/gfx/layers/ShareableCanvasRenderer.h
@@ -1,50 +1,52 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef GFX_SHAREABLECANVASLAYER_H
-#define GFX_SHAREABLECANVASLAYER_H
+#ifndef GFX_SHAREABLECANVASRENDERER_H
+#define GFX_SHAREABLECANVASRENDERER_H
 
 #include "CompositorTypes.h"
-#include "CopyableCanvasLayer.h"
+#include "CopyableCanvasRenderer.h"
 #include "mozilla/layers/CanvasClient.h"
 
 namespace mozilla {
 namespace gl {
 class SurfaceFactory;
 } // namespace gl
 
 namespace layers {
 
-class ShareableCanvasLayer : public CopyableCanvasLayer
+class ShareableCanvasRenderer : public CopyableCanvasRenderer
 {
   typedef CanvasClient::CanvasClientType CanvasClientType;
 public:
-  ShareableCanvasLayer(LayerManager* aLayerManager, void *aImplData);
-
-protected:
-  virtual ~ShareableCanvasLayer();
+  ShareableCanvasRenderer();
+  virtual ~ShareableCanvasRenderer();
 
 public:
-  virtual void Initialize(const Data& aData) override;
+  void Initialize(const CanvasInitializeData& aData) override;
 
   virtual CompositableForwarder* GetForwarder() = 0;
 
-  virtual void AttachCompositable() = 0;
+  virtual bool CreateCompositable() = 0;
+
+  void ClearCachedResources() override;
+  void Destroy() override;
 
   void UpdateCompositableClient();
 
   const TextureFlags& Flags() const { return mFlags; }
 
-protected:
+  CanvasClient* GetCanvasClient() { return mCanvasClient; }
 
-  bool UpdateTarget(gfx::DrawTarget* aDestTarget = nullptr);
+protected:
+  bool UpdateTarget(gfx::DrawTarget* aDestTarget);
 
   CanvasClientType GetCanvasClientType();
 
   RefPtr<CanvasClient> mCanvasClient;
 
   UniquePtr<gl::SurfaceFactory> mFactory;
 
   TextureFlags mFlags;
--- a/gfx/layers/basic/BasicCanvasLayer.cpp
+++ b/gfx/layers/basic/BasicCanvasLayer.cpp
@@ -2,16 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "BasicCanvasLayer.h"
 #include "AsyncCanvasRenderer.h"
 #include "basic/BasicLayers.h"          // for BasicLayerManager
 #include "basic/BasicLayersImpl.h"      // for GetEffectiveOperator
+#include "CopyableCanvasRenderer.h"
 #include "mozilla/mozalloc.h"           // for operator new
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
 #include "gfx2DGlue.h"
 #include "GLScreenBuffer.h"
 #include "GLContext.h"
 #include "gfxUtils.h"
 #include "mozilla/layers/PersistentBufferProvider.h"
@@ -20,123 +21,73 @@
 class gfxContext;
 
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
-already_AddRefed<SourceSurface>
-BasicCanvasLayer::UpdateSurface()
-{
-  if (mAsyncRenderer) {
-    MOZ_ASSERT(!mBufferProvider);
-    MOZ_ASSERT(!mGLContext);
-    return mAsyncRenderer->GetSurface();
-  }
-
-  if (!mGLContext) {
-    return nullptr;
-  }
-
-  SharedSurface* frontbuffer = nullptr;
-  if (mGLFrontbuffer) {
-    frontbuffer = mGLFrontbuffer.get();
-  } else {
-    GLScreenBuffer* screen = mGLContext->Screen();
-    const auto& front = screen->Front();
-    if (front) {
-      frontbuffer = front->Surf();
-    }
-  }
-
-  if (!frontbuffer) {
-    NS_WARNING("Null frame received.");
-    return nullptr;
-  }
-
-  IntSize readSize(frontbuffer->mSize);
-  SurfaceFormat format = (GetContentFlags() & CONTENT_OPAQUE)
-                          ? SurfaceFormat::B8G8R8X8
-                          : SurfaceFormat::B8G8R8A8;
-  bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
-
-  RefPtr<DataSourceSurface> resultSurf = GetTempSurface(readSize, format);
-  // There will already be a warning from inside of GetTempSurface, but
-  // it doesn't hurt to complain:
-  if (NS_WARN_IF(!resultSurf)) {
-    return nullptr;
-  }
-
-  // Readback handles Flush/MarkDirty.
-  if (!mGLContext->Readback(frontbuffer, resultSurf)) {
-    NS_WARNING("Failed to read back canvas surface.");
-    return nullptr;
-  }
-  if (needsPremult) {
-    gfxUtils::PremultiplyDataSurface(resultSurf, resultSurf);
-  }
-  MOZ_ASSERT(resultSurf);
-
-  return resultSurf.forget();
-}
-
 void
 BasicCanvasLayer::Paint(DrawTarget* aDT,
                         const Point& aDeviceOffset,
                         Layer* aMaskLayer)
 {
   if (IsHidden())
     return;
 
   RefPtr<SourceSurface> surface;
+  CopyableCanvasRenderer* canvasRenderer = mCanvasRenderer->AsCopyableCanvasRenderer();
+  MOZ_ASSERT(canvasRenderer);
   if (IsDirty()) {
     Painted();
 
-    FirePreTransactionCallback();
-    surface = UpdateSurface();
-    FireDidTransactionCallback();
+    surface = canvasRenderer->ReadbackSurface();
   }
 
   bool bufferPoviderSnapshot = false;
-  if (!surface && mBufferProvider) {
-    surface = mBufferProvider->BorrowSnapshot();
+  PersistentBufferProvider* bufferProvider = canvasRenderer->GetBufferProvider();
+  if (!surface && bufferProvider) {
+    surface = bufferProvider->BorrowSnapshot();
     bufferPoviderSnapshot = !!surface;
   }
 
   if (!surface) {
     return;
   }
 
-  const bool needsYFlip = (mOriginPos == gl::OriginPos::BottomLeft);
-
   Matrix oldTM;
-  if (needsYFlip) {
+  if (canvasRenderer->NeedsYFlip()) {
     oldTM = aDT->GetTransform();
     aDT->SetTransform(Matrix(oldTM).
                         PreTranslate(0.0f, mBounds.height).
                         PreScale(1.0f, -1.0f));
   }
 
   FillRectWithMask(aDT, aDeviceOffset,
                    Rect(0, 0, mBounds.width, mBounds.height),
                    surface, mSamplingFilter,
                    DrawOptions(GetEffectiveOpacity(), GetEffectiveOperator(this)),
                    aMaskLayer);
 
-  if (needsYFlip) {
+  if (canvasRenderer->NeedsYFlip()) {
     aDT->SetTransform(oldTM);
   }
 
   if (bufferPoviderSnapshot) {
-    mBufferProvider->ReturnSnapshot(surface.forget());
+    bufferProvider->ReturnSnapshot(surface.forget());
   }
 }
 
+CanvasRenderer*
+BasicCanvasLayer::CreateCanvasRendererInternal()
+{
+  return new CopyableCanvasRenderer();
+}
+
 already_AddRefed<CanvasLayer>
 BasicLayerManager::CreateCanvasLayer()
 {
   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
   RefPtr<CanvasLayer> layer = new BasicCanvasLayer(this);
   return layer.forget();
 }
 
--- a/gfx/layers/basic/BasicCanvasLayer.h
+++ b/gfx/layers/basic/BasicCanvasLayer.h
@@ -3,49 +3,47 @@
  * 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 GFX_BASICCANVASLAYER_H
 #define GFX_BASICCANVASLAYER_H
 
 #include "BasicImplData.h"              // for BasicImplData
 #include "BasicLayers.h"                // for BasicLayerManager
-#include "CopyableCanvasLayer.h"        // for CopyableCanvasLayer
 #include "Layers.h"                     // for CanvasLayer, etc
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsRegion.h"                   // for nsIntRegion
 
 namespace mozilla {
 namespace layers {
 
-class BasicCanvasLayer : public CopyableCanvasLayer,
+class BasicCanvasLayer : public CanvasLayer,
                          public BasicImplData
 {
 public:
   explicit BasicCanvasLayer(BasicLayerManager* aLayerManager) :
-    CopyableCanvasLayer(aLayerManager, static_cast<BasicImplData*>(this))
+    CanvasLayer(aLayerManager, static_cast<BasicImplData*>(this))
   { }
 
   virtual void SetVisibleRegion(const LayerIntRegion& aRegion) override
   {
     NS_ASSERTION(BasicManager()->InConstruction(),
                  "Can only set properties in construction phase");
     CanvasLayer::SetVisibleRegion(aRegion);
   }
 
   virtual void Paint(gfx::DrawTarget* aDT,
                      const gfx::Point& aDeviceOffset,
                      Layer* aMaskLayer) override;
 
 protected:
-
-  already_AddRefed<gfx::SourceSurface> UpdateSurface();
-
   BasicLayerManager* BasicManager()
   {
     return static_cast<BasicLayerManager*>(mManager);
   }
+
+  CanvasRenderer* CreateCanvasRendererInternal() override;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -17,17 +17,16 @@
 #include "mozilla/layers/AsyncCanvasRenderer.h"
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/CompositorBridgeChild.h" // for CompositorBridgeChild
 #include "mozilla/layers/LayersTypes.h"
 #include "mozilla/layers/TextureClient.h"  // for TextureClient, etc
 #include "mozilla/layers/TextureClientOGL.h"
 #include "nsDebug.h"                    // for printf_stderr, NS_ASSERTION
 #include "nsXULAppAPI.h"                // for XRE_GetProcessType, etc
-#include "ShareableCanvasLayer.h"
 #include "TextureClientSharedSurface.h"
 
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
@@ -86,40 +85,38 @@ CanvasClient2D::UpdateFromTexture(Textur
   t->mPictureRect = nsIntRect(nsIntPoint(0, 0), aTexture->GetSize());
   t->mFrameID = mFrameID;
 
   GetForwarder()->UseTextures(this, textures);
   aTexture->SyncWithObject(GetForwarder()->GetSyncObject());
 }
 
 void
-CanvasClient2D::Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer)
+CanvasClient2D::Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer)
 {
   mBufferProviderTexture = nullptr;
 
   AutoRemoveTexture autoRemove(this);
   if (mBackBuffer && (mBackBuffer->IsReadLocked() || mBackBuffer->GetSize() != aSize)) {
     autoRemove.mTexture = mBackBuffer;
     mBackBuffer = nullptr;
   }
 
   bool bufferCreated = false;
   if (!mBackBuffer) {
-    bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE);
-    gfxContentType contentType = isOpaque
-                                                ? gfxContentType::COLOR
-                                                : gfxContentType::COLOR_ALPHA;
+    gfxContentType contentType =
+      aCanvasRenderer->IsOpaque() ? gfxContentType::COLOR : gfxContentType::COLOR_ALPHA;
     gfx::SurfaceFormat surfaceFormat
       = gfxPlatform::GetPlatform()->Optimal2DFormatForContent(contentType);
     TextureFlags flags = TextureFlags::DEFAULT;
     if (mTextureFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) {
       flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
     }
 
-    mBackBuffer = CreateTextureClientForCanvas(surfaceFormat, aSize, flags, aLayer);
+    mBackBuffer = CreateTextureClientForCanvas(surfaceFormat, aSize, flags, aCanvasRenderer);
     if (!mBackBuffer) {
       NS_WARNING("Failed to allocate the TextureClient");
       return;
     }
     mBackBuffer->EnableReadLock();
     MOZ_ASSERT(mBackBuffer->CanExposeDrawTarget());
 
     bufferCreated = true;
@@ -130,17 +127,17 @@ CanvasClient2D::Update(gfx::IntSize aSiz
     TextureClientAutoLock autoLock(mBackBuffer, OpenMode::OPEN_WRITE_ONLY);
     if (!autoLock.Succeeded()) {
       mBackBuffer = nullptr;
       return;
     }
 
     RefPtr<DrawTarget> target = mBackBuffer->BorrowDrawTarget();
     if (target) {
-      if (!aLayer->UpdateTarget(target)) {
+      if (!aCanvasRenderer->UpdateTarget(target)) {
         NS_WARNING("Failed to copy the canvas into a TextureClient.");
         return;
       }
       updated = true;
     }
   }
 
   if (bufferCreated && !AddTextureClient(mBackBuffer)) {
@@ -160,19 +157,19 @@ CanvasClient2D::Update(gfx::IntSize aSiz
 
   mBackBuffer.swap(mFrontBuffer);
 }
 
 already_AddRefed<TextureClient>
 CanvasClient2D::CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat,
                                              gfx::IntSize aSize,
                                              TextureFlags aFlags,
-                                             ShareableCanvasLayer* aLayer)
+                                             ShareableCanvasRenderer* aCanvasRenderer)
 {
-  if (aLayer->IsGLLayer()) {
+  if (aCanvasRenderer->HasGLContext()) {
     // We want a cairo backend here as we don't want to be copying into
     // an accelerated backend and we like LockBits to work. This is currently
     // the most effective way to make this work.
     return TextureClient::CreateForRawBufferAccess(GetForwarder(),
                                                    aFormat, aSize, BackendType::CAIRO,
                                                    mTextureFlags | aFlags);
   }
 
@@ -370,56 +367,56 @@ CloneSurface(gl::SharedSurface* src, gl:
     destSurf->ProducerAcquire();
     SharedSurface::ProdCopy(src, dest->Surf(), factory);
     destSurf->ProducerRelease();
 
     return dest.forget();
 }
 
 void
-CanvasClientSharedSurface::Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer)
+CanvasClientSharedSurface::Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer)
 {
   Renderer renderer;
-  renderer.construct<ShareableCanvasLayer*>(aLayer);
+  renderer.construct<ShareableCanvasRenderer*>(aCanvasRenderer);
   UpdateRenderer(aSize, renderer);
 }
 
 void
 CanvasClientSharedSurface::UpdateAsync(AsyncCanvasRenderer* aRenderer)
 {
   Renderer renderer;
   renderer.construct<AsyncCanvasRenderer*>(aRenderer);
   UpdateRenderer(aRenderer->GetSize(), renderer);
 }
 
 void
 CanvasClientSharedSurface::UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer)
 {
   GLContext* gl = nullptr;
-  ShareableCanvasLayer* layer = nullptr;
+  ShareableCanvasRenderer* canvasRenderer = nullptr;
   AsyncCanvasRenderer* asyncRenderer = nullptr;
-  if (aRenderer.constructed<ShareableCanvasLayer*>()) {
-    layer = aRenderer.ref<ShareableCanvasLayer*>();
-    gl = layer->mGLContext;
+  if (aRenderer.constructed<ShareableCanvasRenderer*>()) {
+    canvasRenderer = aRenderer.ref<ShareableCanvasRenderer*>();
+    gl = canvasRenderer->mGLContext;
   } else {
     asyncRenderer = aRenderer.ref<AsyncCanvasRenderer*>();
     gl = asyncRenderer->mGLContext;
   }
   gl->MakeCurrent();
 
   RefPtr<TextureClient> newFront;
 
-  if (layer && layer->mGLFrontbuffer) {
-    mShSurfClient = CloneSurface(layer->mGLFrontbuffer.get(), layer->mFactory.get());
+  if (canvasRenderer && canvasRenderer->mGLFrontbuffer) {
+    mShSurfClient = CloneSurface(canvasRenderer->mGLFrontbuffer.get(), canvasRenderer->mFactory.get());
     if (!mShSurfClient) {
       gfxCriticalError() << "Invalid canvas front buffer";
       return;
     }
-  } else if (layer && layer->mIsMirror) {
-    mShSurfClient = CloneSurface(gl->Screen()->Front()->Surf(), layer->mFactory.get());
+  } else if (canvasRenderer && canvasRenderer->mIsMirror) {
+    mShSurfClient = CloneSurface(gl->Screen()->Front()->Surf(), canvasRenderer->mFactory.get());
     if (!mShSurfClient) {
       return;
     }
   } else {
     mShSurfClient = gl->Screen()->Front();
     if (mShSurfClient && mShSurfClient->GetAllocator() &&
         mShSurfClient->GetAllocator() != GetForwarder()->GetTextureForwarder()) {
       mShSurfClient = CloneSurface(mShSurfClient->Surf(), gl->Screen()->Factory());
@@ -439,19 +436,19 @@ CanvasClientSharedSurface::UpdateRendere
 
   auto forwarder = GetForwarder();
 
   bool needsReadback = (surf->mType == SharedSurfaceType::Basic);
   if (needsReadback) {
     TextureFlags flags = TextureFlags::IMMUTABLE;
 
     CompositableForwarder* shadowForwarder = nullptr;
-    if (layer) {
-      flags |= layer->Flags();
-      shadowForwarder = layer->GetForwarder();
+    if (canvasRenderer) {
+      flags |= canvasRenderer->Flags();
+      shadowForwarder = canvasRenderer->GetForwarder();
     } else {
       MOZ_ASSERT(asyncRenderer);
       flags |= mTextureFlags;
       shadowForwarder = GetForwarder();
     }
 
     auto layersBackend = shadowForwarder->GetCompositorBackendType();
     mReadbackClient = TexClientFromReadback(surf, forwarder, flags, layersBackend);
--- a/gfx/layers/client/CanvasClient.h
+++ b/gfx/layers/client/CanvasClient.h
@@ -23,28 +23,28 @@
 
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat
 
 namespace mozilla {
 namespace layers {
 
 class AsyncCanvasRenderer;
-class ShareableCanvasLayer;
+class ShareableCanvasRenderer;
 class CompositableForwarder;
 class ShadowableLayer;
 class SharedSurfaceTextureClient;
 
 /**
  * Compositable client for 2d and webgl canvas.
  */
 class CanvasClient : public CompositableClient
 {
 public:
-  typedef MaybeOneOf<ShareableCanvasLayer*, AsyncCanvasRenderer*> Renderer;
+  typedef MaybeOneOf<ShareableCanvasRenderer*, AsyncCanvasRenderer*> Renderer;
 
   /**
    * Creates, configures, and returns a new canvas client. If necessary, a
    * message will be sent to the compositor to create a corresponding image
    * host.
    */
   enum CanvasClientType {
     CanvasClientSurface,
@@ -62,17 +62,17 @@ public:
   {
     mTextureFlags = aFlags;
   }
 
   virtual ~CanvasClient() {}
 
   virtual void Clear() {};
 
-  virtual void Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer) = 0;
+  virtual void Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer) = 0;
 
   virtual bool AddTextureClient(TextureClient* aTexture) override
   {
     ++mFrameID;
     return CompositableClient::AddTextureClient(aTexture);
   }
 
   virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) {}
@@ -100,17 +100,17 @@ public:
     return TextureInfo(CompositableType::IMAGE, mTextureFlags);
   }
 
   virtual void Clear() override
   {
     mBackBuffer = mFrontBuffer = mBufferProviderTexture = nullptr;
   }
 
-  virtual void Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer) override;
+  virtual void Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer) override;
 
   virtual void UpdateFromTexture(TextureClient* aBuffer) override;
 
   virtual bool AddTextureClient(TextureClient* aTexture) override
   {
     return CanvasClient::AddTextureClient(aTexture);
   }
 
@@ -119,17 +119,17 @@ public:
     mBackBuffer = mFrontBuffer = nullptr;
   }
 
 private:
   already_AddRefed<TextureClient>
     CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat,
                                  gfx::IntSize aSize,
                                  TextureFlags aFlags,
-                                 ShareableCanvasLayer* aLayer);
+                                 ShareableCanvasRenderer* aCanvasRenderer);
 
   RefPtr<TextureClient> mBackBuffer;
   RefPtr<TextureClient> mFrontBuffer;
   // We store this texture separately to make sure it is not written into
   // in Update() if for some silly reason we end up alternating between
   // UpdateFromTexture and Update.
   // This code is begging for a cleanup. The situation described above should
   // not be made possible.
@@ -158,17 +158,17 @@ public:
     return TextureInfo(CompositableType::IMAGE);
   }
 
   virtual void Clear() override {
     ClearSurfaces();
   }
 
   virtual void Update(gfx::IntSize aSize,
-                      ShareableCanvasLayer* aLayer) override;
+                      ShareableCanvasRenderer* aCanvasRenderer) override;
   void UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer);
 
   virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) override;
 
   virtual void Updated() override;
 
   virtual void OnDetach() override;
 };
@@ -188,17 +188,17 @@ public:
   {
   }
 
   TextureInfo GetTextureInfo() const override
   {
     return TextureInfo(CompositableType::IMAGE);
   }
 
-  virtual void Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer) override
+  virtual void Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer) override
   {
   }
 
   virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) override;
 
   void SetLayer(ShadowableLayer* aLayer)
   {
     mLayer = aLayer;
--- a/gfx/layers/client/ClientCanvasLayer.cpp
+++ b/gfx/layers/client/ClientCanvasLayer.cpp
@@ -18,20 +18,28 @@ ClientCanvasLayer::~ClientCanvasLayer()
 
 void
 ClientCanvasLayer::RenderLayer()
 {
   AUTO_PROFILER_LABEL("ClientCanvasLayer::RenderLayer", GRAPHICS);
 
   RenderMaskLayers(this);
 
-  UpdateCompositableClient();
+  ClientCanvasRenderer* canvasRenderer = mCanvasRenderer->AsClientCanvasRenderer();
+  MOZ_ASSERT(canvasRenderer);
+  canvasRenderer->UpdateCompositableClient();
   ClientManager()->Hold(this);
 }
 
+CanvasRenderer*
+ClientCanvasLayer::CreateCanvasRendererInternal()
+{
+  return new ClientCanvasRenderer(this);
+}
+
 already_AddRefed<CanvasLayer>
 ClientLayerManager::CreateCanvasLayer()
 {
   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
   RefPtr<ClientCanvasLayer> layer =
     new ClientCanvasLayer(this);
   CREATE_SHADOW(Canvas);
   return layer.forget();
--- a/gfx/layers/client/ClientCanvasLayer.h
+++ b/gfx/layers/client/ClientCanvasLayer.h
@@ -1,111 +1,85 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_CLIENTCANVASLAYER_H
 #define GFX_CLIENTCANVASLAYER_H
 
-#include "CanvasClient.h"               // for CanvasClient, etc
+#include "ClientCanvasRenderer.h"
 #include "ClientLayerManager.h"         // for ClientLayerManager, etc
 #include "Layers.h"                     // for CanvasLayer, etc
 #include "mozilla/Attributes.h"         // for override
+#include "mozilla/layers/CanvasClient.h"// for CanvasClient, etc
 #include "mozilla/layers/LayersMessages.h"  // for CanvasLayerAttributes, etc
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
-#include "ShareableCanvasLayer.h"
 
 namespace mozilla {
 namespace layers {
 
 class CompositableClient;
 class ShadowableLayer;
 
-class ClientCanvasLayer : public ShareableCanvasLayer,
+class ClientCanvasLayer : public CanvasLayer,
                           public ClientLayer
 {
 public:
   explicit ClientCanvasLayer(ClientLayerManager* aLayerManager) :
-    ShareableCanvasLayer(aLayerManager, static_cast<ClientLayer*>(this))
+    CanvasLayer(aLayerManager, static_cast<ClientLayer*>(this))
   {
     MOZ_COUNT_CTOR(ClientCanvasLayer);
   }
 
+  CanvasRenderer* CreateCanvasRendererInternal() override;
+
 protected:
   virtual ~ClientCanvasLayer();
 
 public:
   virtual void SetVisibleRegion(const LayerIntRegion& aRegion) override
   {
     NS_ASSERTION(ClientManager()->InConstruction(),
                  "Can only set properties in construction phase");
     CanvasLayer::SetVisibleRegion(aRegion);
   }
 
   virtual void RenderLayer() override;
 
   virtual void ClearCachedResources() override
   {
-    if (mBufferProvider) {
-      mBufferProvider->ClearCachedResources();
-    }
-    if (mCanvasClient) {
-      mCanvasClient->Clear();
-    }
+    mCanvasRenderer->ClearCachedResources();
   }
 
   virtual void HandleMemoryPressure() override
   {
-    if (mBufferProvider) {
-      mBufferProvider->ClearCachedResources();
-    }
-    if (mCanvasClient) {
-      mCanvasClient->HandleMemoryPressure();
-    }
+    mCanvasRenderer->ClearCachedResources();
   }
 
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) override
   {
     aAttrs = CanvasLayerAttributes(mSamplingFilter, mBounds);
   }
 
   virtual Layer* AsLayer()  override { return this; }
   virtual ShadowableLayer* AsShadowableLayer()  override { return this; }
 
   virtual void Disconnect() override
   {
-    if (mBufferProvider) {
-      mBufferProvider->ClearCachedResources();
-    }
-    mCanvasClient = nullptr;
-  }
-
-  virtual CompositableForwarder* GetForwarder() override
-  {
-    return mManager->AsShadowForwarder();
+    mCanvasRenderer->Destroy();
   }
 
   virtual CompositableClient* GetCompositableClient() override
   {
-    return mCanvasClient;
-  }
-
-  virtual void AttachCompositable() override
-  {
-    if (HasShadow()) {
-      if (mAsyncRenderer) {
-        static_cast<CanvasClientBridge*>(mCanvasClient.get())->SetLayer(this);
-      } else {
-        mCanvasClient->Connect();
-        ClientManager()->AsShadowForwarder()->Attach(mCanvasClient, this);
-      }
-    }
+    ClientCanvasRenderer* canvasRenderer = mCanvasRenderer->AsClientCanvasRenderer();
+    MOZ_ASSERT(canvasRenderer);
+    return canvasRenderer->GetCanvasClient();
   }
 
 protected:
   ClientLayerManager* ClientManager()
   {
     return static_cast<ClientLayerManager*>(mManager);
   }
 };
new file mode 100644
--- /dev/null
+++ b/gfx/layers/client/ClientCanvasRenderer.cpp
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ClientCanvasRenderer.h"
+
+#include "ClientCanvasLayer.h"
+
+namespace mozilla {
+namespace layers {
+
+CompositableForwarder*
+ClientCanvasRenderer::GetForwarder()
+{
+  return mLayer->Manager()->AsShadowForwarder();
+}
+
+bool
+ClientCanvasRenderer::CreateCompositable()
+{
+  if (!mCanvasClient) {
+    TextureFlags flags = TextureFlags::DEFAULT;
+    if (mOriginPos == gl::OriginPos::BottomLeft) {
+      flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
+    }
+
+    if (!mIsAlphaPremultiplied) {
+      flags |= TextureFlags::NON_PREMULTIPLIED;
+    }
+
+    mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
+                                                     GetForwarder(),
+                                                     flags);
+    if (!mCanvasClient) {
+      return false;
+    }
+
+    if (mLayer->HasShadow()) {
+      if (mAsyncRenderer) {
+        static_cast<CanvasClientBridge*>(mCanvasClient.get())->SetLayer(mLayer);
+      } else {
+        mCanvasClient->Connect();
+        GetForwarder()->AsLayerForwarder()->Attach(mCanvasClient, mLayer);
+      }
+    }
+  }
+
+  return true;
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/client/ClientCanvasRenderer.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFX_CLIENTCANVASRENDERER_H
+#define GFX_CLIENTCANVASRENDERER_H
+
+#include "ShareableCanvasRenderer.h"
+
+namespace mozilla {
+namespace layers {
+
+class ClientCanvasLayer;
+class ClientCanvasRenderer : public ShareableCanvasRenderer
+{
+public:
+  explicit ClientCanvasRenderer(ClientCanvasLayer* aLayer)
+    : mLayer(aLayer)
+  { }
+
+  ClientCanvasRenderer* AsClientCanvasRenderer() override { return this; }
+
+  CompositableForwarder* GetForwarder() override;
+
+  bool CreateCompositable() override;
+
+protected:
+  ClientCanvasLayer* mLayer;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif
--- a/gfx/layers/composite/CanvasLayerComposite.h
+++ b/gfx/layers/composite/CanvasLayerComposite.h
@@ -28,22 +28,16 @@ class CanvasLayerComposite : public Canv
 {
 public:
   explicit CanvasLayerComposite(LayerManagerComposite* aManager);
 
 protected:
   virtual ~CanvasLayerComposite();
 
 public:
-  // CanvasLayer impl
-  virtual void Initialize(const Data& aData) override
-  {
-    MOZ_CRASH("Incompatibe surface type");
-  }
-
   virtual bool SetCompositableHost(CompositableHost* aHost) override;
 
   virtual void Disconnect() override
   {
     Destroy();
   }
 
   virtual void SetLayerManager(HostLayerManager* aManager) override;
@@ -58,16 +52,21 @@ public:
 
   CompositableHost* GetCompositableHost() override;
 
   virtual HostLayer* AsHostLayer() override { return this; }
 
   virtual const char* Name() const override { return "CanvasLayerComposite"; }
 
 protected:
+  CanvasRenderer* CreateCanvasRendererInternal() override {
+    MOZ_CRASH("Incompatible surface type");
+    return nullptr;
+  }
+
   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
 
 private:
   gfx::SamplingFilter GetSamplingFilter();
 
 private:
   RefPtr<CompositableHost> mCompositableHost;
 };
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -1066,36 +1066,36 @@ LayerManagerComposite::RenderToPresentat
 {
   widget::CompositorWidget* const widget = mCompositor->GetWidget();
   ANativeWindow* window = widget->AsAndroid()->GetPresentationANativeWindow();
 
   if (!window) {
     return;
   }
 
-  EGLSurface surface = widget->AsAndroid()->GetPresentationEGLSurface();
-
-  if (!surface) {
-    //create surface;
-    surface = GLContextProviderEGL::CreateEGLSurface(window);
-    if (!surface) {
-      return;
-    }
-
-    widget->AsAndroid()->SetPresentationEGLSurface(surface);
-  }
-
   CompositorOGL* compositor = mCompositor->AsCompositorOGL();
   GLContext* gl = compositor->gl();
   GLContextEGL* egl = GLContextEGL::Cast(gl);
 
   if (!egl) {
     return;
   }
 
+  EGLSurface surface = widget->AsAndroid()->GetPresentationEGLSurface();
+
+  if (!surface) {
+    //create surface;
+    surface = egl->CreateCompatibleSurface(window);
+    if (!surface) {
+      return;
+    }
+
+    widget->AsAndroid()->SetPresentationEGLSurface(surface);
+  }
+
   const IntSize windowSize(ANativeWindow_getWidth(window),
                            ANativeWindow_getHeight(window));
 
 
   if ((windowSize.width <= 0) || (windowSize.height <= 0)) {
     return;
   }
 
--- a/gfx/layers/ipc/PWebRenderBridge.ipdl
+++ b/gfx/layers/ipc/PWebRenderBridge.ipdl
@@ -58,18 +58,18 @@ parent:
   async DPEnd(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
               LayoutSize aContentSize, ByteBuffer aDL, BuiltDisplayListDescriptor aDLDesc,
               WebRenderScrollData aScrollData, IdNamespace aIdNamespace, TimeStamp fwdTime);
   sync DPSyncEnd(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
                  LayoutSize aContentSize, ByteBuffer aDL, BuiltDisplayListDescriptor aDLDesc,
                  WebRenderScrollData aScrollData, IdNamespace aIdNamespace, TimeStamp fwdTime);
   async ParentCommands(WebRenderParentCommand[] commands);
   sync DPGetSnapshot(PTexture texture);
-  async AddPipelineIdForAsyncCompositable(PipelineId aImageId, CompositableHandle aHandle);
-  async RemovePipelineIdForAsyncCompositable(PipelineId aPipelineId);
+  async AddPipelineIdForCompositable(PipelineId aImageId, CompositableHandle aHandle, bool aAsync);
+  async RemovePipelineIdForCompositable(PipelineId aPipelineId);
   async AddExternalImageIdForCompositable(ExternalImageId aImageId, CompositableHandle aHandle);
   async RemoveExternalImageId(ExternalImageId aImageId);
   async SetLayerObserverEpoch(uint64_t layerObserverEpoch);
   async ClearCachedResources();
   // Schedule a composite if one isn't already scheduled.
   async ForceComposite();
 
   // These correspond exactly to the equivalent APIs in PLayerTransaction -
--- a/gfx/layers/mlgpu/CanvasLayerMLGPU.h
+++ b/gfx/layers/mlgpu/CanvasLayerMLGPU.h
@@ -27,32 +27,33 @@ class CanvasLayerMLGPU final : public Ca
 {
 public:
   explicit CanvasLayerMLGPU(LayerManagerMLGPU* aManager);
 
 protected:
   ~CanvasLayerMLGPU() override;
 
 public:
-  void Initialize(const Data& aData) override {
-    MOZ_CRASH("Incompatibe surface type");
-  }
-
   Layer* GetLayer() override;
   void Disconnect() override;
 
   HostLayer* AsHostLayer() override { return this; }
   CanvasLayerMLGPU* AsCanvasLayerMLGPU() override { return this; }
   gfx::SamplingFilter GetSamplingFilter() override;
   void ClearCachedResources() override;
   void SetRegionToRender(LayerIntRegion&& aRegion) override;
 
   MOZ_LAYER_DECL_NAME("CanvasLayerMLGPU", TYPE_CANVAS)
 
 protected:
+  CanvasRenderer* CreateCanvasRendererInternal() override {
+    MOZ_CRASH("Incompatible surface type");
+    return nullptr;
+  }
+
   void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
   void CleanupResources();
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif /* GFX_CanvasLayerMLGPU_H */
--- a/gfx/layers/mlgpu/FrameBuilder.cpp
+++ b/gfx/layers/mlgpu/FrameBuilder.cpp
@@ -150,27 +150,16 @@ FrameBuilder::ProcessContainerLayer(Cont
 
   // We don't want to traverse containers twice, so we only traverse them if
   // they haven't been prepared yet.
   bool isFirstVisit = !layer->IsPrepared();
   if (isFirstVisit && !layer->PrepareToRender(this, aClipRect)) {
     return false;
   }
 
-  // If the container is not part of the invalid region, we don't draw it
-  // or traverse it. Note that we do not pass the geometry here. Otherwise
-  // we could decide the particular split is not visible, and because of the
-  // check above, never bother traversing the container again.
-  gfx::IntRect boundingBox = layer->GetClippedBoundingBox(aView, Nothing());
-  const gfx::IntRect& invalidRect = aView->GetInvalidRect();
-  if (boundingBox.IsEmpty() || !invalidRect.Intersects(boundingBox)) {
-    AL_LOG("Culling ContainerLayer %p that does not need painting\n", aContainer);
-    return false;
-  }
-
   if (!aContainer->UseIntermediateSurface()) {
     // In case the layer previously required an intermediate surface, we
     // clear any intermediate render targets here.
     layer->ClearCachedResources();
 
     // This is a pass-through container, so we just process children and
     // instruct AssignLayer to early-return.
     ProcessChildList(aContainer, aView, aClipRect, aGeometry);
--- a/gfx/layers/mlgpu/RenderPassMLGPU.cpp
+++ b/gfx/layers/mlgpu/RenderPassMLGPU.cpp
@@ -464,17 +464,22 @@ TexturedRenderPass::AddItem(Txn& aTxn,
   }
 
   MOZ_ASSERT(!aInfo.geometry);
   MOZ_ASSERT(aInfo.HasRectTransformAndClip());
   MOZ_ASSERT(mHasRectTransformAndClip);
 
   const Matrix4x4& fullTransform = aInfo.layer->GetLayer()->GetEffectiveTransformForBuffer();
   Matrix transform = fullTransform.As2D();
-  Matrix inverse = transform.Inverse();
+  Matrix inverse = transform;
+  if (!inverse.Invert()) {
+    // Degenerate transforms are not visible, since there is no mapping to
+    // screen space. Just return without adding any draws.
+    return true;
+  }
   MOZ_ASSERT(inverse.IsRectilinear());
 
   // Transform the clip rect.
   IntRect clipRect = aInfo.layer->GetComputedClipRect().ToUnknownRect();
   clipRect += aInfo.view->GetTargetOffset();
 
   // Clip and adjust the texture rect.
   Rect localClip = inverse.TransformBounds(Rect(clipRect));
--- a/gfx/layers/mlgpu/SharedBufferMLGPU.h
+++ b/gfx/layers/mlgpu/SharedBufferMLGPU.h
@@ -2,16 +2,17 @@
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_gfx_layers_mlgpu_SharedBufferMLGPU_h
 #define mozilla_gfx_layers_mlgpu_SharedBufferMLGPU_h
 
 #include "ShaderDefinitionsMLGPU.h"
+#include "MLGDevice.h"
 #include "MLGDeviceTypes.h"
 #include "StagingBuffer.h"
 #include "mozilla/gfx/Logging.h"
 
 namespace mozilla {
 namespace layers {
 
 class MLGBuffer;
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -124,16 +124,17 @@ EXPORTS.mozilla.layers += [
     'AtomicRefCountedWithFinalize.h',
     'AxisPhysicsModel.h',
     'AxisPhysicsMSDModel.h',
     'basic/BasicCompositor.h',
     'basic/MacIOSurfaceTextureHostBasic.h',
     'basic/TextureHostBasic.h',
     'BSPTree.h',
     'BufferTexture.h',
+    'CanvasRenderer.h',
     'client/CanvasClient.h',
     'client/CompositableClient.h',
     'client/ContentClient.h',
     'client/GPUVideoTextureClient.h',
     'client/ImageClient.h',
     'client/SingleTiledContentClient.h',
     'client/TextureClient.h',
     'client/TextureClientPool.h',
@@ -155,16 +156,17 @@ EXPORTS.mozilla.layers += [
     'composite/ImageLayerComposite.h',
     'composite/LayerManagerComposite.h',
     'composite/PaintedLayerComposite.h',
     'composite/TextRenderer.h',
     'composite/TextureHost.h',
     'composite/TiledContentHost.h',
     'Compositor.h',
     'CompositorTypes.h',
+    'CopyableCanvasRenderer.h',
     'D3D11ShareHandleImage.h',
     'D3D11YCbCrImage.h',
     'D3D9SurfaceImage.h',
     'DirectionUtils.h',
     'Effects.h',
     'ImageDataSerializer.h',
     'ipc/APZChild.h',
     'ipc/APZCTreeManagerChild.h',
@@ -214,27 +216,29 @@ EXPORTS.mozilla.layers += [
     'opengl/CompositorOGL.h',
     'opengl/MacIOSurfaceTextureClientOGL.h',
     'opengl/MacIOSurfaceTextureHostOGL.h',
     'opengl/TextureClientOGL.h',
     'opengl/TextureHostOGL.h',
     'PaintThread.h',
     'PersistentBufferProvider.h',
     'RenderTrace.h',
+    'ShareableCanvasRenderer.h',
     'SourceSurfaceSharedData.h',
     'SourceSurfaceVolatileData.h',
     'TextureSourceProvider.h',
     'TextureWrapperImage.h',
     'TransactionIdAllocator.h',
     'UpdateImageHelper.h',
     'wr/AsyncImagePipelineManager.h',
     'wr/ScrollingLayersHelper.h',
     'wr/StackingContextHelper.h',
     'wr/WebRenderBridgeChild.h',
     'wr/WebRenderBridgeParent.h',
+    'wr/WebRenderCanvasRenderer.h',
     'wr/WebRenderDisplayItemLayer.h',
     'wr/WebRenderImageHost.h',
     'wr/WebRenderLayer.h',
     'wr/WebRenderLayerManager.h',
     'wr/WebRenderLayersLogging.h',
     'wr/WebRenderMessageUtils.h',
     'wr/WebRenderScrollData.h',
     'wr/WebRenderScrollDataWrapper.h',
@@ -335,19 +339,21 @@ UNIFIED_SOURCES += [
     'basic/BasicLayerManager.cpp',
     'basic/BasicLayersImpl.cpp',
     'basic/BasicPaintedLayer.cpp',
     'basic/BasicTextLayer.cpp',
     'basic/TextureHostBasic.cpp',
     'BSPTree.cpp',
     'BufferTexture.cpp',
     'BufferUnrotate.cpp',
+    'CanvasRenderer.cpp',
     'client/CanvasClient.cpp',
     'client/ClientBorderLayer.cpp',
     'client/ClientCanvasLayer.cpp',
+    'client/ClientCanvasRenderer.cpp',
     'client/ClientColorLayer.cpp',
     'client/ClientContainerLayer.cpp',
     'client/ClientImageLayer.cpp',
     'client/ClientLayerManager.cpp',
     'client/ClientPaintedLayer.cpp',
     'client/ClientTextLayer.cpp',
     'client/ClientTiledPaintedLayer.cpp',
     'client/CompositableClient.cpp',
@@ -375,17 +381,17 @@ UNIFIED_SOURCES += [
     'composite/ImageHost.cpp',
     'composite/ImageLayerComposite.cpp',
     'composite/LayerManagerComposite.cpp',
     'composite/PaintedLayerComposite.cpp',
     'composite/TextRenderer.cpp',
     'composite/TextureHost.cpp',
     'composite/TiledContentHost.cpp',
     'Compositor.cpp',
-    'CopyableCanvasLayer.cpp',
+    'CopyableCanvasRenderer.cpp',
     'Effects.cpp',
     'FrameMetrics.cpp',
     'GLImages.cpp',
     'ImageDataSerializer.cpp',
     'ImageLayers.cpp',
     'ipc/APZChild.cpp',
     'ipc/APZCTreeManagerChild.cpp',
     'ipc/APZCTreeManagerParent.cpp',
@@ -442,27 +448,28 @@ UNIFIED_SOURCES += [
     'opengl/TextureClientOGL.cpp',
     'opengl/TextureHostOGL.cpp',
     'opengl/TexturePoolOGL.cpp',
     'PaintThread.cpp',
     'protobuf/LayerScopePacket.pb.cc',
     'ReadbackProcessor.cpp',
     'RenderTrace.cpp',
     'RotatedBuffer.cpp',
-    'ShareableCanvasLayer.cpp',
+    'ShareableCanvasRenderer.cpp',
     'SourceSurfaceSharedData.cpp',
     'SourceSurfaceVolatileData.cpp',
     'TextureSourceProvider.cpp',
     'TextureWrapperImage.cpp',
     'wr/AsyncImagePipelineManager.cpp',
     'wr/ScrollingLayersHelper.cpp',
     'wr/StackingContextHelper.cpp',
     'wr/WebRenderBridgeChild.cpp',
     'wr/WebRenderBridgeParent.cpp',
     'wr/WebRenderCanvasLayer.cpp',
+    'wr/WebRenderCanvasRenderer.cpp',
     'wr/WebRenderColorLayer.cpp',
     'wr/WebRenderContainerLayer.cpp',
     'wr/WebRenderDisplayItemLayer.cpp',
     'wr/WebRenderImageHost.cpp',
     'wr/WebRenderImageLayer.cpp',
     'wr/WebRenderLayer.cpp',
     'wr/WebRenderLayerManager.cpp',
     'wr/WebRenderLayersLogging.cpp',
--- a/gfx/layers/wr/StackingContextHelper.cpp
+++ b/gfx/layers/wr/StackingContextHelper.cpp
@@ -19,31 +19,31 @@ StackingContextHelper::StackingContextHe
 
 StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParentSC,
                                              wr::DisplayListBuilder& aBuilder,
                                              LayerRect aBoundForSC,
                                              LayerPoint aOrigin,
                                              uint64_t aAnimationsId,
                                              float* aOpacityPtr,
                                              gfx::Matrix4x4* aTransformPtr,
-                                             const nsTArray<wr::WrFilterOp>& aFilters)
+                                             const nsTArray<wr::WrFilterOp>& aFilters,
+                                             const gfx::CompositionOp& aMixBlendMode)
   : mBuilder(&aBuilder)
 {
   wr::LayoutRect scBounds = aParentSC.ToRelativeLayoutRect(aBoundForSC);
   if (aTransformPtr) {
     mTransform = *aTransformPtr;
   }
 
   mBuilder->PushStackingContext(scBounds,
                                 aAnimationsId,
                                 aOpacityPtr,
                                 aTransformPtr,
                                 wr::TransformStyle::Flat,
-                                // TODO: set correct blend mode.
-                                wr::ToMixBlendMode(gfx::CompositionOp::OP_OVER),
+                                wr::ToMixBlendMode(aMixBlendMode),
                                 aFilters);
 
   mOrigin = aOrigin;
 }
 
 StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParentSC,
                                              wr::DisplayListBuilder& aBuilder,
                                              WebRenderLayer* aLayer,
--- a/gfx/layers/wr/StackingContextHelper.h
+++ b/gfx/layers/wr/StackingContextHelper.h
@@ -45,17 +45,18 @@ public:
   // The constructor for layers-free mode.
   StackingContextHelper(const StackingContextHelper& aParentSC,
                         wr::DisplayListBuilder& aBuilder,
                         LayerRect aBoundForSC,
                         LayerPoint aOrigin,
                         uint64_t aAnimationsId,
                         float* aOpacityPtr,
                         gfx::Matrix4x4* aTransformPtr,
-                        const nsTArray<wr::WrFilterOp>& aFilters = nsTArray<wr::WrFilterOp>());
+                        const nsTArray<wr::WrFilterOp>& aFilters = nsTArray<wr::WrFilterOp>(),
+                        const gfx::CompositionOp& aMixBlendMode = gfx::CompositionOp::OP_OVER);
   // This version of the constructor should only be used at the root level
   // of the tree, so that we have a StackingContextHelper to pass down into
   // the RenderLayer traversal, but don't actually want it to push a stacking
   // context on the display list builder.
   StackingContextHelper();
 
   // Pops the stacking context, if one was pushed during the constructor.
   ~StackingContextHelper();
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp
+++ b/gfx/layers/wr/WebRenderBridgeChild.cpp
@@ -139,23 +139,30 @@ WebRenderBridgeChild::ProcessWebRenderPa
   this->SendParentCommands(mParentCommands);
   mParentCommands.Clear();
 }
 
 void
 WebRenderBridgeChild::AddPipelineIdForAsyncCompositable(const wr::PipelineId& aPipelineId,
                                                         const CompositableHandle& aHandle)
 {
-  SendAddPipelineIdForAsyncCompositable(aPipelineId, aHandle);
+  SendAddPipelineIdForCompositable(aPipelineId, aHandle, true);
 }
 
 void
-WebRenderBridgeChild::RemovePipelineIdForAsyncCompositable(const wr::PipelineId& aPipelineId)
+WebRenderBridgeChild::AddPipelineIdForCompositable(const wr::PipelineId& aPipelineId,
+                                                   const CompositableHandle& aHandle)
 {
-  SendRemovePipelineIdForAsyncCompositable(aPipelineId);
+  SendAddPipelineIdForCompositable(aPipelineId, aHandle, false);
+}
+
+void
+WebRenderBridgeChild::RemovePipelineIdForCompositable(const wr::PipelineId& aPipelineId)
+{
+  SendRemovePipelineIdForCompositable(aPipelineId);
 }
 
 wr::ExternalImageId
 WebRenderBridgeChild::GetNextExternalImageId()
 {
   wr::MaybeExternalImageId id = GetCompositorBridgeChild()->GetNextExternalImageId();
   MOZ_RELEASE_ASSERT(id.isSome());
   return id.value();
--- a/gfx/layers/wr/WebRenderBridgeChild.h
+++ b/gfx/layers/wr/WebRenderBridgeChild.h
@@ -71,17 +71,19 @@ public:
   wr::PipelineId GetPipeline() { return mPipelineId; }
 
   // KnowsCompositor
   TextureForwarder* GetTextureForwarder() override;
   LayersIPCActor* GetLayersIPCActor() override;
 
   void AddPipelineIdForAsyncCompositable(const wr::PipelineId& aPipelineId,
                                          const CompositableHandle& aHandlee);
-  void RemovePipelineIdForAsyncCompositable(const wr::PipelineId& aPipelineId);
+  void AddPipelineIdForCompositable(const wr::PipelineId& aPipelineId,
+                                    const CompositableHandle& aHandlee);
+  void RemovePipelineIdForCompositable(const wr::PipelineId& aPipelineId);
 
   wr::ExternalImageId AllocExternalImageIdForCompositable(CompositableClient* aCompositable);
   void DeallocExternalImageId(wr::ExternalImageId& aImageId);
 
   /**
    * Clean this up, finishing with SendShutDown() which will cause __delete__
    * to be sent from the parent side.
    */
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -740,30 +740,36 @@ WebRenderBridgeParent::RecvDPGetSnapshot
   mApi->Readback(size, buffer, buffer_size);
 
   mForceRendering = false;
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvAddPipelineIdForAsyncCompositable(const wr::PipelineId& aPipelineId,
-                                                             const CompositableHandle& aHandle)
+WebRenderBridgeParent::RecvAddPipelineIdForCompositable(const wr::PipelineId& aPipelineId,
+                                                        const CompositableHandle& aHandle,
+                                                        const bool& aAsync)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
 
   MOZ_ASSERT(!mAsyncCompositables.Get(wr::AsUint64(aPipelineId)).get());
 
-  RefPtr<ImageBridgeParent> imageBridge = ImageBridgeParent::GetInstance(OtherPid());
-  if (!imageBridge) {
-     return IPC_FAIL_NO_REASON(this);
+  RefPtr<CompositableHost> host;
+  if (aAsync) {
+    RefPtr<ImageBridgeParent> imageBridge = ImageBridgeParent::GetInstance(OtherPid());
+    if (!imageBridge) {
+       return IPC_FAIL_NO_REASON(this);
+    }
+    host = imageBridge->FindCompositable(aHandle);
+  } else {
+    host = FindCompositable(aHandle);
   }
-  RefPtr<CompositableHost> host = imageBridge->FindCompositable(aHandle);
   if (!host) {
     return IPC_FAIL_NO_REASON(this);
   }
   MOZ_ASSERT(host->AsWebRenderImageHost());
   WebRenderImageHost* wrHost = host->AsWebRenderImageHost();
   if (!wrHost) {
     return IPC_OK();
   }
@@ -771,17 +777,17 @@ WebRenderBridgeParent::RecvAddPipelineId
   wrHost->SetWrBridge(this);
   mAsyncCompositables.Put(wr::AsUint64(aPipelineId), wrHost);
   mAsyncImageManager->AddAsyncImagePipeline(aPipelineId, wrHost);
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvRemovePipelineIdForAsyncCompositable(const wr::PipelineId& aPipelineId)
+WebRenderBridgeParent::RecvRemovePipelineIdForCompositable(const wr::PipelineId& aPipelineId)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
 
   WebRenderImageHost* wrHost = mAsyncCompositables.Get(wr::AsUint64(aPipelineId)).get();
   if (!wrHost) {
     return IPC_OK();
@@ -1304,17 +1310,16 @@ WebRenderBridgeParent::ClearResources()
   DeleteOldImages();
   for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) {
     iter.Data()->ClearWrBridge();
   }
   mExternalImageIds.Clear();
   for (auto iter = mAsyncCompositables.Iter(); !iter.Done(); iter.Next()) {
     wr::PipelineId pipelineId = wr::AsPipelineId(iter.Key());
     RefPtr<WebRenderImageHost> host = iter.Data();
-    MOZ_ASSERT(host->GetAsyncRef());
     host->ClearWrBridge();
     mAsyncImageManager->RemoveAsyncImagePipeline(mApi, pipelineId);
   }
   mAsyncCompositables.Clear();
 
   mAsyncImageManager->RemovePipeline(mPipelineId, wr::NewEpoch(wrEpoch));
 
   for (std::unordered_set<uint64_t>::iterator iter = mActiveAnimations.begin(); iter != mActiveAnimations.end(); iter++) {
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -113,19 +113,20 @@ public:
                                         const wr::ByteBuffer& dl,
                                         const wr::BuiltDisplayListDescriptor& dlDesc,
                                         const WebRenderScrollData& aScrollData,
                                         const wr::IdNamespace& aIdNamespace,
                                         const TimeStamp& aFwdTime) override;
   mozilla::ipc::IPCResult RecvParentCommands(nsTArray<WebRenderParentCommand>&& commands) override;
   mozilla::ipc::IPCResult RecvDPGetSnapshot(PTextureParent* aTexture) override;
 
-  mozilla::ipc::IPCResult RecvAddPipelineIdForAsyncCompositable(const wr::PipelineId& aPipelineIds,
-                                                                const CompositableHandle& aHandle) override;
-  mozilla::ipc::IPCResult RecvRemovePipelineIdForAsyncCompositable(const wr::PipelineId& aPipelineId) override;
+  mozilla::ipc::IPCResult RecvAddPipelineIdForCompositable(const wr::PipelineId& aPipelineIds,
+                                                           const CompositableHandle& aHandle,
+                                                           const bool& aAsync) override;
+  mozilla::ipc::IPCResult RecvRemovePipelineIdForCompositable(const wr::PipelineId& aPipelineId) override;
 
   mozilla::ipc::IPCResult RecvAddExternalImageIdForCompositable(const ExternalImageId& aImageId,
                                                                 const CompositableHandle& aHandle) override;
   mozilla::ipc::IPCResult RecvRemoveExternalImageId(const ExternalImageId& aImageId) override;
   mozilla::ipc::IPCResult RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch) override;
 
   mozilla::ipc::IPCResult RecvClearCachedResources() override;
   mozilla::ipc::IPCResult RecvForceComposite() override;
--- a/gfx/layers/wr/WebRenderCanvasLayer.cpp
+++ b/gfx/layers/wr/WebRenderCanvasLayer.cpp
@@ -15,62 +15,42 @@
 #include "mozilla/layers/ScrollingLayersHelper.h"
 #include "mozilla/layers/StackingContextHelper.h"
 #include "mozilla/layers/TextureClientSharedSurface.h"
 #include "mozilla/layers/WebRenderBridgeChild.h"
 #include "PersistentBufferProvider.h"
 #include "SharedSurface.h"
 #include "SharedSurfaceGL.h"
 #include "mozilla/webrender/WebRenderTypes.h"
+#include "WebRenderCanvasRenderer.h"
 
 namespace mozilla {
 namespace layers {
 
 WebRenderCanvasLayer::~WebRenderCanvasLayer()
 {
   MOZ_COUNT_DTOR(WebRenderCanvasLayer);
-  ClearWrResources();
-}
-
-void
-WebRenderCanvasLayer::ClearWrResources()
-{
-  if (mExternalImageId.isSome()) {
-    WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
-    mExternalImageId = Nothing();
-  }
 }
 
-void
-WebRenderCanvasLayer::Initialize(const Data& aData)
+CanvasRenderer*
+WebRenderCanvasLayer::CreateCanvasRendererInternal()
 {
-  ShareableCanvasLayer::Initialize(aData);
-
-  // XXX: Use basic surface factory until we support shared surface.
-  if (!mGLContext || mGLFrontbuffer)
-    return;
-
-  gl::GLScreenBuffer* screen = mGLContext->Screen();
-  auto factory = MakeUnique<gl::SurfaceFactory_Basic>(mGLContext, screen->mCaps, mFlags);
-  screen->Morph(Move(factory));
+  return new WebRenderCanvasRendererSync(mManager->AsWebRenderLayerManager());
 }
 
 void
 WebRenderCanvasLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
                                   const StackingContextHelper& aSc)
 {
-  UpdateCompositableClient();
-
-  if (mExternalImageId.isNothing()) {
-    mExternalImageId = Some(WrBridge()->AllocExternalImageIdForCompositable(mCanvasClient));
-  }
+  WebRenderCanvasRendererSync* canvasRenderer = mCanvasRenderer->AsWebRenderCanvasRendererSync();
+  MOZ_ASSERT(canvasRenderer);
+  canvasRenderer->UpdateCompositableClient();
 
   Maybe<gfx::Matrix4x4> transform;
-  const bool needsYFlip = (mOriginPos == gl::OriginPos::BottomLeft);
-  if (needsYFlip) {
+  if (canvasRenderer->NeedsYFlip()) {
     transform = Some(GetTransform().PreTranslate(0, mBounds.height, 0).PreScale(1, -1, 1));
   }
 
   ScrollingLayersHelper scroller(this, aBuilder, aSc);
   StackingContextHelper sc(aSc, aBuilder, this, transform);
 
   LayerRect rect(0, 0, mBounds.width, mBounds.height);
   DumpLayerInfo("CanvasLayer", rect);
@@ -79,41 +59,23 @@ WebRenderCanvasLayer::RenderLayer(wr::Di
 
   if (gfxPrefs::LayersDump()) {
     printf_stderr("CanvasLayer %p texture-filter=%s\n",
                   this->GetLayer(),
                   Stringify(filter).c_str());
   }
 
   wr::WrImageKey key = GenerateImageKey();
-  WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(mExternalImageId.value(), key));
+  WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(canvasRenderer->GetExternalImageId().value(), key));
   WrManager()->AddImageKeyForDiscard(key);
 
   wr::LayoutRect r = sc.ToRelativeLayoutRect(rect);
   aBuilder.PushImage(r, r, filter, key);
 }
 
 void
-WebRenderCanvasLayer::AttachCompositable()
-{
-  mCanvasClient->Connect();
-}
-
-CompositableForwarder*
-WebRenderCanvasLayer::GetForwarder()
-{
-  return WrManager()->WrBridge();
-}
-
-void
 WebRenderCanvasLayer::ClearCachedResources()
 {
-  ClearWrResources();
-  if (mBufferProvider) {
-    mBufferProvider->ClearCachedResources();
-  }
-  if (mCanvasClient) {
-    mCanvasClient->Clear();
-  }
+  mCanvasRenderer->ClearCachedResources();
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/wr/WebRenderCanvasLayer.h
+++ b/gfx/layers/wr/WebRenderCanvasLayer.h
@@ -1,55 +1,46 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_WEBRENDERCANVASLAYER_H
 #define GFX_WEBRENDERCANVASLAYER_H
 
+#include "Layers.h"
 #include "mozilla/layers/WebRenderLayer.h"
 #include "mozilla/layers/WebRenderLayerManager.h"
-#include "ShareableCanvasLayer.h"
 
 namespace mozilla {
 namespace gfx {
 class SourceSurface;
 }; // namespace gfx
 
 namespace layers {
 
 class WebRenderCanvasLayer : public WebRenderLayer,
-                             public ShareableCanvasLayer
+                             public CanvasLayer
 {
 public:
   explicit WebRenderCanvasLayer(WebRenderLayerManager* aLayerManager)
-    : ShareableCanvasLayer(aLayerManager, static_cast<WebRenderLayer*>(this))
+    : CanvasLayer(aLayerManager, static_cast<WebRenderLayer*>(this))
   {
     MOZ_COUNT_CTOR(WebRenderCanvasLayer);
   }
 
-  virtual void Initialize(const Data& aData) override;
-
-  virtual CompositableForwarder* GetForwarder() override;
-
-  virtual void AttachCompositable() override;
+  CanvasRenderer* CreateCanvasRendererInternal() override;
 
   virtual void ClearCachedResources() override;
 
 protected:
   virtual ~WebRenderCanvasLayer();
 
-  void ClearWrResources();
-
 public:
   Layer* GetLayer() override { return this; }
   void RenderLayer(wr::DisplayListBuilder& aBuilder,
                    const StackingContextHelper& aSc) override;
-
-protected:
-  wr::MaybeExternalImageId mExternalImageId;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // GFX_WEBRENDERCANVASLAYER_H
new file mode 100644
--- /dev/null
+++ b/gfx/layers/wr/WebRenderCanvasRenderer.cpp
@@ -0,0 +1,171 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "WebRenderCanvasRenderer.h"
+
+#include "GLContext.h"
+#include "GLScreenBuffer.h"
+#include "SharedSurfaceGL.h"
+#include "WebRenderBridgeChild.h"
+#include "WebRenderLayerManager.h"
+
+namespace mozilla {
+namespace layers {
+
+CompositableForwarder*
+WebRenderCanvasRenderer::GetForwarder()
+{
+  return mManager->WrBridge();
+}
+
+void
+WebRenderCanvasRenderer::Initialize(const CanvasInitializeData& aData)
+{
+  ShareableCanvasRenderer::Initialize(aData);
+
+  // XXX: Use basic surface factory until we support shared surface.
+  if (!mGLContext || mGLFrontbuffer)
+    return;
+
+  gl::GLScreenBuffer* screen = mGLContext->Screen();
+  auto factory = MakeUnique<gl::SurfaceFactory_Basic>(mGLContext,
+                                                      screen->mCaps,
+                                                      mFlags);
+  screen->Morph(Move(factory));
+}
+
+WebRenderCanvasRendererSync::~WebRenderCanvasRendererSync()
+{
+  Destroy();
+}
+
+void
+WebRenderCanvasRendererSync::Initialize(const CanvasInitializeData& aData)
+{
+  WebRenderCanvasRenderer::Initialize(aData);
+
+  if (mExternalImageId.isSome()) {
+    mManager->WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
+    mExternalImageId.reset();
+  }
+}
+
+bool
+WebRenderCanvasRendererSync::CreateCompositable()
+{
+  if (!mCanvasClient) {
+    TextureFlags flags = TextureFlags::DEFAULT;
+    if (mOriginPos == gl::OriginPos::BottomLeft) {
+      flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
+    }
+
+    if (!mIsAlphaPremultiplied) {
+      flags |= TextureFlags::NON_PREMULTIPLIED;
+    }
+
+    mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
+                                                     GetForwarder(),
+                                                     flags);
+    if (!mCanvasClient) {
+      return false;
+    }
+
+    mCanvasClient->Connect();
+  }
+
+  if (mExternalImageId.isNothing()) {
+    mExternalImageId = Some(mManager->WrBridge()->AllocExternalImageIdForCompositable(mCanvasClient));
+  }
+
+  return true;
+}
+
+void
+WebRenderCanvasRendererSync::ClearCachedResources()
+{
+  if (mExternalImageId.isSome()) {
+    mManager->WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
+    mExternalImageId.reset();
+  }
+}
+
+void
+WebRenderCanvasRendererSync::Destroy()
+{
+  if (mExternalImageId.isSome()) {
+    mManager->WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
+    mExternalImageId.reset();
+  }
+}
+
+WebRenderCanvasRendererAsync::~WebRenderCanvasRendererAsync()
+{
+  Destroy();
+}
+
+void
+WebRenderCanvasRendererAsync::Initialize(const CanvasInitializeData& aData)
+{
+  WebRenderCanvasRenderer::Initialize(aData);
+
+  if (mPipelineId.isSome()) {
+    mManager->WrBridge()->RemovePipelineIdForCompositable(mPipelineId.ref());
+    mPipelineId.reset();
+  }
+}
+
+bool
+WebRenderCanvasRendererAsync::CreateCompositable()
+{
+  if (!mCanvasClient) {
+    TextureFlags flags = TextureFlags::DEFAULT;
+    if (mOriginPos == gl::OriginPos::BottomLeft) {
+      flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
+    }
+
+    if (!mIsAlphaPremultiplied) {
+      flags |= TextureFlags::NON_PREMULTIPLIED;
+    }
+
+    mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
+                                                     GetForwarder(),
+                                                     flags);
+    if (!mCanvasClient) {
+      return false;
+    }
+
+    mCanvasClient->Connect();
+  }
+
+  if (!mPipelineId) {
+    // Alloc async image pipeline id.
+    mPipelineId = Some(mManager->WrBridge()->GetCompositorBridgeChild()->GetNextPipelineId());
+    mManager->WrBridge()->AddPipelineIdForCompositable(mPipelineId.ref(),
+                                                       mCanvasClient->GetIPCHandle());
+  }
+
+  return true;
+}
+
+void
+WebRenderCanvasRendererAsync::ClearCachedResources()
+{
+  if (mPipelineId.isSome()) {
+    mManager->WrBridge()->RemovePipelineIdForCompositable(mPipelineId.ref());
+    mPipelineId.reset();
+  }
+}
+
+void
+WebRenderCanvasRendererAsync::Destroy()
+{
+  if (mPipelineId.isSome()) {
+    mManager->WrBridge()->RemovePipelineIdForCompositable(mPipelineId.ref());
+    mPipelineId.reset();
+  }
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/wr/WebRenderCanvasRenderer.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFX_WEBRENDERCANVASRENDERER_H
+#define GFX_WEBRENDERCANVASRENDERER_H
+
+#include "ShareableCanvasRenderer.h"
+
+namespace mozilla {
+namespace layers {
+
+class WebRenderLayerManager;
+
+class WebRenderCanvasRenderer : public ShareableCanvasRenderer
+{
+public:
+  explicit WebRenderCanvasRenderer(WebRenderLayerManager* aManager)
+    : mManager(aManager)
+  { }
+
+  void Initialize(const CanvasInitializeData& aData) override;
+
+  CompositableForwarder* GetForwarder() override;
+
+protected:
+  WebRenderLayerManager* mManager;
+};
+
+class WebRenderCanvasRendererSync : public WebRenderCanvasRenderer
+{
+public:
+  explicit WebRenderCanvasRendererSync(WebRenderLayerManager* aManager)
+    : WebRenderCanvasRenderer(aManager)
+  { }
+  virtual ~WebRenderCanvasRendererSync();
+
+  WebRenderCanvasRendererSync* AsWebRenderCanvasRendererSync() override { return this; }
+
+  void Initialize(const CanvasInitializeData& aData) override;
+  bool CreateCompositable() override;
+
+  void ClearCachedResources() override;
+  void Destroy() override;
+
+  wr::MaybeExternalImageId GetExternalImageId() { return mExternalImageId; }
+protected:
+  wr::MaybeExternalImageId mExternalImageId;
+};
+
+class WebRenderCanvasRendererAsync : public WebRenderCanvasRenderer
+{
+public:
+  explicit WebRenderCanvasRendererAsync(WebRenderLayerManager* aManager)
+    : WebRenderCanvasRenderer(aManager)
+  { }
+  virtual ~WebRenderCanvasRendererAsync();
+
+  WebRenderCanvasRendererAsync* AsWebRenderCanvasRendererAsync() override { return this; }
+
+  void Initialize(const CanvasInitializeData& aData) override;
+  bool CreateCompositable() override;
+
+  void ClearCachedResources() override;
+  void Destroy() override;
+
+  Maybe<wr::PipelineId> GetPipelineId() { return mPipelineId; }
+protected:
+  Maybe<wr::PipelineId> mPipelineId;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif
--- a/gfx/layers/wr/WebRenderImageLayer.cpp
+++ b/gfx/layers/wr/WebRenderImageLayer.cpp
@@ -42,17 +42,17 @@ WebRenderImageLayer::ClearWrResources()
     WrManager()->AddImageKeyForDiscard(mKey.value());
     mKey = Nothing();
   }
   if (mExternalImageId.isSome()) {
     WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
     mExternalImageId = Nothing();
   }
   if (mPipelineId.isSome()) {
-    WrBridge()->RemovePipelineIdForAsyncCompositable(mPipelineId.ref());
+    WrBridge()->RemovePipelineIdForCompositable(mPipelineId.ref());
     mPipelineId = Nothing();
   }
 }
 
 CompositableType
 WebRenderImageLayer::GetImageClientType()
 {
   if (mImageClientContainerType != CompositableType::UNKNOWN) {
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -10,16 +10,17 @@
 #include "LayersLogging.h"
 #include "mozilla/gfx/DrawEventRecorder.h"
 #include "mozilla/layers/CompositorBridgeChild.h"
 #include "mozilla/layers/StackingContextHelper.h"
 #include "mozilla/layers/TextureClient.h"
 #include "mozilla/layers/WebRenderBridgeChild.h"
 #include "mozilla/layers/UpdateImageHelper.h"
 #include "WebRenderCanvasLayer.h"
+#include "WebRenderCanvasRenderer.h"
 #include "WebRenderColorLayer.h"
 #include "WebRenderContainerLayer.h"
 #include "WebRenderImageLayer.h"
 #include "WebRenderPaintedLayer.h"
 #include "WebRenderPaintedLayerBlob.h"
 #include "WebRenderTextLayer.h"
 #include "WebRenderDisplayItemLayer.h"
 
@@ -588,31 +589,38 @@ WebRenderLayerManager::EndTransactionInt
     // aDisplayList being null here means this is an empty transaction following a layers-free
     // transaction, so we reuse the previously built displaylist and scroll
     // metadata information
     if (aDisplayList && aDisplayListBuilder) {
       StackingContextHelper sc;
       mParentCommands.Clear();
       mScrollData = WebRenderScrollData();
       MOZ_ASSERT(mLayerScrollData.empty());
+      mLastCanvasDatas.Clear();
 
       CreateWebRenderCommandsFromDisplayList(aDisplayList, aDisplayListBuilder, sc, builder);
 
       builder.Finalize(contentSize, mBuiltDisplayList);
 
       // Make a "root" layer data that has everything else as descendants
       mLayerScrollData.emplace_back();
       mLayerScrollData.back().InitializeRoot(mLayerScrollData.size() - 1);
       // Append the WebRenderLayerScrollData items into WebRenderScrollData
       // in reverse order, from topmost to bottommost. This is in keeping with
       // the semantics of WebRenderScrollData.
       for (auto i = mLayerScrollData.crbegin(); i != mLayerScrollData.crend(); i++) {
         mScrollData.AddLayerData(*i);
       }
       mLayerScrollData.clear();
+    } else {
+      for (auto iter = mLastCanvasDatas.Iter(); !iter.Done(); iter.Next()) {
+        RefPtr<WebRenderCanvasData> canvasData = iter.Get()->GetKey();
+        WebRenderCanvasRendererAsync* canvas = canvasData->GetCanvasRenderer();
+        canvas->UpdateCompositableClient();
+      }
     }
 
     builder.PushBuiltDisplayList(mBuiltDisplayList);
     WrBridge()->AddWebRenderParentCommands(mParentCommands);
   } else {
     mScrollData = WebRenderScrollData();
 
     mRoot->StartPendingAnimations(mAnimationReadyTime);
--- a/gfx/layers/wr/WebRenderLayerManager.h
+++ b/gfx/layers/wr/WebRenderLayerManager.h
@@ -185,35 +185,44 @@ public:
   const APZTestData& GetAPZTestData() const
   { return mApzTestData; }
 
   // Those are data that we kept between transactions. We used to cache some
   // data in the layer. But in layers free mode, we don't have layer which
   // means we need some other place to cached the data between transaction.
   // We store the data in frame's property.
   template<class T> already_AddRefed<T>
-  CreateOrRecycleWebRenderUserData(nsDisplayItem* aItem)
+  CreateOrRecycleWebRenderUserData(nsDisplayItem* aItem, bool* aOutIsRecycled = nullptr)
   {
     MOZ_ASSERT(aItem);
     nsIFrame* frame = aItem->Frame();
+    if (aOutIsRecycled) {
+      *aOutIsRecycled = true;
+    }
 
     if (!frame->HasProperty(nsIFrame::WebRenderUserDataProperty())) {
       frame->AddProperty(nsIFrame::WebRenderUserDataProperty(),
                          new nsIFrame::WebRenderUserDataTable());
     }
 
     nsIFrame::WebRenderUserDataTable* userDataTable =
       frame->GetProperty(nsIFrame::WebRenderUserDataProperty());
     RefPtr<WebRenderUserData>& data = userDataTable->GetOrInsert(aItem->GetPerFrameKey());
     if (!data || (data->GetType() != T::Type())) {
       data = new T(this);
+      if (aOutIsRecycled) {
+        *aOutIsRecycled = false;
+      }
     }
 
     MOZ_ASSERT(data);
     MOZ_ASSERT(data->GetType() == T::Type());
+    if (T::Type() == WebRenderUserData::UserDataType::eCanvas) {
+      mLastCanvasDatas.PutEntry(data->AsCanvasData());
+    }
     RefPtr<T> res = static_cast<T*>(data.get());
     return res.forget();
   }
 
 private:
   /**
    * Take a snapshot of the parent context, and copy
    * it into mTarget.
@@ -285,14 +294,18 @@ private:
  // being drawn to the default target, and then copy those pixels
  // back to mTarget.
  RefPtr<gfxContext> mTarget;
 
   // See equivalent field in ClientLayerManager
   uint32_t mPaintSequenceNumber;
   // See equivalent field in ClientLayerManager
   APZTestData mApzTestData;
+
+  typedef nsTHashtable<nsRefPtrHashKey<WebRenderCanvasData>> CanvasDataSet;
+  // Store of WebRenderCanvasData objects for use in empty transactions
+  CanvasDataSet mLastCanvasDatas;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif /* GFX_WEBRENDERLAYERMANAGER_H */
--- a/gfx/layers/wr/WebRenderScrollData.cpp
+++ b/gfx/layers/wr/WebRenderScrollData.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/layers/WebRenderScrollData.h"
 
 #include "Layers.h"
 #include "LayersLogging.h"
 #include "mozilla/layout/RenderFrameParent.h"
 #include "mozilla/Unused.h"
+#include "nsDisplayList.h"
 #include "nsTArray.h"
 #include "UnitTransforms.h"
 
 namespace mozilla {
 namespace layers {
 
 WebRenderLayerScrollData::WebRenderLayerScrollData()
   : mDescendantCount(-1)
--- a/gfx/layers/wr/WebRenderScrollData.h
+++ b/gfx/layers/wr/WebRenderScrollData.h
@@ -14,16 +14,18 @@
 #include "LayersTypes.h"
 #include "mozilla/GfxMessageUtils.h"
 #include "mozilla/layers/LayerAttributes.h"
 #include "mozilla/layers/LayersMessageUtils.h"
 #include "mozilla/layers/FocusTarget.h"
 #include "mozilla/Maybe.h"
 #include "nsTArrayForwardDeclare.h"
 
+class nsDisplayItem;
+
 namespace mozilla {
 
 struct ActiveScrolledRoot;
 
 namespace layers {
 
 class Layer;
 class WebRenderScrollData;
--- a/gfx/layers/wr/WebRenderUserData.cpp
+++ b/gfx/layers/wr/WebRenderUserData.cpp
@@ -1,19 +1,34 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebRenderUserData.h"
+
+#include "mozilla/layers/ImageClient.h"
+#include "mozilla/layers/WebRenderBridgeChild.h"
+#include "mozilla/layers/WebRenderLayerManager.h"
+#include "mozilla/layers/WebRenderMessages.h"
 #include "nsDisplayListInvalidation.h"
+#include "WebRenderCanvasRenderer.h"
 
 namespace mozilla {
 namespace layers {
 
+WebRenderUserData::WebRenderUserData(WebRenderLayerManager* aWRManager)
+  : mWRManager(aWRManager)
+{
+}
+
+WebRenderUserData::~WebRenderUserData()
+{
+}
+
 WebRenderBridgeChild*
 WebRenderUserData::WrBridge() const
 {
   return mWRManager->WrBridge();
 }
 
 WebRenderImageData::WebRenderImageData(WebRenderLayerManager* aWRManager)
   : WebRenderUserData(aWRManager)
@@ -26,17 +41,17 @@ WebRenderImageData::~WebRenderImageData(
     mWRManager->AddImageKeyForDiscard(mKey.value());
   }
 
   if (mExternalImageId) {
     WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
   }
 
   if (mPipelineId) {
-    WrBridge()->RemovePipelineIdForAsyncCompositable(mPipelineId.ref());
+    WrBridge()->RemovePipelineIdForCompositable(mPipelineId.ref());
   }
 }
 
 Maybe<wr::ImageKey>
 WebRenderImageData::UpdateImageKey(ImageContainer* aContainer, bool aForceUpdate)
 {
   CreateImageClientIfNeeded();
   CreateExternalImageIfNeeded();
@@ -86,18 +101,18 @@ WebRenderImageData::GetImageClient()
 }
 
 void
 WebRenderImageData::CreateAsyncImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
                                                       ImageContainer* aContainer,
                                                       const StackingContextHelper& aSc,
                                                       const LayerRect& aBounds,
                                                       const LayerRect& aSCBounds,
-                                                      const Matrix4x4& aSCTransform,
-                                                      const MaybeIntSize& aScaleToSize,
+                                                      const gfx::Matrix4x4& aSCTransform,
+                                                      const gfx::MaybeIntSize& aScaleToSize,
                                                       const wr::ImageRendering& aFilter,
                                                       const wr::MixBlendMode& aMixBlendMode)
 {
   MOZ_ASSERT(aContainer->IsAsync());
   if (!mPipelineId) {
     // Alloc async image pipeline id.
     mPipelineId = Some(WrBridge()->GetCompositorBridgeChild()->GetNextPipelineId());
     WrBridge()->AddPipelineIdForAsyncCompositable(mPipelineId.ref(),
@@ -171,10 +186,29 @@ WebRenderFallbackData::SetGeometry(nsAut
 }
 
 WebRenderAnimationData::WebRenderAnimationData(WebRenderLayerManager* aWRManager)
   : WebRenderUserData(aWRManager),
     mAnimationInfo(aWRManager)
 {
 }
 
+WebRenderCanvasData::WebRenderCanvasData(WebRenderLayerManager* aWRManager)
+  : WebRenderUserData(aWRManager)
+{
+}
+
+WebRenderCanvasData::~WebRenderCanvasData()
+{
+}
+
+WebRenderCanvasRendererAsync*
+WebRenderCanvasData::GetCanvasRenderer()
+{
+  if (!mCanvasRenderer) {
+    mCanvasRenderer = MakeUnique<WebRenderCanvasRendererAsync>(mWRManager);
+  }
+
+  return mCanvasRenderer.get();
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/wr/WebRenderUserData.h
+++ b/gfx/layers/wr/WebRenderUserData.h
@@ -9,49 +9,52 @@
 #include "mozilla/layers/StackingContextHelper.h"
 #include "mozilla/webrender/WebRenderAPI.h"
 #include "mozilla/layers/AnimationInfo.h"
 
 class nsDisplayItemGeometry;
 
 namespace mozilla {
 namespace layers {
+class CanvasLayer;
 class ImageClient;
 class ImageContainer;
 class WebRenderBridgeChild;
+class WebRenderCanvasData;
+class WebRenderCanvasRendererAsync;
 class WebRenderImageData;
 class WebRenderFallbackData;
 class WebRenderLayerManager;
 
 class WebRenderUserData
 {
 public:
   NS_INLINE_DECL_REFCOUNTING(WebRenderUserData)
 
-  explicit WebRenderUserData(WebRenderLayerManager* aWRManager)
-    : mWRManager(aWRManager)
-  { }
+  explicit WebRenderUserData(WebRenderLayerManager* aWRManager);
 
   virtual WebRenderImageData* AsImageData() { return nullptr; }
   virtual WebRenderFallbackData* AsFallbackData() { return nullptr; }
+  virtual WebRenderCanvasData* AsCanvasData() { return nullptr; }
 
   enum class UserDataType {
     eImage,
     eFallback,
     eAnimation,
+    eCanvas,
   };
 
   virtual UserDataType GetType() = 0;
 
 protected:
-  virtual ~WebRenderUserData() {}
+  virtual ~WebRenderUserData();
 
   WebRenderBridgeChild* WrBridge() const;
 
-  WebRenderLayerManager* mWRManager;
+  RefPtr<WebRenderLayerManager> mWRManager;
 };
 
 class WebRenderImageData : public WebRenderUserData
 {
 public:
   explicit WebRenderImageData(WebRenderLayerManager* aWRManager);
   virtual ~WebRenderImageData();
 
@@ -117,12 +120,28 @@ public:
   virtual UserDataType GetType() override { return UserDataType::eAnimation; }
   static UserDataType Type() { return UserDataType::eAnimation; }
   AnimationInfo& GetAnimationInfo() { return mAnimationInfo; }
 
 protected:
   AnimationInfo mAnimationInfo;
 };
 
+class WebRenderCanvasData : public WebRenderUserData
+{
+public:
+  explicit WebRenderCanvasData(WebRenderLayerManager* aWRManager);
+  virtual ~WebRenderCanvasData();
+
+  virtual WebRenderCanvasData* AsCanvasData() override { return this; }
+  virtual UserDataType GetType() override { return UserDataType::eCanvas; }
+  static UserDataType Type() { return UserDataType::eCanvas; }
+
+  WebRenderCanvasRendererAsync* GetCanvasRenderer();
+
+protected:
+  UniquePtr<WebRenderCanvasRendererAsync> mCanvasRenderer;
+};
+
 } // namespace layers
 } // namespace mozilla
 
 #endif /* GFX_WEBRENDERUSERDATA_H */
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -712,16 +712,17 @@ private:
                 WebGLDisableFailIfMajorPerformanceCaveat, bool, false);
   DECL_GFX_PREF(Live, "webgl.disable-DOM-blit-uploads",
                 WebGLDisableDOMBlitUploads, bool, false);
 
   DECL_GFX_PREF(Live, "webgl.disabled",                        WebGLDisabled, bool, false);
 
   DECL_GFX_PREF(Live, "webgl.enable-draft-extensions",         WebGLDraftExtensionsEnabled, bool, false);
   DECL_GFX_PREF(Live, "webgl.enable-privileged-extensions",    WebGLPrivilegedExtensionsEnabled, bool, false);
+  DECL_GFX_PREF(Live, "webgl.enable-surface-texture",          WebGLSurfaceTextureEnabled, bool, false);
   DECL_GFX_PREF(Live, "webgl.enable-webgl2",                   WebGL2Enabled, bool, true);
   DECL_GFX_PREF(Live, "webgl.force-enabled",                   WebGLForceEnabled, bool, false);
   DECL_GFX_PREF(Once, "webgl.force-layers-readback",           WebGLForceLayersReadback, bool, false);
   DECL_GFX_PREF(Live, "webgl.force-index-validation",          WebGLForceIndexValidation, bool, false);
   DECL_GFX_PREF(Live, "webgl.lose-context-on-memory-pressure", WebGLLoseContextOnMemoryPressure, bool, false);
   DECL_GFX_PREF(Live, "webgl.max-warnings-per-context",        WebGLMaxWarningsPerContext, uint32_t, 32);
   DECL_GFX_PREF(Live, "webgl.min_capability_mode",             WebGLMinCapabilityMode, bool, false);
   DECL_GFX_PREF(Live, "webgl.msaa-force",                      WebGLForceMSAA, bool, false);
@@ -729,16 +730,17 @@ private:
   DECL_GFX_PREF(Live, "webgl.restore-context-when-visible",    WebGLRestoreWhenVisible, bool, true);
   DECL_GFX_PREF(Live, "webgl.allow-immediate-queries",         WebGLImmediateQueries, bool, false);
   DECL_GFX_PREF(Live, "webgl.allow-fb-invalidation",           WebGLFBInvalidation, bool, false);
 
   DECL_GFX_PREF(Live, "webgl.perf.max-warnings",                    WebGLMaxPerfWarnings, int32_t, 0);
   DECL_GFX_PREF(Live, "webgl.perf.max-acceptable-fb-status-invals", WebGLMaxAcceptableFBStatusInvals, int32_t, 0);
   DECL_GFX_PREF(Live, "webgl.perf.spew-frame-allocs",          WebGLSpewFrameAllocs, bool, true);
 
+
   DECL_GFX_PREF(Live, "webgl.webgl2-compat-mode",              WebGL2CompatMode, bool, false);
 
   DECL_GFX_PREF(Live, "widget.window-transforms.disabled",     WindowTransformsDisabled, bool, false);
 
   // WARNING:
   // Please make sure that you've added your new preference to the list above in alphabetical order.
   // Please do not just append it to the end of the list.
 
--- a/ipc/mscom/Interceptor.cpp
+++ b/ipc/mscom/Interceptor.cpp
@@ -301,25 +301,28 @@ Interceptor::MarshalInterface(IStream* p
      * in a single-threaded apartment. Since our chrome main thread does live
      * inside an STA, we will therefore be able to check whether the caller TID
      * equals our chrome main thread TID. This enables us to distinguish
      * between our chrome thread vs other out-of-process callers.
      */
     DWORD callerTid;
     if (::CoGetCallerTID(&callerTid) == S_FALSE && callerTid != chromeMainTid) {
       // The caller isn't our chrome process, so do not provide a handler.
-      // First, seek back to the stream position that we prevously saved.
-      seekTo.QuadPart = objrefPos.QuadPart;
-      hr = pStm->Seek(seekTo, STREAM_SEEK_SET, nullptr);
+
+      // First, save the current position that marks the current end of the
+      // OBJREF in the stream.
+      ULARGE_INTEGER endPos;
+      hr = pStm->Seek(seekTo, STREAM_SEEK_CUR, &endPos);
       if (FAILED(hr)) {
         return hr;
       }
 
       // Now strip out the handler.
-      if (!StripHandlerFromOBJREF(WrapNotNull(pStm))) {
+      if (!StripHandlerFromOBJREF(WrapNotNull(pStm), objrefPos.QuadPart,
+                                  endPos.QuadPart)) {
         return E_FAIL;
       }
 
       return S_OK;
     }
   }
 #endif // defined(MOZ_MSCOM_REMARSHAL_NO_HANDLER)
 
--- a/ipc/mscom/Objref.cpp
+++ b/ipc/mscom/Objref.cpp
@@ -135,44 +135,47 @@ template <typename T>
 using VarStructUniquePtr = mozilla::UniquePtr<T, ByteArrayDeleter>;
 
 } // anonymous namespace
 
 namespace mozilla {
 namespace mscom {
 
 bool
-StripHandlerFromOBJREF(NotNull<IStream*> aStream)
+StripHandlerFromOBJREF(NotNull<IStream*> aStream, const uint64_t aStartPos,
+                       const uint64_t aEndPos)
 {
-  // Get current stream position
+  // Ensure that the current stream position is set to the beginning
   LARGE_INTEGER seekTo;
-  seekTo.QuadPart = 0;
+  seekTo.QuadPart = aStartPos;
 
-  ULARGE_INTEGER objrefPos;
-
-  HRESULT hr = aStream->Seek(seekTo, STREAM_SEEK_CUR, &objrefPos);
+  HRESULT hr = aStream->Seek(seekTo, STREAM_SEEK_SET, nullptr);
   if (FAILED(hr)) {
     return false;
   }
 
   ULONG bytesRead;
 
   uint32_t signature;
   hr = aStream->Read(&signature, sizeof(signature), &bytesRead);
   if (FAILED(hr) || bytesRead != sizeof(signature) ||
       signature != OBJREF_SIGNATURE) {
     return false;
   }
 
   uint32_t type;
   hr = aStream->Read(&type, sizeof(type), &bytesRead);
-  if (FAILED(hr) || bytesRead != sizeof(type) ||
-      type != OBJREF_TYPE_HANDLER) {
-    // If we're not a handler then just return success
-    return true;
+  if (FAILED(hr) || bytesRead != sizeof(type)) {
+    return false;
+  }
+  if (type != OBJREF_TYPE_HANDLER) {
+    // If we're not a handler then just seek to the end of the OBJREF and return
+    // success; there is nothing left to do.
+    seekTo.QuadPart = aEndPos;
+    return SUCCEEDED(aStream->Seek(seekTo, STREAM_SEEK_SET, nullptr));
   }
 
   IID iid;
   hr = aStream->Read(&iid, sizeof(iid), &bytesRead);
   if (FAILED(hr) || bytesRead != sizeof(iid) || !IsValidGUID(iid)) {
     return false;
   }
 
@@ -212,17 +215,17 @@ StripHandlerFromOBJREF(NotNull<IStream*>
   ULONG bytesToRead = resAddrSize - sizeof(numEntries);
 
   hr = aStream->Read(&resAddr->mSecurityOffset, bytesToRead, &bytesRead);
   if (FAILED(hr) || bytesRead != bytesToRead) {
     return false;
   }
 
   // Signature doesn't change so we'll seek past that
-  seekTo.QuadPart = objrefPos.QuadPart + sizeof(signature);
+  seekTo.QuadPart = aStartPos + sizeof(signature);
   hr = aStream->Seek(seekTo, STREAM_SEEK_SET, nullptr);
   if (FAILED(hr)) {
     return false;
   }
 
   ULONG bytesWritten;
 
   uint32_t newType = OBJREF_TYPE_STANDARD;
@@ -246,13 +249,15 @@ StripHandlerFromOBJREF(NotNull<IStream*>
   // The difference between a OBJREF_STANDARD and an OBJREF_HANDLER is
   // sizeof(CLSID), so we'll zero out the remaining bytes.
   CLSID zeroClsid = {0};
   hr = aStream->Write(&zeroClsid, sizeof(CLSID), &bytesWritten);
   if (FAILED(hr) || bytesWritten != sizeof(CLSID)) {
     return false;
   }
 
-  return true;
+  // Back up to just before the zeros we just wrote
+  seekTo.QuadPart = -static_cast<int64_t>(sizeof(CLSID));
+  return SUCCEEDED(aStream->Seek(seekTo, STREAM_SEEK_CUR, nullptr));
 }
 
 } // namespace mscom
 } // namespace mozilla
--- a/ipc/mscom/Objref.h
+++ b/ipc/mscom/Objref.h
@@ -12,21 +12,25 @@
 struct IStream;
 
 namespace mozilla {
 namespace mscom {
 
 /**
  * Given a buffer containing a serialized proxy to an interface with a handler,
  * this function strips out the handler and converts it to a standard one.
- * @param aStream IStream whose pointer is positioned at the beginning of the
- *                OBJREF to be stripped. There should be nothing else written
- *                to the stream past the current OBJREF.
+ * @param aStream IStream containing a serialized proxy.
+ *                There should be nothing else written to the stream past the
+ *                current OBJREF.
+ * @param aStart  Absolute position of the beginning of the OBJREF.
+ * @param aEnd    Absolute position of the end of the OBJREF.
  * @return true if the handler was successfully stripped, otherwise false.
  */
 bool
-StripHandlerFromOBJREF(NotNull<IStream*> aStream);
+StripHandlerFromOBJREF(NotNull<IStream*> aStream,
+                       const uint64_t aStart,
+                       const uint64_t aEnd);
 
 } // namespace mscom
 } // namespace mozilla
 
 #endif // mozilla_mscom_Objref_h
 
--- a/ipc/mscom/oop/Handler.cpp
+++ b/ipc/mscom/oop/Handler.cpp
@@ -201,26 +201,26 @@ Handler::MarshalInterface(IStream* pStm,
 
   hr = mUnmarshal->MarshalInterface(pStm, marshalAs, unkToMarshal.get(),
                                     dwDestContext, pvDestContext, mshlflags);
   if (FAILED(hr)) {
     return hr;
   }
 
 #if defined(MOZ_MSCOM_REMARSHAL_NO_HANDLER)
-  // Now the OBJREF has been written, so seek back to its beginning (the
-  // position that we saved earlier).
-  seekTo.QuadPart = objrefPos.QuadPart;
-  hr = pStm->Seek(seekTo, STREAM_SEEK_SET, nullptr);
+  // Obtain the current stream position which is the end of the OBJREF
+  ULARGE_INTEGER endPos;
+  hr = pStm->Seek(seekTo, STREAM_SEEK_CUR, &endPos);
   if (FAILED(hr)) {
     return hr;
   }
 
   // Now strip out the handler.
-  if (!StripHandlerFromOBJREF(WrapNotNull(pStm))) {
+  if (!StripHandlerFromOBJREF(WrapNotNull(pStm), objrefPos.QuadPart,
+                              endPos.QuadPart)) {
     return E_FAIL;
   }
 
   return S_OK;
 #else
   if (!HasPayload()) {
     return S_OK;
   }
--- a/js/xpconnect/loader/ScriptPreloader.h
+++ b/js/xpconnect/loader/ScriptPreloader.h
@@ -140,17 +140,17 @@ private:
     // non-null mScript value. If it was read from the last session's cache
     // file, it also has a non-empty mXDRRange range, which will be stored in
     // the next session's cache file. If it was compiled in this session, its
     // mXDRRange will initially be empty, and its mXDRData buffer will be
     // populated just before it is written to the cache file.
     class CachedScript : public LinkedListElement<CachedScript>
     {
     public:
-        CachedScript(CachedScript&&) = default;
+        CachedScript(CachedScript&&) = delete;
 
         CachedScript(ScriptPreloader& cache, const nsCString& url, const nsCString& cachePath, JSScript* script)
             : mCache(cache)
             , mURL(url)
             , mCachePath(cachePath)
             , mScript(script)
             , mReadyToExecute(true)
         {}
--- a/js/xpconnect/tests/chrome/test_windowProxyDeadWrapper.html
+++ b/js/xpconnect/tests/chrome/test_windowProxyDeadWrapper.html
@@ -50,24 +50,20 @@ function go() {
         frame.remove();
 
         TestUtils.topicObserved("outer-window-nuked", (subject, data) => {
             let id = subject.QueryInterface(SpecialPowers.Ci.nsISupportsPRUint64).data;
             return id == winID;
         }).then(() => {
             ok(checkDead(), "Expected a dead object wrapper");
 
-            // Wrapping the Window should throw now.
-            var exc;
-            try {
-                Components.utils.getGlobalForObject(getObject());
-            } catch(e) {
-                exc = e;
-            }
-            is(exc.message, "Can't wrap dead object");
+            // Wrapping the Window should return a dead wrapper now.
+            var global = Components.utils.getGlobalForObject(getObject());
+            ok(Components.utils.isDeadWrapper(global),
+               "Expected a dead wrapper when requesting the window's global");
 
             SimpleTest.finish();
         });
     }
 }
 
   </script>
 </head>
--- a/js/xpconnect/tests/unit/xpcshell.ini
+++ b/js/xpconnect/tests/unit/xpcshell.ini
@@ -80,17 +80,16 @@ head = head_ongc.js
 [test_onGarbageCollection-03.js]
 head = head_ongc.js
 [test_onGarbageCollection-04.js]
 head = head_ongc.js
 [test_onGarbageCollection-05.js]
 head = head_ongc.js
 [test_reflect_parse.js]
 [test_localeCompare.js]
-skip-if = toolkit == "android" # bug 1347431
 [test_recursive_import.js]
 [test_xpcomutils.js]
 [test_unload.js]
 [test_attributes.js]
 [test_params.js]
 [test_tearoffs.js]
 [test_want_components.js]
 [test_components.js]
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -159,24 +159,23 @@ WrapperFactory::PrepareForWrapping(JSCon
                                    MutableHandleObject retObj)
 {
     bool waive = ShouldWaiveXray(cx, objectPassedToWrap);
     RootedObject obj(cx, objArg);
     retObj.set(nullptr);
     // Outerize any raw inner objects at the entry point here, so that we don't
     // have to worry about them for the rest of the wrapping code.
     if (js::IsWindow(obj)) {
-        JSAutoCompartment ac(cx, obj);
         obj = js::ToWindowProxyIfWindow(obj);
         MOZ_ASSERT(obj);
         // ToWindowProxyIfWindow can return a CCW if |obj| was a
         // navigated-away-from Window. Strip any CCWs.
         obj = js::UncheckedUnwrap(obj);
         if (JS_IsDeadWrapper(obj)) {
-            JS_ReportErrorASCII(cx, "Can't wrap dead object");
+            retObj.set(JS_NewDeadWrapper(cx, obj));
             return;
         }
         MOZ_ASSERT(js::IsWindowProxy(obj));
         // We crossed a compartment boundary there, so may now have a gray
         // object.  This function is not allowed to return gray objects, so
         // don't do that.
         ExposeObjectToActiveJS(obj);
     }
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -5,16 +5,20 @@
 
 /* rendering object for the HTML <canvas> element */
 
 #include "nsHTMLCanvasFrame.h"
 
 #include "nsGkAtoms.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
+#include "mozilla/layers/WebRenderBridgeChild.h"
+#include "mozilla/layers/WebRenderCanvasRenderer.h"
+#include "mozilla/layers/WebRenderLayer.h"
+#include "mozilla/layers/WebRenderLayerManager.h"
 #include "nsDisplayList.h"
 #include "nsLayoutUtils.h"
 #include "nsStyleUtil.h"
 #include "ImageLayers.h"
 #include "Layers.h"
 #include "ActiveLayerTracker.h"
 
 #include <algorithm>
@@ -112,16 +116,96 @@ public:
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override
   {
     return static_cast<nsHTMLCanvasFrame*>(mFrame)->
       BuildLayer(aBuilder, aManager, this, aContainerParameters);
   }
+
+  virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       const StackingContextHelper& aSc,
+                                       nsTArray<WebRenderParentCommand>& aParentCommands,
+                                       mozilla::layers::WebRenderLayerManager* aManager,
+                                       nsDisplayListBuilder* aDisplayListBuilder) override
+  {
+    HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(mFrame->GetContent());
+    switch(element->GetCurrentContextType()) {
+      case CanvasContextType::Canvas2D:
+      case CanvasContextType::WebGL1:
+      case CanvasContextType::WebGL2:
+      {
+        bool isRecycled;
+        RefPtr<WebRenderCanvasData> canvasData =
+          aManager->CreateOrRecycleWebRenderUserData<WebRenderCanvasData>(this, &isRecycled);
+        WebRenderCanvasRendererAsync* data =
+          static_cast<WebRenderCanvasRendererAsync*>(canvasData->GetCanvasRenderer());
+
+        if (isRecycled) {
+          static_cast<nsHTMLCanvasFrame*>(mFrame)->InitializeCanvasRenderer(aDisplayListBuilder, data);
+        }
+
+        data->UpdateCompositableClient();
+
+        // Push IFrame for async image pipeline.
+        // XXX Remove this once partial display list update is supported.
+
+        /* ScrollingLayersHelper scroller(this, aBuilder, aSc); */
+        nsIntSize canvasSizeInPx = data->GetSize();
+        IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSizeInPx);
+        nsSize intrinsicRatio = IntrinsicRatioFromCanvasSize(canvasSizeInPx);
+
+        nsRect area = mFrame->GetContentRectRelativeToSelf() + ToReferenceFrame();
+        nsRect dest =
+          nsLayoutUtils::ComputeObjectDestRect(area, intrinsicSize, intrinsicRatio,
+                                               mFrame->StylePosition());
+
+        LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
+          dest, mFrame->PresContext()->AppUnitsPerDevPixel());
+
+        // We don't push a stacking context for this async image pipeline here.
+        // Instead, we do it inside the iframe that hosts the image. As a result,
+        // a bunch of the calculations normally done as part of that stacking
+        // context need to be done manually and pushed over to the parent side,
+        // where it will be done when we build the display list for the iframe.
+        // That happens in WebRenderCompositableHolder.
+
+        wr::LayoutRect r = aSc.ToRelativeLayoutRect(bounds);
+        aBuilder.PushIFrame(r, data->GetPipelineId().ref());
+
+        gfx::Matrix4x4 scTransform;
+        if (data->NeedsYFlip()) {
+          scTransform = scTransform.PreTranslate(0, data->GetSize().height, 0).PreScale(1, -1, 1);
+        }
+
+        MaybeIntSize scaleToSize;
+        LayerRect scBounds(0, 0, bounds.width, bounds.height);
+        wr::ImageRendering filter = wr::ToImageRendering(nsLayoutUtils::GetSamplingFilterForFrame(mFrame));
+        wr::MixBlendMode mixBlendMode = wr::MixBlendMode::Normal;
+
+        aManager->WrBridge()->AddWebRenderParentCommand(OpUpdateAsyncImagePipeline(data->GetPipelineId().value(),
+                                                                                   scBounds,
+                                                                                   scTransform,
+                                                                                   scaleToSize,
+                                                                                   filter,
+                                                                                   mixBlendMode));
+        break;
+      }
+      case CanvasContextType::ImageBitmap:
+      {
+        // TODO: Support ImageBitmap
+        break;
+      }
+      case CanvasContextType::NoContext:
+        return false;
+    }
+    return true;
+  }
+
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override
   {
     if (HTMLCanvasElement::FromContent(mFrame->GetContent())->ShouldForceInactiveLayer(aManager))
       return LAYER_INACTIVE;
 
     // If compositing is cheap, just do that
@@ -352,25 +436,36 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayL
   gfxPoint p = destGFXRect.TopLeft() + aContainerParameters.mOffset;
   Matrix transform = Matrix::Translation(p.x, p.y);
   transform.PreScale(destGFXRect.Width() / canvasSizeInPx.width,
                      destGFXRect.Height() / canvasSizeInPx.height);
   layer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
   if (layer->GetType() == layers::Layer::TYPE_CANVAS) {
     RefPtr<CanvasLayer> canvasLayer = static_cast<CanvasLayer*>(layer.get());
     canvasLayer->SetSamplingFilter(nsLayoutUtils::GetSamplingFilterForFrame(this));
+    nsIntRect bounds;
+    bounds.SetRect(0, 0, canvasSizeInPx.width, canvasSizeInPx.height);
+    canvasLayer->SetBounds(bounds);
   } else if (layer->GetType() == layers::Layer::TYPE_IMAGE) {
     RefPtr<ImageLayer> imageLayer = static_cast<ImageLayer*>(layer.get());
     imageLayer->SetSamplingFilter(nsLayoutUtils::GetSamplingFilterForFrame(this));
   }
 
   return layer.forget();
 }
 
 void
+nsHTMLCanvasFrame::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+                                            CanvasRenderer* aRenderer)
+{
+  HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(GetContent());
+  element->InitializeCanvasRenderer(aBuilder, aRenderer);
+}
+
+void
 nsHTMLCanvasFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                     const nsRect&           aDirtyRect,
                                     const nsDisplayListSet& aLists)
 {
   if (!IsVisibleForPainting(aBuilder))
     return;
 
   DisplayBorderBackgroundOutline(aBuilder, aLists);
--- a/layout/generic/nsHTMLCanvasFrame.h
+++ b/layout/generic/nsHTMLCanvasFrame.h
@@ -23,16 +23,17 @@ class nsPresContext;
 class nsDisplayItem;
 class nsAString;
 
 nsIFrame* NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
 
 class nsHTMLCanvasFrame final : public nsContainerFrame
 {
 public:
+  typedef mozilla::layers::CanvasRenderer CanvasRenderer;
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayerManager LayerManager;
   typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
 
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS(nsHTMLCanvasFrame)
 
   explicit nsHTMLCanvasFrame(nsStyleContext* aContext)
@@ -47,16 +48,18 @@ public:
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) override;
 
   already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                      LayerManager* aManager,
                                      nsDisplayItem* aItem,
                                      const ContainerLayerParameters& aContainerParameters);
+  void InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+                                CanvasRenderer* aRenderer);
 
   /* get the size of the canvas's image */
   nsIntSize GetCanvasSize();
 
   virtual nscoord GetMinISize(gfxContext *aRenderingContext) override;
   virtual nscoord GetPrefISize(gfxContext *aRenderingContext) override;
   virtual mozilla::IntrinsicSize GetIntrinsicSize() override;
   virtual nsSize GetIntrinsicRatio() override;
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -2118,16 +2118,20 @@ already_AddRefed<LayerManager> nsDisplay
         // SVG-as-an-image docs don't paint as part of the retained layer tree,
         // but they still need the invalidation state bits cleared in order for
         // invalidation for CSS/SMIL animation to work properly.
         (document && document->IsBeingUsedAsImage())) {
       frame->ClearInvalidationStateBits();
     }
 
     aBuilder->SetIsCompositingCheap(temp);
+    if (document && widgetTransaction) {
+      TriggerPendingAnimations(document, layerManager->GetAnimationReadyTime());
+    }
+
     return layerManager.forget();
   }
 
   NotifySubDocInvalidationFunc computeInvalidFunc =
     presContext->MayHavePaintEventListenerInSubDocument() ? nsPresContext::NotifySubDocInvalidation : 0;
 
   UniquePtr<LayerProperties> props;
   RefPtr<ContainerLayer> root;
@@ -6187,16 +6191,39 @@ nsRegion nsDisplayBlendMode::GetOpaqueRe
 LayerState
 nsDisplayBlendMode::GetLayerState(nsDisplayListBuilder* aBuilder,
                                      LayerManager* aManager,
                                      const ContainerLayerParameters& aParameters)
 {
   return LAYER_ACTIVE;
 }
 
+bool
+nsDisplayBlendMode::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                            const StackingContextHelper& aSc,
+                                            nsTArray<WebRenderParentCommand>& aParentCommands,
+                                            mozilla::layers::WebRenderLayerManager* aManager,
+                                            nsDisplayListBuilder* aDisplayListBuilder)
+{
+  nsRect itemBounds = mList.GetClippedBoundsWithRespectToASR(aDisplayListBuilder, mActiveScrolledRoot);
+  nsRect childrenVisible = GetVisibleRectForChildren();
+  nsRect visibleRect = itemBounds.Intersect(childrenVisible);
+  float appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
+  LayerRect bounds = ViewAs<LayerPixel>(LayoutDeviceRect::FromAppUnits(visibleRect, appUnitsPerDevPixel),
+                                        PixelCastJustification::WebRenderHasUnitResolution);
+  LayerPoint origin = bounds.TopLeft();
+
+  nsTArray<mozilla::wr::WrFilterOp> filters;
+  StackingContextHelper sc(aSc, aBuilder, bounds, origin, 0, nullptr, nullptr,
+                           filters, nsCSSRendering::GetGFXBlendMode(mBlendMode));
+
+  return nsDisplayWrapList::CreateWebRenderCommands(aBuilder, sc, aParentCommands,
+                                                    aManager, aDisplayListBuilder);
+}
+
 // nsDisplayBlendMode uses layers for rendering
 already_AddRefed<Layer>
 nsDisplayBlendMode::BuildLayer(nsDisplayListBuilder* aBuilder,
                                   LayerManager* aManager,
                                   const ContainerLayerParameters& aContainerParameters) {
   ContainerLayerParameters newContainerParameters = aContainerParameters;
   newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true;
 
@@ -6297,16 +6324,37 @@ nsDisplayBlendContainer::BuildLayer(nsDi
 LayerState
 nsDisplayBlendContainer::GetLayerState(nsDisplayListBuilder* aBuilder,
                                        LayerManager* aManager,
                                        const ContainerLayerParameters& aParameters)
 {
   return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, GetAnimatedGeometryRoot());
 }
 
+bool
+nsDisplayBlendContainer::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                                 const StackingContextHelper& aSc,
+                                                 nsTArray<WebRenderParentCommand>& aParentCommands,
+                                                 mozilla::layers::WebRenderLayerManager* aManager,
+                                                 nsDisplayListBuilder* aDisplayListBuilder)
+{
+  nsRect itemBounds = mList.GetClippedBoundsWithRespectToASR(aDisplayListBuilder, mActiveScrolledRoot);
+  nsRect childrenVisible = GetVisibleRectForChildren();
+  nsRect visibleRect = itemBounds.Intersect(childrenVisible);
+  float appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
+  LayerRect bounds = ViewAs<LayerPixel>(LayoutDeviceRect::FromAppUnits(visibleRect, appUnitsPerDevPixel),
+                                        PixelCastJustification::WebRenderHasUnitResolution);
+  LayerPoint origin = bounds.TopLeft();
+
+  StackingContextHelper sc(aSc, aBuilder, bounds, origin, 0, nullptr, nullptr);
+
+  return nsDisplayWrapList::CreateWebRenderCommands(aBuilder, sc, aParentCommands,
+                                                    aManager, aDisplayListBuilder);
+}
+
 bool nsDisplayBlendContainer::TryMerge(nsDisplayItem* aItem) {
   if (aItem->GetType() != TYPE_BLEND_CONTAINER)
     return false;
   // items for the same content element should be merged into a single
   // compositing group
   // aItem->GetUnderlyingFrame() returns non-null because it's nsDisplayOpacity
   if (aItem->Frame()->GetContent() != mFrame->GetContent())
     return false;
@@ -7541,29 +7589,29 @@ nsDisplayTransform::ShouldPrerenderTrans
         AnimationPerformanceWarning::Type::TransformFrameInactive));
 
     return NoPrerender;
   }
 
   // We should not allow prerender if any ancestor container element has
   // mask/clip-path effects.
   //
-  // With prerender and sync transform animation, we do not need to restyle an
+  // With prerender and async transform animation, we do not need to restyle an
   // animated element to respect position changes, since that transform is done
   // by layer animation. As a result, the container element is not aware of
   // position change of that containing element and loses the chance to update
   // the content of mask/clip-path.
   //
   // Why do we need to update a mask? This is relative to how we generate a
   // mask layer in ContainerState::SetupMaskLayerForCSSMask. While creating a
   // mask layer, to reduce memory usage, we did not choose the size of the
   // masked element as mask size. Instead, we read the union of bounds of all
   // children display items by nsDisplayWrapList::GetBounds, which is smaller
   // than or equal to the masked element's boundary, and use it as the position
-  ///size of the mask layer. That union bounds is actually affected by the
+  // size of the mask layer. That union bounds is actually affected by the
   // geometry of the animated element. To keep the content of mask up to date,
   // forbidding of prerender is required.
   for (nsIFrame* container = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
        container; container = nsLayoutUtils::GetCrossDocParentFrame(container)) {
     const nsStyleSVGReset *svgReset = container->StyleSVGReset();
     if (svgReset->HasMask() || svgReset->HasClipPath()) {
       return NoPrerender;
     }
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -4045,16 +4045,21 @@ public:
   }
   virtual uint32_t GetPerFrameKey() override {
     return (mIndex << nsDisplayItem::TYPE_BITS) |
       nsDisplayItem::GetPerFrameKey();
   }
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
+  bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                               const StackingContextHelper& aSc,
+                               nsTArray<WebRenderParentCommand>& aParentCommands,
+                               mozilla::layers::WebRenderLayerManager* aManager,
+                               nsDisplayListBuilder* aDisplayListBuilder) override;
   virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                  nsRegion* aVisibleRegion) override;
   virtual bool TryMerge(nsDisplayItem* aItem) override;
   virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
     return false;
   }
   NS_DISPLAY_DECL_NAME("BlendMode", TYPE_BLEND_MODE)
 
@@ -4080,16 +4085,21 @@ public:
 #endif
 
     virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                                LayerManager* aManager,
                                                const ContainerLayerParameters& aContainerParameters) override;
     virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                      LayerManager* aManager,
                                      const ContainerLayerParameters& aParameters) override;
+    bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                 const StackingContextHelper& aSc,
+                                 nsTArray<WebRenderParentCommand>& aParentCommands,
+                                 mozilla::layers::WebRenderLayerManager* aManager,
+                                 nsDisplayListBuilder* aDisplayListBuilder) override;
     virtual bool TryMerge(nsDisplayItem* aItem) override;
     virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
       return false;
     }
     virtual uint32_t GetPerFrameKey() override {
       return (mIsForBackground ? 1 << nsDisplayItem::TYPE_BITS : 0) |
         nsDisplayItem::GetPerFrameKey();
     }
--- a/python/mozbuild/mozbuild/codecoverage/lcov_rewriter.py
+++ b/python/mozbuild/mozbuild/codecoverage/lcov_rewriter.py
@@ -78,20 +78,20 @@ class LcovRecord(object):
 class RecordRewriter(object):
     # Helper class for rewriting/spliting individual lcov records according
     # to what the preprocessor did.
     def __init__(self):
         self.pp_info = {}
         self._ranges = None
         self._line_comment_re = re.compile('^//@line (\d+) "(.+)"$')
 
+    def has_pp_info(self, src_path):
+        return src_path in self.pp_info
+
     def populate_pp_info(self, fh, src_path):
-        if src_path in self.pp_info:
-            return
-
         # (start, end) -> (included_source, start)
         section_info = dict()
 
         this_section = None
 
         def finish_section(pp_end):
             pp_start, inc_source, inc_start = this_section
             section_info[(pp_start, pp_end)] = inc_source, inc_start
@@ -241,46 +241,55 @@ class LcovFile(object):
       'BRF': 0,
       'BRH': 0,
       'DA': 2,
       'LH': 0,
       'LF': 0,
     }
 
     def __init__(self, lcov_fh):
-        # These are keyed by source file because output will split sources (at
-        # least for xbl).
-        self._records = defaultdict(lambda: LcovRecord())
-        self.new_record()
-        self.parse_file(lcov_fh)
-
-    @property
-    def records(self):
-        return self._records.values()
+        self.lcov_fh = lcov_fh
 
-    @records.setter
-    def records(self, value):
-        self._records = {r.source_file: r for r in value}
-
-    def new_record(self):
-        rec = LcovRecord()
-        self.current_record = rec
-
-    def finish_record(self):
-        self._records[self.current_record.source_file] += self.current_record
-        self.new_record()
-
-    def parse_file(self, lcov_fh):
-        for count, line in enumerate(lcov_fh):
+    def iterate_records(self, rewrite_source=None):
+        current_source_file = None
+        current_preprocessed = False
+        current_lines = []
+        for line in self.lcov_fh:
             line = line.rstrip()
             if not line:
                 continue
+
             if line == 'end_of_record':
-                self.finish_record()
+                # We skip records that we couldn't rewrite, that is records for which
+                # rewrite_url returns None.
+                if current_source_file != None:
+                    yield (current_source_file, current_preprocessed, current_lines)
+                current_source_file = None
+                current_preprocessed = False
+                current_lines = []
                 continue
+
+            colon = line.find(':')
+            prefix = line[:colon]
+
+            if prefix == 'SF':
+                sf = line[(colon + 1):]
+                res = rewrite_source(sf) if rewrite_source is not None else (sf, False)
+                if res is None:
+                    current_lines.append(line)
+                else:
+                    current_source_file, current_preprocessed = res
+                    current_lines.append('SF:' + current_source_file)
+            else:
+                current_lines.append(line)
+
+    def parse_record(self, record_content):
+        self.current_record = LcovRecord()
+
+        for line in record_content:
             colon = line.find(':')
 
             prefix = line[:colon]
 
             # We occasionally end up with multi-line scripts in data:
             # uris that will trip up the parser, just skip them for now.
             if colon < 0 or prefix not in self.PREFIX_TYPES:
                 continue
@@ -292,39 +301,48 @@ class LcovFile(object):
                     return int(a)
                 except ValueError:
                     return a
             args = [try_convert(a) for a in args]
 
             try:
                 LcovFile.__dict__['parse_' + prefix](self, *args)
             except ValueError:
-                print("Encountered an error at line %d:\n%s" %
-                      (count + 1, line))
+                print("Encountered an error in %s:\n%s" %
+                      (self.lcov_fh.name, line))
                 raise
             except KeyError:
-                print("Invalid lcov line start at %s:%d:\n%s" %
-                      (lcov_fh.name, count + 1, line))
+                print("Invalid lcov line start in %s:\n%s" %
+                      (self.lcov_fh.name, line))
                 raise
             except TypeError:
-                print("Invalid lcov line start at %s:%d:\n%s" %
-                      (lcov_fh.name, count + 1, line))
+                print("Invalid lcov line start in %s:\n%s" %
+                      (self.lcov_fh.name, line))
                 raise
 
-    def print_file(self, fh):
-        for record in self.records:
-            fh.write(self.format_record(record))
-            fh.write('\n')
+        ret = self.current_record
+        self.current_record = LcovRecord()
+        return ret
+
+    def print_file(self, fh, rewrite_source, rewrite_record):
+        for source_file, preprocessed, record_content in self.iterate_records(rewrite_source):
+            if preprocessed:
+                record = self.parse_record(record_content)
+                for r in rewrite_record(record):
+                    fh.write(self.format_record(r))
+                fh.write(self.format_record(record))
+            else:
+                fh.write('\n'.join(record_content) + '\nend_of_record\n')
 
     def format_record(self, record):
         out_lines = []
         for name in LcovRecord.__slots__:
             if hasattr(record, name):
                 out_lines.append(LcovFile.__dict__['format_' + name](self, record))
-        return '\n'.join(out_lines) + '\nend_of_record'
+        return '\n'.join(out_lines) + '\nend_of_record\n'
 
     def format_test_name(self, record):
         return "TN:%s" % record.test_name
 
     def format_source_file(self, record):
         return "SF:%s" % record.source_file
 
     def format_functions(self, record):
@@ -645,60 +663,50 @@ class LcovFileRewriter(object):
         self.topobjdir = buildconfig.topobjdir
         self.url_finder = UrlFinder(appdir, gredir, extra_chrome_manifests)
         self.pp_rewriter = RecordRewriter()
 
     def rewrite_file(self, in_path, output_suffix):
         in_path = os.path.abspath(in_path)
         out_path = in_path + output_suffix
 
-        with open(in_path) as fh:
-            lcov_file = LcovFile(fh)
+        unknowns = set()
+        found_valid = False
 
-        removals = set()
-        additions = []
-        unknowns = set()
-        pp = set()
-        for record in lcov_file.records:
-            url = record.source_file
+        def rewrite_source(url):
             try:
                 res = self.url_finder.rewrite_url(url)
                 if res is None:
-                    removals.add(record)
-                    continue
-
+                    return None
             except Exception as e:
                 if url not in unknowns:
                     print("Error: %s.\nCouldn't find source info for %s, removing record" %
                           (e, url))
-                removals.add(record)
                 unknowns.add(url)
-                continue
+                return None
+
             source_file, objdir_file, preprocessed = res
             assert os.path.isfile(source_file), "Couldn't find mapped source file at %s!" % source_file
-            record.source_file = source_file
-            if preprocessed:
-                pp.add(record)
+            if preprocessed and not self.pp_rewriter.has_pp_info(source_file):
                 obj_path = os.path.join(self.topobjdir, objdir_file)
                 with open(obj_path) as fh:
                     self.pp_rewriter.populate_pp_info(fh, source_file)
 
-        additions = []
-        for r in pp:
-            additions += self.pp_rewriter.rewrite_record(r)
+            found_valid = True
+
+            return source_file, preprocessed
 
-        lcov_file.records = [r for r in lcov_file.records + additions
-                             if r not in removals]
-        if not lcov_file.records:
+        with open(in_path) as fh, open(out_path, 'w+') as out_fh:
+            lcov_file = LcovFile(fh)
+            lcov_file.print_file(out_fh, rewrite_source, self.pp_rewriter.rewrite_record)
+
+        if not found_valid:
             print("WARNING: No valid records found in %s" % in_path)
             return
 
-        with open(out_path, 'w+') as out_fh:
-            lcov_file.print_file(out_fh)
-
 
 def main():
     parser = ArgumentParser(description="Given a set of gcov .info files produced "
                             "by spidermonkey's code coverage, re-maps file urls "
                             "back to source files and lines in preprocessed files "
                             "back to their original locations.")
     parser.add_argument("--app-dir", default="dist/bin/browser/",
                         help="Prefix of the appdir in use. This is used to map "
--- a/python/mozbuild/mozbuild/test/codecoverage/test_lcov_rewrite.py
+++ b/python/mozbuild/mozbuild/test/codecoverage/test_lcov_rewrite.py
@@ -100,41 +100,31 @@ end_of_record
 """
 
 class TestLcovParser(unittest.TestCase):
 
     def get_lcov(self, lcov_string):
         fh = StringIO(lcov_string)
         return lcov_rewriter.LcovFile(fh)
 
-    def parser_roundtrip(self, lcov_string, resummarize=False):
+    def parser_roundtrip(self, lcov_string):
         file_obj = self.get_lcov(lcov_string)
-        if resummarize:
-            for r in file_obj.records:
-                r.resummarize()
         out = StringIO()
-        file_obj.print_file(out)
+        file_obj.print_file(out, lambda s: (s, False), lambda x: x)
         return out.getvalue()
 
     def test_basic_parse(self):
         output = self.parser_roundtrip(basic_file)
         self.assertEqual(basic_file, output)
 
         output = self.parser_roundtrip(multiple_records)
         self.assertEqual(multiple_records, output)
 
-    def test_resummarize(self):
-        output = self.parser_roundtrip(basic_file, True)
-        self.assertEqual(basic_file, output)
-
-        output = self.parser_roundtrip(multiple_records, True)
-        self.assertEqual(multiple_records, output)
-
     def test_multiple_commas(self):
-        output = self.parser_roundtrip(fn_with_multiple_commas, True)
+        output = self.parser_roundtrip(fn_with_multiple_commas)
         self.assertEqual(fn_with_multiple_commas, output)
 
 multiple_included_files = """//@line 1 "foo.js"
 bazfoobar
 //@line 2 "bar.js"
 @foo@
 //@line 3 "foo.js"
 bazbarfoo
@@ -166,22 +156,16 @@ class TestLineRemapping(unittest.TestCas
 
         self.lcov_rewriter = lcov_rewriter.LcovFileRewriter('', '', [])
         self.pp_rewriter = self.lcov_rewriter.pp_rewriter
 
     def tearDown(self):
         if self._old_chrome_info_file:
             shutil.move(self._old_chrome_info_file, self._chrome_map_file)
 
-    def get_lcov_file(self, name):
-        fpath = os.path.join(here, name)
-        with open(fpath) as fh:
-            lcov_file = lcov_rewriter.LcovFile(fh)
-        return lcov_file
-
     def test_map_multiple_included(self):
         self.pp_rewriter.populate_pp_info(StringIO(multiple_included_files),
                                           '')
         actual = self.pp_rewriter.pp_info['']
         expected = {
             (2, 3): ('foo.js', 1),
             (4, 5): ('bar.js', 2),
             (6, 7): ('foo.js', 3),
@@ -209,45 +193,65 @@ class TestLineRemapping(unittest.TestCas
             (453, 602): ('page.js', 141),
             (2675, 2678): ('newTab.js', 70),
             (56, 321): ('transformations.js', 6),
             (603, 863): ('grid.js', 6),
             (322, 452): ('page.js', 6),
             (986, 1401): ('sites.js', 6)
         }
 
-        lcov_file = self.get_lcov_file('sample_lcov.info')
+        self.pp_rewriter.pp_info['lcov_test_newTab.js'] = pp_remap
+
+        fpath = os.path.join(here, 'sample_lcov.info')
+
+        # Read original records
+        with open(fpath) as fh:
+            lcov_file = lcov_rewriter.LcovFile(fh)
+            records = [lcov_file.parse_record(r) for _, _, r in lcov_file.iterate_records()]
 
-        self.assertEqual(len(lcov_file.records), 1)
+            # This summarization changes values due multiple reports per line coming
+            # from the JS engine (bug 1198356).
+            for r in records:
+                r.resummarize()
+                original_line_count = r.line_count
+                original_covered_line_count = r.covered_line_count
+                original_function_count = r.function_count
+                original_covered_function_count = r.covered_function_count
+
+            self.assertEqual(len(records), 1)
 
-        # This summarization changes values due multiple reports per line coming
-        # from the JS engine (bug 1198356).
-        for r in lcov_file.records:
-            r.resummarize()
-            original_line_count = r.line_count
-            original_covered_line_count = r.covered_line_count
-            original_function_count = r.function_count
-            original_covered_function_count = r.covered_function_count
+        # Rewrite preprocessed entries.
+        with open(fpath) as fh:
+            lcov_file = lcov_rewriter.LcovFile(fh)
+            r_num = []
+            def rewrite_source(s):
+                r_num.append(1)
+                return s, self.pp_rewriter.has_pp_info(s)
 
-        self.pp_rewriter.pp_info['lcov_test_newTab.js'] = pp_remap
-        additions = []
-        for r in lcov_file.records:
-            additions += self.pp_rewriter.rewrite_record(r)
-        lcov_file.records = lcov_file.records + additions
-        self.assertEqual(len(lcov_file.records), 17)
+            out = StringIO()
+            lcov_file.print_file(out, rewrite_source, self.pp_rewriter.rewrite_record)
+            self.assertEqual(len(r_num), 1)
+
+        # Read rewritten lcov.
+        fh = StringIO(out.getvalue())
+        lcov_file = lcov_rewriter.LcovFile(fh)
+
+        records = [lcov_file.parse_record(r) for _, _, r in lcov_file.iterate_records()]
+
+        self.assertEqual(len(records), 17)
 
         # Lines/functions are only "moved" between records, not duplicated or omited.
         self.assertEqual(original_line_count,
-                         sum(r.line_count for r in lcov_file.records))
+                         sum(r.line_count for r in records))
         self.assertEqual(original_covered_line_count,
-                         sum(r.covered_line_count for r in lcov_file.records))
+                         sum(r.covered_line_count for r in records))
         self.assertEqual(original_function_count,
-                         sum(r.function_count for r in lcov_file.records))
+                         sum(r.function_count for r in records))
         self.assertEqual(original_covered_function_count,
-                         sum(r.covered_function_count for r in lcov_file.records))
+                         sum(r.covered_function_count for r in records))
 
 class TestUrlFinder(unittest.TestCase):
     def setUp(self):
         chrome_map_file = os.path.join(buildconfig.topobjdir, 'chrome-map.json')
         self._old_chrome_info_file = None
         if os.path.isfile(chrome_map_file):
             backup_file = os.path.join(buildconfig.topobjdir, 'chrome-map-backup.json')
             self._old_chrome_info_file = backup_file
--- a/taskcluster/ci/test/tests.yml
+++ b/taskcluster/ci/test/tests.yml
@@ -4,17 +4,16 @@
 # for a description of the fields used here.
 
 # Note that these are in lexical order, as enforced by the task loader.
 
 awsy:
     description: "Are we slim yet"
     suite: awsy
     treeherder-symbol: tc-SY(sy)
-    docker-image: {"in-tree": "desktop1604-test"}
     max-run-time: 7200
     instance-size: xlarge
     allow-software-gl-layers: false
     mozharness:
         script: awsy_script.py
         config:
             by-test-platform:
                 windows.*/opt:
@@ -23,17 +22,16 @@ awsy:
                     - awsy/macosx_config.py
                 default:
                     - awsy/linux_config.py
 
 awsy-stylo:
     description: "Are we slim yet for Stylo parallel"
     suite: awsy
     treeherder-symbol: tc-SY-stylo(sy)
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             macosx64-stylo/.*: ['mozilla-central', 'try']
             default: built-projects
     max-run-time: 7200
     instance-size: xlarge
     allow-software-gl-layers: false
     mozharness:
@@ -50,17 +48,16 @@ awsy-stylo:
                     - awsy/linux_config.py
         extra-options:
             - --enable-stylo
 
 awsy-stylo-sequential:
     description: "Are we slim yet for Stylo sequential"
     suite: awsy
     treeherder-symbol: tc-SY-stylo-seq(sy)
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             macosx64-stylo/.*: ['mozilla-central', 'try']
             default: built-projects
     max-run-time: 7200
     instance-size: xlarge
     allow-software-gl-layers: false
     mozharness:
@@ -74,17 +71,16 @@ awsy-stylo-sequential:
             - --enable-stylo
             - --single-stylo-traversal
 
 cppunit:
     description: "CPP Unit Tests"
     suite: cppunittest
     treeherder-symbol: tc(Cpp)
     e10s: false
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             windows10-64-asan/opt: []  # as an exception to windows.*
             linux64-qr/.*: ['mozilla-central', 'try']
             macosx64-stylo/.*: ['autoland', 'mozilla-central', 'try']
             default: built-projects
     mozharness:
         by-test-platform:
@@ -113,17 +109,16 @@ cppunit:
 crashtest:
     description: "Crashtest run"
     suite: reftest/crashtest
     treeherder-symbol: tc-R(C)
     instance-size:
         by-test-platform:
             android.*: xlarge
             default: default
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             # Deactivate try on Buildbot, by default. We don't have enough machines
             windows8-64.*: ['mozilla-release', 'mozilla-beta', 'mozilla-central', 'mozilla-inbound', 'autoland']
             windows8-64-devedition/opt: built-projects  # No dev edition outside of supported branches
             windows10.*: []
             macosx64-stylo/.*: ['autoland', 'mozilla-central', 'try']
             default: built-projects
@@ -165,17 +160,16 @@ crashtest:
             linux64-qr/.*: 1
             default: default
 
 firefox-ui-functional-local:
     description: "Firefox-ui-tests functional run"
     suite: "firefox-ui/functional local"
     treeherder-symbol: tc-Fxfn-l(en-US)
     max-run-time: 5400
-    docker-image: {"in-tree": "desktop1604-test"}
     mozharness:
         script: firefox_ui_tests/functional.py
         config:
             by-test-platform:
                 windows.*:
                     - firefox_ui_tests/taskcluster_windows.py
                 macosx.*:
                     - firefox_ui_tests/taskcluster.py
@@ -187,17 +181,16 @@ firefox-ui-functional-local:
             - "local"
 
 firefox-ui-functional-remote:
     description: "Firefox-ui-tests functional run"
     suite: "firefox-ui/functional remote"
     treeherder-symbol: tc-Fxfn-r(en-US)
     max-run-time: 5400
     tier: 2
-    docker-image: {"in-tree": "desktop1604-test"}
     mozharness:
         script: firefox_ui_tests/functional.py
         config:
             by-test-platform:
                 windows.*:
                     - firefox_ui_tests/taskcluster_windows.py
                 macosx.*:
                     - firefox_ui_tests/taskcluster.py
@@ -224,17 +217,16 @@ geckoview:
             - --test-suite=geckoview
 
 gtest:
     description: "GTests run"
     suite: gtest
     treeherder-symbol: tc(GTest)
     e10s: false
     instance-size: xlarge
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             linux64-qr/.*: ['mozilla-central', 'try']
             windows.*-pgo/.*: [] # permafails on pgo
             default: built-projects
     mozharness:
         script: desktop_unittest.py
         no-read-buildbot-config: true
@@ -255,17 +247,16 @@ gtest:
             windows10-64-pgo.*: 3
             default: default
 
 jittest:
     description: "JIT Test run"
     suite: jittest/jittest-chunked
     treeherder-symbol: tc(Jit)
     e10s: false
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             linux64-qr/.*: ['mozilla-central', 'try']
             default: built-projects
     chunks:
         by-test-platform:
             windows.*: 1
             macosx.*: 1
@@ -293,17 +284,16 @@ jittest:
         files-changed:
             - js/src/**
             - js/public/**
 
 jsreftest:
     description: "JS Reftest run"
     suite: reftest/jsreftest
     treeherder-symbol: tc-R(J)
-    docker-image: {"in-tree": "desktop1604-test"}
     instance-size:
         by-test-platform:
             android.*: xlarge
             default: default
     chunks:
         by-test-platform:
             android-4.3-arm7-api-15/debug: 100
             android.*: 40
@@ -356,17 +346,16 @@ marionette:
     max-run-time:
         by-test-platform:
             android.*: 3600
             default: 5400
     instance-size:
         by-test-platform:
             android.*: xlarge
             default: default
-    docker-image: {"in-tree": "desktop1604-test"}
     tier:
         by-test-platform:
             android.*: 2
             default: default
     chunks:
         by-test-platform:
             android.*: 10
             default: 1
@@ -397,17 +386,16 @@ marionette-headless:
     suite: marionette
     treeherder-symbol: tc(MnH)
     max-run-time:
         by-test-platform:
             default: 5400
     instance-size:
         by-test-platform:
             default: default
-    docker-image: {"in-tree": "desktop1604-test"}
     tier:
         by-test-platform:
             default: default
     chunks:
         by-test-platform:
             default: 1
     mozharness:
         by-test-platform:
@@ -431,17 +419,16 @@ marionette-headless:
 mochitest:
     description: "Mochitest plain run"
     suite:
         by-test-platform:
             linux64-jsdcov/opt: mochitest/plain-chunked-coverage
             default: mochitest/plain-chunked
     treeherder-symbol: tc-M()
     loopback-video: true
-    docker-image: {"in-tree": "desktop1604-test"}
     instance-size:
         by-test-platform:
             linux64-jsdcov/opt: xlarge
             android.*: xlarge
             default: legacy # Bug 1281241: migrating to m3.large instances
     chunks:
         by-test-platform:
             android-4.3-arm7-api-15/debug: 48
@@ -503,17 +490,16 @@ mochitest:
                             - --mochitest-suite=plain-chunked
 
 mochitest-a11y:
     description: "Mochitest a11y run"
     suite: mochitest/a11y
     treeherder-symbol: tc-M(a11y)
     loopback-video: true
     e10s: false
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             linux64-qr/.*: ['mozilla-central', 'try']
             default: built-projects
     mozharness:
         script: desktop_unittest.py
         no-read-buildbot-config: true
         chunked: false
@@ -533,17 +519,16 @@ mochitest-a11y:
 mochitest-browser-chrome:
     description: "Mochitest browser-chrome run"
     suite:
         by-test-platform:
             linux64-jsdcov/opt: mochitest/browser-chrome-coverage
             default: mochitest/browser-chrome-chunked
     treeherder-symbol: tc-M(bc)
     loopback-video: true
-    docker-image: {"in-tree": "desktop1604-test"}
     chunks:
         by-test-platform:
             linux64-jsdcov/opt: 35
             linux64/debug: 16
             linux32/debug: 16
             linux64-asan/opt: 16
             default: 7
     e10s:
@@ -628,17 +613,16 @@ mochitest-browser-screenshots:
     allow-software-gl-layers: false
 
 mochitest-chrome:
     description: "Mochitest chrome run"
     suite: mochitest/chrome
     treeherder-symbol: tc-M(c)
     loopback-video: true
     virtualization: hardware
-    docker-image: {"in-tree": "desktop1604-test"}
     instance-size:
         by-test-platform:
             android.*: xlarge
             default: default
     chunks:
         by-test-platform:
             android-4.3-arm7-api-15/debug: 4
             android.*: 2
@@ -690,17 +674,16 @@ mochitest-chrome:
             windows7-32.*: 2
             default: default
 
 mochitest-chrome-style:
     description: "Mochitest chrome run for style system"
     suite: mochitest/chrome-style
     treeherder-symbol: tc-M(cs)
     loopback-video: true
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             macosx64-stylo/.*: ['autoland', 'mozilla-central', 'try']
             default: built-projects
     e10s: false
     mozharness:
         mochitest-flavor: chrome
         script: desktop_unittest.py
@@ -718,17 +701,16 @@ mochitest-chrome-style:
             - --mochitest-suite=chrome-style
 
 mochitest-clipboard:
     description: "Mochitest clipboard run"
     suite: mochitest/clipboard
     treeherder-symbol: tc-M(cl)
     loopback-video: true
     virtualization: hardware
-    docker-image: {"in-tree": "desktop1604-test"}
     instance-size: xlarge
     run-on-projects:
         by-test-platform:
             windows.*: ['try']
             default: built-projects
     worker-type:
         by-test-platform:
             windows7-32.*: buildbot-bridge/buildbot-bridge
@@ -771,17 +753,16 @@ mochitest-devtools-chrome:
     description: "Mochitest devtools-chrome run"
     suite:
         by-test-platform:
             linux64-jsdcov/opt: mochitest/mochitest-devtools-chrome-coverage
             default: mochitest/mochitest-devtools-chrome-chunked
     treeherder-symbol: tc-M(dt)
     loopback-video: true
     max-run-time: 5400
-    docker-image: {"in-tree": "desktop1604-test"}
     chunks:
         by-test-platform:
             windows.*: 8
             macosx.*: 8
             default: 10
     run-on-projects:
         by-test-platform:
             # Deactivate try on Buildbot, by default. We don't have enough machines
@@ -826,17 +807,16 @@ mochitest-devtools-chrome:
     allow-software-gl-layers: false
 
 mochitest-gpu:
     description: "Mochitest GPU run"
     suite: mochitest/gpu
     treeherder-symbol: tc-M(gpu)
     loopback-video: true
     virtualization: virtual-with-gpu
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             # Deactivate try on Buildbot, by default. We don't have enough machines
             windows8-64.*: ['mozilla-release', 'mozilla-beta', 'mozilla-central', 'mozilla-inbound', 'autoland']
             windows8-64-devedition/opt: built-projects  # No dev edition outside of supported branches
             windows10.*: []
             default: built-projects
     worker-type:
@@ -901,28 +881,26 @@ mochitest-jetpack:
             - --mochitest-suite=jetpack-package
 
 mochitest-media:
     description: "Mochitest media run"
     suite: mochitest/mochitest-media
     treeherder-symbol: tc-M(mda)
     max-run-time: 5400
     loopback-video: true
-    docker-image: {"in-tree": "desktop1604-test"}
     instance-size:
         by-test-platform:
             android.*: xlarge
             default: large
     chunks:
         by-test-platform:
             android.*: 3
             macosx64.*: 1
             windows8-64.*: 1
             default: 3
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             # Deactivate try on Buildbot, by default. We don't have enough machines
             windows8-64.*: ['mozilla-release', 'mozilla-beta', 'mozilla-central', 'mozilla-inbound', 'autoland']
             windows8-64-devedition/opt: built-projects  # No dev edition outside of supported branches
             windows10.*: []
             default: built-projects
     worker-type:
@@ -964,17 +942,16 @@ mochitest-media:
             linux64-qr/.*: 1
             default: default
 
 mochitest-style:
     description: "Mochitest plain run for style system"
     suite: mochitest/plain-style
     treeherder-symbol: tc-M(s)
     loopback-video: true
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             macosx64-stylo/.*: ['autoland', 'mozilla-central', 'try']
             default: built-projects
     mozharness:
         mochitest-flavor: plain
         script: desktop_unittest.py
         no-read-buildbot-config: true
@@ -1019,17 +996,16 @@ mochitest-valgrind:
         extra-options:
             - --mochitest-suite=valgrind-plain
 
 mochitest-webgl:
     description: "Mochitest webgl run"
     suite: mochitest/mochitest-gl
     treeherder-symbol: tc-M(gl)
     virtualization: virtual-with-gpu
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             # Deactivate try on Buildbot, by default. We don't have enough machines
             windows8-64.*: ['mozilla-release', 'mozilla-beta', 'mozilla-central', 'mozilla-inbound', 'autoland']
             windows8-64-devedition/opt: built-projects  # No dev edition outside of supported branches
             windows10.*: []
             default: built-projects
     worker-type:
@@ -1082,17 +1058,16 @@ mochitest-webgl:
         by-test-platform:
             linux64-qr/.*: 1
             default: default
 
 reftest:
     description: "Reftest run"
     suite: reftest/reftest
     treeherder-symbol: tc-R(R)
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             # Deactivate try on Buildbot, by default. We don't have enough machines
             windows8-64.*: ['mozilla-release', 'mozilla-beta', 'mozilla-central', 'mozilla-inbound', 'autoland']
             windows8-64-devedition/opt: built-projects  # No dev edition outside of supported branches
             windows10.*: []
             macosx64-stylo/.*: ['autoland', 'mozilla-central', 'try']
             default: built-projects
@@ -1151,17 +1126,16 @@ reftest:
         by-test-platform:
             linux64-qr/.*: 1
             default: default
 
 reftest-gpu:
     description: "Reftest GPU run"
     suite: reftest/reftest-gpu
     treeherder-symbol: tc-R(Rg)
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             windows10.*: []
             windows8-64.*: []
             default: built-projects
     worker-type:
         by-test-platform:
             windows7-32.*/debug: buildbot-bridge/buildbot-bridge
@@ -1194,17 +1168,16 @@ reftest-gpu:
                     - --reftest-suite=reftest-gpu
     tier: default
 
 reftest-no-accel:
     description: "Reftest not accelerated run"
     suite: reftest/reftest-no-accel
     treeherder-symbol: tc-R(Ru)
     virtualization: virtual-with-gpu
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             windows10.*: []
             linux64-qr/.*: ['mozilla-central', 'try']
             # Deactivate try on Buildbot, by default. We don't have enough machines
             windows8-64.*: ['mozilla-release', 'mozilla-beta', 'mozilla-central', 'mozilla-inbound', 'autoland']
             windows8-64-devedition/opt: built-projects  # No dev edition outside of supported branches
             default: built-projects
@@ -1702,17 +1675,16 @@ talos-xperf:
 
 telemetry-tests-client:
     description: "Telemetry tests client run"
     suite: telemetry-tests-client
     treeherder-symbol: tc-e10s
     max-run-time: 5400
     checkout: true
     tier: 3
-    docker-image: {"in-tree": "desktop1604-test"}
     mozharness:
         script: telemetry/telemetry_client.py
         config:
             by-test-platform:
                 linux.*:
                     - remove_executables.py
                 windows.*: []
 
@@ -1723,17 +1695,16 @@ web-platform-tests:
     treeherder-symbol: tc-W(wpt)
     chunks:
       by-test-platform:
         macosx64/opt: 5
         macosx64/debug: 10
         default: 12
     max-run-time: 7200
     instance-size: xlarge
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             macosx64-stylo/.*: ['autoland', 'mozilla-central', 'try']
             default: built-projects
     mozharness:
         script: web_platform_tests.py
         no-read-buildbot-config: true
         chunked: true
@@ -1755,17 +1726,16 @@ web-platform-tests-reftests:
     treeherder-symbol: tc-W(Wr)
     max-run-time: 5400
     instance-size: xlarge
     chunks:
       by-test-platform:
         macosx.*: 1
         windows.*: 1
         default: 6
-    docker-image: {"in-tree": "desktop1604-test"}
     run-on-projects:
         by-test-platform:
             macosx64-stylo/.*: ['autoland', 'mozilla-central', 'try']
             default: built-projects
     mozharness:
         script: web_platform_tests.py
         no-read-buildbot-config: true
         config:
@@ -1781,17 +1751,16 @@ web-platform-tests-reftests:
             - --test-type=reftest
 
 web-platform-tests-wdspec:
     description: "Web platform webdriver-spec run"
     suite: web-platform-tests-wdspec
     treeherder-symbol: tc-W(Wd)
     max-run-time: 5400
     instance-size: xlarge
-    docker-image: {"in-tree": "desktop1604-test"}
     mozharness:
         script: web_platform_tests.py
         no-read-buildbot-config: true
         config:
             by-test-platform:
                 windows.*:
                     - web_platform_tests/prod_config_windows_taskcluster.py
                 macosx.*:
@@ -1816,17 +1785,16 @@ xpcshell:
             windows8-64.*: ['mozilla-release', 'mozilla-beta', 'mozilla-central', 'mozilla-inbound', 'autoland']
             windows8-64-devedition/opt: built-projects  # No dev edition outside of supported branches
             windows10-64-asan/opt: []  # No XPCShell on ASAN yet
             default: built-projects
     worker-type:
         by-test-platform:
             windows8-64.*: buildbot-bridge/buildbot-bridge
             default: null
-    docker-image: {"in-tree": "desktop1604-test"}
     tier:
         by-test-platform:
             default: default
     chunks:
         by-test-platform:
             linux64/debug: 10
             android-4.2-x86/opt: 6
             macosx.*: 1
--- a/taskcluster/taskgraph/transforms/tests.py
+++ b/taskcluster/taskgraph/transforms/tests.py
@@ -225,17 +225,17 @@ test_description_schema = Schema({
     # due to poor LLVMPipe performance (bug 1296086).  Defaults to true for
     # unit tests on linux platforms and false otherwise
     Optional('allow-software-gl-layers'): bool,
 
     # For tasks that will run in docker-worker or docker-engine, this is the
     # name of the docker image or in-tree docker image to run the task in.  If
     # in-tree, then a dependency will be created automatically.  This is
     # generally `desktop-test`, or an image that acts an awful lot like it.
-    Required('docker-image', default={'in-tree': 'desktop-test'}): optionally_keyed_by(
+    Required('docker-image', default={'in-tree': 'desktop1604-test'}): optionally_keyed_by(
         'test-platform',
         Any(
             # a raw Docker image path (repo/image:tag)
             basestring,
             # an in-tree generated docker image (from `taskcluster/docker/<name>`)
             {'in-tree': basestring}
         )
     ),
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -298645,21 +298645,16 @@
      {}
     ]
    ],
    "old-tests/submission/Opera/script_scheduling/scripts/include-11.js": [
     [
      {}
     ]
    ],
-   "old-tests/submission/Opera/script_scheduling/scripts/include-12.js": [
-    [
-     {}
-    ]
-   ],
    "old-tests/submission/Opera/script_scheduling/scripts/include-2.js": [
     [
      {}
     ]
    ],
    "old-tests/submission/Opera/script_scheduling/scripts/include-3.js": [
     [
      {}
@@ -360667,22 +360662,16 @@
     ]
    ],
    "old-tests/submission/Opera/script_scheduling/099.html": [
     [
      "/old-tests/submission/Opera/script_scheduling/099.html",
      {}
     ]
    ],
-   "old-tests/submission/Opera/script_scheduling/100.html": [
-    [
-     "/old-tests/submission/Opera/script_scheduling/100.html",
-     {}
-    ]
-   ],
    "old-tests/submission/Opera/script_scheduling/101.html": [
     [
      "/old-tests/submission/Opera/script_scheduling/101.html",
      {}
     ]
    ],
    "old-tests/submission/Opera/script_scheduling/103.html": [
     [
@@ -603300,20 +603289,16 @@
   "old-tests/submission/Opera/script_scheduling/097.html": [
    "3ac30238216932854620a416f05cb1e7abcb25aa",
    "testharness"
   ],
   "old-tests/submission/Opera/script_scheduling/099.html": [
    "49a56e4ebe6a752002776f81c8511b6f34852a15",
    "testharness"
   ],
-  "old-tests/submission/Opera/script_scheduling/100.html": [
-   "c8e8962700545210d6f2e900af7e562d6d624171",
-   "testharness"
-  ],
   "old-tests/submission/Opera/script_scheduling/101.html": [
    "8aa9b4d0c0c3aec53f4b9cbbbe04a98198379c8f",
    "testharness"
   ],
   "old-tests/submission/Opera/script_scheduling/102.html": [
    "0b63d6d6e084ce841d491badee08cb3854095576",
    "support"
   ],
@@ -603548,20 +603533,16 @@
   "old-tests/submission/Opera/script_scheduling/scripts/include-10.js": [
    "8b70b5a43ab3f1efd9755bf95f9a2713bbe588ce",
    "support"
   ],
   "old-tests/submission/Opera/script_scheduling/scripts/include-11.js": [
    "f26e65bc15505040371e3026cd09c8eb0df0a1c4",
    "support"
   ],
-  "old-tests/submission/Opera/script_scheduling/scripts/include-12.js": [
-   "7dcd929b6b7dd65553f87ec8b0fbf0ec84c335b2",
-   "support"
-  ],
   "old-tests/submission/Opera/script_scheduling/scripts/include-2.js": [
    "3a3c18956bb0ccf8c13b301cd3c6f0a6e474ce75",
    "support"
   ],
   "old-tests/submission/Opera/script_scheduling/scripts/include-3.js": [
    "80d22183699d06a1b7da5136a118404a7e05778e",
    "support"
   ],
deleted file mode 100644
--- a/testing/web-platform/tests/old-tests/submission/Opera/script_scheduling/100.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html><head>
-	<title> scheduler: defer adding iframe containing script</title>
-	<script src="/resources/testharness.js"></script>
-	<script src="/resources/testharnessreport.js"></script>
-	<script src="testlib/testlib.js"></script>
-</head>
-<body>
-
-	<div id="log">FAILED (This TC requires JavaScript enabled)</div>
-
-        <script defer src="scripts/include-12.js"></script>
-	<script>
-          var t = async_test();
-
-          onload = t.step_func(function() {assert_array_equals(eventOrder, ["external script before adding object", "script in object"]); t.done();});
-        </script>
-</body>
-</html>
deleted file mode 100644
--- a/testing/web-platform/tests/old-tests/submission/Opera/script_scheduling/scripts/include-12.js
+++ /dev/null
@@ -1,4 +0,0 @@
-log("external script before adding object");
-var object = document.createElement("object");
-object.data = "data:text/html,<script>parent.log('script in object')</script>"
-document.body.appendChild(object);
\ No newline at end of file
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -42,18 +42,16 @@ Cu.import("resource://gre/modules/XPCOMU
 Cu.import("resource://gre/modules/Services.jsm");
 
 /* globals processCount */
 
 XPCOMUtils.defineLazyPreferenceGetter(this, "processCount", "dom.ipc.processCount.extension");
 
 XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
                                   "resource://gre/modules/AddonManager.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
-                                  "resource://gre/modules/AppConstants.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown",
                                   "resource://gre/modules/AsyncShutdown.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionAPIs",
                                   "resource://gre/modules/ExtensionAPI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionCommon",
                                   "resource://gre/modules/ExtensionCommon.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionPermissions",
                                   "resource://gre/modules/ExtensionPermissions.jsm");
@@ -64,22 +62,16 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "Log",
                                   "resource://gre/modules/Log.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "MessageChannel",
                                   "resource://gre/modules/MessageChannel.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
                                   "resource://gre/modules/NetUtil.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
                                   "resource://gre/modules/osfile.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
-                                  "resource://gre/modules/PrivateBrowsingUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
-                                  "resource://gre/modules/Preferences.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "require",
-                                  "resource://devtools/shared/Loader.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Schemas",
                                   "resource://gre/modules/Schemas.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "setTimeout",
                                   "resource://gre/modules/Timer.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
                                   "resource://gre/modules/TelemetryStopwatch.jsm");
 
 XPCOMUtils.defineLazyGetter(
@@ -195,27 +187,27 @@ const COMMENT_REGEXP = new RegExp(String
 // All moz-extension URIs use a machine-specific UUID rather than the
 // extension's own ID in the host component. This makes it more
 // difficult for web pages to detect whether a user has a given add-on
 // installed (by trying to load a moz-extension URI referring to a
 // web_accessible_resource from the extension). UUIDMap.get()
 // returns the UUID for a given add-on ID.
 var UUIDMap = {
   _read() {
-    let pref = Preferences.get(UUID_MAP_PREF, "{}");
+    let pref = Services.prefs.getStringPref(UUID_MAP_PREF, "{}");
     try {
       return JSON.parse(pref);
     } catch (e) {
       Cu.reportError(`Error parsing ${UUID_MAP_PREF}.`);
       return {};
     }
   },
 
   _write(map) {
-    Preferences.set(UUID_MAP_PREF, JSON.stringify(map));
+    Services.prefs.setStringPref(UUID_MAP_PREF, JSON.stringify(map));
   },
 
   get(id, create = true) {
     let map = this._read();
 
     if (id in map) {
       return map[id];
     }
@@ -576,17 +568,17 @@ this.ExtensionData = class {
       }
     } catch (e) {
       // Errors are handled by the type checks above.
     }
 
     let whitelist = [];
     for (let perm of this.manifest.permissions) {
       if (perm === "geckoProfiler") {
-        const acceptedExtensions = Preferences.get("extensions.geckoProfiler.acceptedExtensionIds");
+        const acceptedExtensions = Services.prefs.getStringPref("extensions.geckoProfiler.acceptedExtensionIds", "");
         if (!acceptedExtensions.split(",").includes(this.id)) {
           this.manifestError("Only whitelisted extensions are allowed to access the geckoProfiler.");
           continue;
         }
       }
 
       let type = classifyPermission(perm);
       if (type.origin) {
--- a/toolkit/components/extensions/ExtensionAPI.jsm
+++ b/toolkit/components/extensions/ExtensionAPI.jsm
@@ -10,18 +10,16 @@ this.EXPORTED_SYMBOLS = ["ExtensionAPI",
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ConsoleAPI",
                                   "resource://gre/modules/Console.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
-                                  "resource://gre/modules/EventEmitter.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Schemas",
                                   "resource://gre/modules/Schemas.jsm");
 
 const global = this;
 
 class ExtensionAPI {
   constructor(extension) {
     this.extension = extension;
--- a/toolkit/components/extensions/ExtensionContent.jsm
+++ b/toolkit/components/extensions/ExtensionContent.jsm
@@ -529,17 +529,17 @@ defineLazyGetter(ContentScriptContextChi
 // scripts into them when new documents are created.
 DocumentManager = {
   // Map[windowId -> Map[ExtensionChild -> ContentScriptContextChild]]
   contexts: new Map(),
 
   initialized: false,
 
   lazyInit() {
-    if (this.initalized) {
+    if (this.initialized) {
       return;
     }
     this.initialized = true;
 
     Services.obs.addObserver(this, "inner-window-destroyed");
     Services.obs.addObserver(this, "memory-pressure");
   },
 
--- a/toolkit/components/extensions/ExtensionParent.jsm
+++ b/toolkit/components/extensions/ExtensionParent.jsm
@@ -13,28 +13,24 @@ const {classes: Cc, interfaces: Ci, util
 
 /* exported ExtensionParent */
 
 this.EXPORTED_SYMBOLS = ["ExtensionParent"];
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
-                                  "resource://gre/modules/AddonManager.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
                                   "resource://gre/modules/AppConstants.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DeferredSave",
                                   "resource://gre/modules/DeferredSave.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "E10SUtils",
                                   "resource:///modules/E10SUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
                                   "resource://gre/modules/FileUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "IndexedDB",
-                                  "resource://gre/modules/IndexedDB.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "MessageChannel",
                                   "resource://gre/modules/MessageChannel.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NativeApp",
                                   "resource://gre/modules/NativeMessaging.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
                                   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Schemas",
                                   "resource://gre/modules/Schemas.jsm");
--- a/toolkit/components/extensions/ExtensionPermissions.jsm
+++ b/toolkit/components/extensions/ExtensionPermissions.jsm
@@ -7,18 +7,16 @@ Cu.import("resource://gre/modules/XPCOMU
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionParent",
                                   "resource://gre/modules/ExtensionParent.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionUtils",
                                   "resource://gre/modules/ExtensionUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
                                   "resource://gre/modules/FileUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "JSONFile",
                                   "resource://gre/modules/JSONFile.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "OS",
-                                  "resource://gre/modules/osfile.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "StartupCache", () => ExtensionParent.StartupCache);
 
 this.EXPORTED_SYMBOLS = ["ExtensionPermissions"];
 
 const FILE_NAME = "extension-preferences.json";
 
 let prefs;
--- a/toolkit/components/extensions/ExtensionStorageSync.jsm
+++ b/toolkit/components/extensions/ExtensionStorageSync.jsm
@@ -36,46 +36,42 @@ const HISTOGRAM_GET_OPS_SIZE = "STORAGE_
 const HISTOGRAM_SET_OPS_SIZE = "STORAGE_SYNC_SET_OPS_SIZE";
 const HISTOGRAM_REMOVE_OPS = "STORAGE_SYNC_REMOVE_OPS";
 const SCALAR_EXTENSIONS_USING = "storage.sync.api.usage.extensions_using";
 const SCALAR_ITEMS_STORED = "storage.sync.api.usage.items_stored";
 const SCALAR_STORAGE_CONSUMED = "storage.sync.api.usage.storage_consumed";
 // Default is 5sec, which seems a bit aggressive on the open internet
 const KINTO_REQUEST_TIMEOUT = 30000;
 
+Cu.import("resource://gre/modules/Log.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 
 
 XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown",
                                   "resource://gre/modules/AsyncShutdown.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "BulkKeyBundle",
                                   "resource://services-sync/keys.js");
 XPCOMUtils.defineLazyModuleGetter(this, "CollectionKeyManager",
                                   "resource://services-sync/record.js");
 XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
                                   "resource://services-common/utils.js");
 XPCOMUtils.defineLazyModuleGetter(this, "CryptoUtils",
                                   "resource://services-crypto/utils.js");
-XPCOMUtils.defineLazyModuleGetter(this, "ExtensionStorage",
-                                  "resource://gre/modules/ExtensionStorage.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
                                   "resource://gre/modules/FxAccounts.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "KintoHttpClient",
                                   "resource://services-common/kinto-http-client.js");
 XPCOMUtils.defineLazyModuleGetter(this, "Kinto",
                                   "resource://services-common/kinto-offline-client.js");
 XPCOMUtils.defineLazyModuleGetter(this, "FirefoxAdapter",
                                   "resource://services-common/kinto-storage-adapter.js");
-XPCOMUtils.defineLazyModuleGetter(this, "Log",
-                                  "resource://gre/modules/Log.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Observers",
                                   "resource://services-common/observers.js");
-XPCOMUtils.defineLazyModuleGetter(this, "Services",
-                                  "resource://gre/modules/Services.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Sqlite",
                                   "resource://gre/modules/Sqlite.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Utils",
                                   "resource://services-sync/util.js");
 XPCOMUtils.defineLazyPreferenceGetter(this, "prefPermitsStorageSync",
                                       STORAGE_SYNC_ENABLED_PREF, true);
 XPCOMUtils.defineLazyPreferenceGetter(this, "prefStorageSyncServerURL",
                                       STORAGE_SYNC_SERVER_URL_PREF,
--- a/toolkit/components/extensions/ExtensionUtils.jsm
+++ b/toolkit/components/extensions/ExtensionUtils.jsm
@@ -11,18 +11,16 @@ const Cc = Components.classes;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ConsoleAPI",
                                   "resource://gre/modules/Console.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "MessageChannel",
-                                  "resource://gre/modules/MessageChannel.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
                                   "resource://gre/modules/osfile.jsm");
 
 function getConsole() {
   return new ConsoleAPI({
     maxLogLevelPref: "extensions.webextensions.log.level",
     prefix: "WebExtensions",
   });
--- a/toolkit/components/extensions/ext-backgroundPage.js
+++ b/toolkit/components/extensions/ext-backgroundPage.js
@@ -1,14 +1,10 @@
 "use strict";
 
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
-                                  "resource://gre/modules/AddonManager.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
                                   "resource://gre/modules/TelemetryStopwatch.jsm");
 
 Cu.import("resource://gre/modules/ExtensionParent.jsm");
 var {
   HiddenExtensionPage,
   promiseExtensionViewLoaded,
 } = ExtensionParent;
--- a/toolkit/components/extensions/ext-browser-content.js
+++ b/toolkit/components/extensions/ext-browser-content.js
@@ -6,20 +6,16 @@
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "clearTimeout",
                                   "resource://gre/modules/Timer.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionCommon",
                                   "resource://gre/modules/ExtensionCommon.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
-                                  "resource://gre/modules/NetUtil.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "require",
-                                  "resource://devtools/shared/Loader.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "setTimeout",
                                   "resource://gre/modules/Timer.jsm");
 
 Cu.import("resource://gre/modules/ExtensionUtils.jsm");
 const {
   getWinUtils,
 } = ExtensionUtils;
 
--- a/toolkit/components/extensions/ext-c-extension.js
+++ b/toolkit/components/extensions/ext-c-extension.js
@@ -1,13 +1,10 @@
 "use strict";
 
-XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
-                                  "resource://gre/modules/PrivateBrowsingUtils.jsm");
-
 this.extension = class extends ExtensionAPI {
   getAPI(context) {
     let api = {
       getURL(url) {
         return context.extension.baseURI.resolve(url);
       },
 
       get lastError() {
--- a/toolkit/components/extensions/ext-c-storage.js
+++ b/toolkit/components/extensions/ext-c-storage.js
@@ -1,17 +1,16 @@
 "use strict";
 
 /* import-globals-from ext-c-toolkit.js */
 
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionStorage",
                                   "resource://gre/modules/ExtensionStorage.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
                                   "resource://gre/modules/TelemetryStopwatch.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
 
 var {
   ExtensionError,
 } = ExtensionUtils;
 
 const storageGetHistogram = "WEBEXT_STORAGE_LOCAL_GET_MS";
 const storageSetHistogram = "WEBEXT_STORAGE_LOCAL_SET_MS";
 
--- a/toolkit/components/extensions/ext-cookies.js
+++ b/toolkit/components/extensions/ext-cookies.js
@@ -1,15 +1,13 @@
 "use strict";
 
 // The ext-* files are imported into the same scopes.
 /* import-globals-from ext-toolkit.js */
 
-XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
-                                  "resource://gre/modules/ContextualIdentityService.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 
 /* globals DEFAULT_STORE, PRIVATE_STORE */
 
 const convertCookie = ({cookie, isPrivate}) => {
   let result = {
     name: cookie.name,
--- a/toolkit/components/extensions/ext-downloads.js
+++ b/toolkit/components/extensions/ext-downloads.js
@@ -8,18 +8,16 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
                                   "resource://gre/modules/Downloads.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadPaths",
                                   "resource://gre/modules/DownloadPaths.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
                                   "resource://gre/modules/osfile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
                                   "resource://gre/modules/FileUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
-                                  "resource://gre/modules/NetUtil.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
                                   "resource://gre/modules/EventEmitter.jsm");
 
 var {
   normalizeTime,
 } = ExtensionUtils;
 
 var {
@@ -460,17 +458,17 @@ this.downloads = class extends Extension
             return Promise.resolve();
           }
 
           async function createTarget(downloadsDir) {
             let target;
             if (filename) {
               target = OS.Path.join(downloadsDir, filename);
             } else {
-              let uri = NetUtil.newURI(options.url);
+              let uri = Services.io.newURI(options.url);
 
               let remote;
               if (uri instanceof Ci.nsIURL) {
                 remote = uri.fileName;
               }
               target = OS.Path.join(downloadsDir, remote || "download");
             }
 
--- a/toolkit/components/extensions/ext-permissions.js
+++ b/toolkit/components/extensions/ext-permissions.js
@@ -1,14 +1,12 @@
 "use strict";
 
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionPermissions",
                                   "resource://gre/modules/ExtensionPermissions.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
-                                  "resource://gre/modules/NetUtil.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 
 var {
   ExtensionError,
 } = ExtensionUtils;
 
 XPCOMUtils.defineLazyPreferenceGetter(this, "promptsEnabled",
--- a/toolkit/components/extensions/ext-runtime.js
+++ b/toolkit/components/extensions/ext-runtime.js
@@ -2,22 +2,20 @@
 
 // The ext-* files are imported into the same scopes.
 /* import-globals-from ext-toolkit.js */
 
 XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
                                   "resource://gre/modules/AddonManager.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AddonManagerPrivate",
                                   "resource://gre/modules/AddonManager.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Extension",
-                                  "resource://gre/modules/Extension.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionParent",
                                   "resource://gre/modules/ExtensionParent.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
-                                  "resource://gre/modules/NetUtil.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Services",
+                                  "resource://gre/modules/Services.jsm");
 
 this.runtime = class extends ExtensionAPI {
   getAPI(context) {
     let {extension} = context;
     return {
       runtime: {
         onStartup: new EventManager(context, "runtime.onStartup", fire => {
           if (context.incognito) {
@@ -121,17 +119,17 @@ this.runtime = class extends ExtensionAP
 
         setUninstallURL: function(url) {
           if (url.length == 0) {
             return Promise.resolve();
           }
 
           let uri;
           try {
-            uri = NetUtil.newURI(url);
+            uri = Services.io.newURI(url);
           } catch (e) {
             return Promise.reject({message: `Invalid URL: ${JSON.stringify(url)}`});
           }
 
           if (uri.scheme != "http" && uri.scheme != "https") {
             return Promise.reject({message: "url must have the scheme http or https"});
           }
 
--- a/toolkit/components/extensions/ext-theme.js
+++ b/toolkit/components/extensions/ext-theme.js
@@ -1,22 +1,20 @@
 "use strict";
 
 Cu.import("resource://gre/modules/Services.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
-                                  "resource://gre/modules/Preferences.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
                                   "resource://gre/modules/LightweightThemeManager.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "gThemesEnabled", () => {
-  return Preferences.get("extensions.webextensions.themes.enabled");
+  return Services.prefs.getBoolPref("extensions.webextensions.themes.enabled");
 });
 
-const ICONS = Preferences.get("extensions.webextensions.themes.icons.buttons", "").split(",");
+const ICONS = Services.prefs.getStringPref("extensions.webextensions.themes.icons.buttons", "").split(",");
 
 /** Class representing a theme. */
 class Theme {
   /**
    * Creates a theme instance.
    *
    * @param {string} baseURI The base URI of the extension, used to
    *   resolve relative filepaths.
@@ -128,17 +126,17 @@ class Theme {
   }
 
   /**
    * Helper method for loading icons found in the extension's manifest.
    *
    * @param {Object} icons Dictionary mapping icon properties to extension URLs.
    */
   loadIcons(icons) {
-    if (!Preferences.get("extensions.webextensions.themes.icons.enabled")) {
+    if (!Services.prefs.getBoolPref("extensions.webextensions.themes.icons.enabled")) {
       // Return early if icons are disabled.
       return;
     }
 
     for (let icon of Object.getOwnPropertyNames(icons)) {
       let val = icons[icon];
       // We also have to compare against the baseURI spec because
       // `val` might have been resolved already. Resolving "" against
--- a/toolkit/components/prompts/content/tabprompts.xml
+++ b/toolkit/components/prompts/content/tabprompts.xml
@@ -155,17 +155,19 @@
                     throw "BUTTON_DELAY_ENABLE not yet supported for tab-modal prompts";
 
                 // We need to remove the prompt when the tab or browser window is closed or
                 // the page navigates, else we never unwind the event loop and that's sad times.
                 // Remember to cleanup in shutdownPrompt()!
                 this.isLive = true;
                 window.addEventListener("resize", this);
                 window.addEventListener("unload", this);
-                linkedTab.addEventListener("TabClose", this);
+                if (linkedTab) {
+                  linkedTab.addEventListener("TabClose", this);
+                }
                 // Note:
                 // nsPrompter.js or in e10s mode browser-parent.js call abortPrompt,
                 // when the domWindow, for which the prompt was created, generates
                 // a "pagehide" event.
 
                 let tmp = {};
                 Components.utils.import("resource://gre/modules/CommonDialog.jsm", tmp);
                 this.Dialog = new tmp.CommonDialog(args, this.ui);
@@ -186,17 +188,19 @@
 
         <method name="shutdownPrompt">
             <body>
             <![CDATA[
                 // remove our event listeners
                 try {
                     window.removeEventListener("resize", this);
                     window.removeEventListener("unload", this);
-                    this.linkedTab.removeEventListener("TabClose", this);
+                    if (this.linkedTab) {
+                      this.linkedTab.removeEventListener("TabClose", this);
+                    }
                 } catch (e) { }
                 this.isLive = false;
                 // invoke callback
                 this.onCloseCallback();
             ]]>
             </body>
         </method>
 
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -71,17 +71,17 @@
 
 #include "mozilla/Logging.h"
 #include "LogModulePrefWatcher.h"
 
 using namespace mozilla;
 
 static LazyLogModule nsComponentManagerLog("nsComponentManager");
 
-#if 0 || defined (DEBUG_timeless)
+#if 0
  #define SHOW_DENIED_ON_SHUTDOWN
  #define SHOW_CI_ON_EXISTING_SERVICE
 #endif
 
 // Bloated registry buffer size to improve startup performance -- needs to
 // be big enough to fit the entire file into memory or it'll thrash.
 // 512K is big enough to allow for some future growth in the registry.
 #define BIG_REGISTRY_BUFLEN   (512*1024)
@@ -975,21 +975,21 @@ nsComponentManagerImpl::CreateInstance(c
                                        void** aResult)
 {
   // test this first, since there's no point in creating a component during
   // shutdown -- whether it's available or not would depend on the order it
   // occurs in the list
   if (gXPCOMShuttingDown) {
     // When processing shutdown, don't process new GetService() requests
 #ifdef SHOW_DENIED_ON_SHUTDOWN
-    nsXPIDLCString cid, iid;
-    cid.Adopt(aClass.ToString());
-    iid.Adopt(aIID.ToString());
+    char cid[NSID_LENGTH], iid[NSID_LENGTH];
+    aClass.ToProvidedString(cid);
+    aIID.ToProvidedString(iid);
     fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
-            "         CID: %s\n         IID: %s\n", cid.get(), iid.get());
+            "         CID: %s\n         IID: %s\n", cid, iid);
 #endif /* SHOW_DENIED_ON_SHUTDOWN */
     return NS_ERROR_UNEXPECTED;
   }
 
   if (!aResult) {
     return NS_ERROR_NULL_POINTER;
   }
   *aResult = nullptr;
@@ -997,21 +997,21 @@ nsComponentManagerImpl::CreateInstance(c
   nsFactoryEntry* entry = GetFactoryEntry(aClass);
 
   if (!entry) {
     return NS_ERROR_FACTORY_NOT_REGISTERED;
   }
 
 #ifdef SHOW_CI_ON_EXISTING_SERVICE
   if (entry->mServiceObject) {
-    nsXPIDLCString cid;
-    cid.Adopt(aClass.ToString());
+    char cid[NSID_LENGTH];
+    aClass.ToProvidedString(cid);
     nsAutoCString message;
     message = NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
-              cid +
+              nsDependentCString(cid) +
               NS_LITERAL_CSTRING("\" when a service for this CID already exists!");
     NS_ERROR(message.get());
   }
 #endif
 
   nsresult rv;
   nsCOMPtr<nsIFactory> factory = entry->GetFactory();
   if (factory) {
@@ -1058,20 +1058,20 @@ nsComponentManagerImpl::CreateInstanceBy
   }
 
   // test this first, since there's no point in creating a component during
   // shutdown -- whether it's available or not would depend on the order it
   // occurs in the list
   if (gXPCOMShuttingDown) {
     // When processing shutdown, don't process new GetService() requests
 #ifdef SHOW_DENIED_ON_SHUTDOWN
-    nsXPIDLCString iid;
-    iid.Adopt(aIID.ToString());
+    char iid[NSID_LENGTH];
+    aIID.ToProvidedString(iid);
     fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
-            "  ContractID: %s\n         IID: %s\n", aContractID, iid.get());
+            "  ContractID: %s\n         IID: %s\n", aContractID, iid);
 #endif /* SHOW_DENIED_ON_SHUTDOWN */
     return NS_ERROR_UNEXPECTED;
   }
 
   if (!aResult) {
     return NS_ERROR_NULL_POINTER;
   }
   *aResult = nullptr;
@@ -1181,21 +1181,21 @@ nsComponentManagerImpl::GetService(const
                                    void** aResult)
 {
   // test this first, since there's no point in returning a service during
   // shutdown -- whether it's available or not would depend on the order it
   // occurs in the list
   if (gXPCOMShuttingDown) {
     // When processing shutdown, don't process new GetService() requests
 #ifdef SHOW_DENIED_ON_SHUTDOWN
-    nsXPIDLCString cid, iid;
-    cid.Adopt(aClass.ToString());
-    iid.Adopt(aIID.ToString());
+    char cid[NSID_LENGTH], iid[NSID_LENGTH];
+    aClass.ToProvidedString(cid);
+    aIID.ToProvidedString(iid);
     fprintf(stderr, "Getting service on shutdown. Denied.\n"
-            "         CID: %s\n         IID: %s\n", cid.get(), iid.get());
+            "         CID: %s\n         IID: %s\n", cid, iid);
 #endif /* SHOW_DENIED_ON_SHUTDOWN */
     return NS_ERROR_UNEXPECTED;
   }
 
   // `service` must be released after the lock is released, so it must be
   // declared before the lock in this C++ block.
   nsCOMPtr<nsISupports> service;
   MutexLock lock(mLock);
@@ -1297,21 +1297,21 @@ nsComponentManagerImpl::IsServiceInstant
   // to create an instance of it. mmh!
 
   // test this first, since there's no point in returning a service during
   // shutdown -- whether it's available or not would depend on the order it
   // occurs in the list
   if (gXPCOMShuttingDown) {
     // When processing shutdown, don't process new GetService() requests
 #ifdef SHOW_DENIED_ON_SHUTDOWN
-    nsXPIDLCString cid, iid;
-    cid.Adopt(aClass.ToString());
-    iid.Adopt(aIID.ToString());
+    char cid[NSID_LENGTH], iid[NSID_LENGTH];
+    aClass.ToProvidedString(cid);
+    aIID.ToProvidedString(iid);
     fprintf(stderr, "Checking for service on shutdown. Denied.\n"
-            "         CID: %s\n         IID: %s\n", cid.get(), iid.get());
+            "         CID: %s\n         IID: %s\n", cid, iid);
 #endif /* SHOW_DENIED_ON_SHUTDOWN */
     return NS_ERROR_UNEXPECTED;
   }
 
   nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
   nsFactoryEntry* entry;
 
   {
@@ -1338,20 +1338,20 @@ nsComponentManagerImpl::IsServiceInstant
   // to create an instance of it. mmh!
 
   // test this first, since there's no point in returning a service during
   // shutdown -- whether it's available or not would depend on the order it
   // occurs in the list
   if (gXPCOMShuttingDown) {
     // When processing shutdown, don't process new GetService() requests
 #ifdef SHOW_DENIED_ON_SHUTDOWN
-    nsXPIDLCString iid;
-    iid.Adopt(aIID.ToString());
+    char iid[NSID_LENGTH];
+    aIID.ToProvidedString(iid);
     fprintf(stderr, "Checking for service on shutdown. Denied.\n"
-            "  ContractID: %s\n         IID: %s\n", aContractID, iid.get());
+            "  ContractID: %s\n         IID: %s\n", aContractID, iid);
 #endif /* SHOW_DENIED_ON_SHUTDOWN */
     return NS_ERROR_UNEXPECTED;
   }
 
   nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
   nsFactoryEntry* entry;
   {
     SafeMutexAutoLock lock(mLock);
@@ -1373,20 +1373,20 @@ nsComponentManagerImpl::GetServiceByCont
                                                void** aResult)
 {
   // test this first, since there's no point in returning a service during
   // shutdown -- whether it's available or not would depend on the order it
   // occurs in the list
   if (gXPCOMShuttingDown) {
     // When processing shutdown, don't process new GetService() requests
 #ifdef SHOW_DENIED_ON_SHUTDOWN
-    nsXPIDLCString iid;
-    iid.Adopt(aIID.ToString());
+    char iid[NSID_LENGTH];
+    aIID.ToProvidedString(iid);
     fprintf(stderr, "Getting service on shutdown. Denied.\n"
-            "  ContractID: %s\n         IID: %s\n", aContractID, iid.get());
+            "  ContractID: %s\n         IID: %s\n", aContractID, iid);
 #endif /* SHOW_DENIED_ON_SHUTDOWN */
     return NS_ERROR_UNEXPECTED;
   }
 
   // `service` must be released after the lock is released, so it must be
   // declared before the lock in this C++ block.
   nsCOMPtr<nsISupports> service;
   MutexLock lock(mLock);
--- a/xpcom/ds/nsTArray.h
+++ b/xpcom/ds/nsTArray.h
@@ -2196,17 +2196,17 @@ auto
 nsTArray_Impl<E, Alloc>::AppendElement(Item&& aItem) -> elem_type*
 {
   if (!ActualAlloc::Successful(this->template EnsureCapacity<ActualAlloc>(
          Length() + 1, sizeof(elem_type)))) {
     return nullptr;
   }
   elem_type* elem = Elements() + Length();
   elem_traits::Construct(elem, mozilla::Forward<Item>(aItem));
-  this->IncrementLength(1);
+  this->mHdr->mLength += 1;
   return elem;
 }
 
 template<typename E, typename Alloc>
 inline void
 ImplCycleCollectionUnlink(nsTArray_Impl<E, Alloc>& aField)
 {
   aField.Clear();