Merge mozilla-central to b2g-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Mon, 13 Jan 2014 14:44:08 +0100
changeset 163129 6af4c495a33fbf10a293d03e7314674756d70a07
parent 163128 8c99b82a36e640e68eab68c99d65e6a4a953bf79 (current diff)
parent 163108 80a27198344a0cedc444aa80071380d5726b5a39 (diff)
child 163130 fbe57a30e322ced26f5d35a78805156ddfd7fd4d
push id25982
push userryanvm@gmail.com
push dateMon, 13 Jan 2014 22:30:39 +0000
treeherdermozilla-central@d524c4b2cbb8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to b2g-inbound
content/xbl/builtin/android/jar.mn
content/xbl/builtin/android/moz.build
content/xbl/builtin/android/platformHTMLBindings.xml
content/xbl/builtin/browser-base.inc
content/xbl/builtin/editor-base.inc
content/xbl/builtin/emacs/jar.mn
content/xbl/builtin/emacs/moz.build
content/xbl/builtin/emacs/platformHTMLBindings.xml
content/xbl/builtin/input-fields-base.inc
content/xbl/builtin/mac/jar.mn
content/xbl/builtin/mac/moz.build
content/xbl/builtin/mac/platformHTMLBindings.xml
content/xbl/builtin/moz.build
content/xbl/builtin/textareas-base.inc
content/xbl/builtin/unix/jar.mn
content/xbl/builtin/unix/moz.build
content/xbl/builtin/unix/platformHTMLBindings.xml
content/xbl/builtin/win/jar.mn
content/xbl/builtin/win/moz.build
content/xbl/builtin/win/platformHTMLBindings.xml
content/xbl/crashtests/205735-1.xhtml
content/xbl/crashtests/223799-1.xul
content/xbl/crashtests/226744-1.xhtml
content/xbl/crashtests/232095-1.xul
content/xbl/crashtests/277523-1.xhtml
content/xbl/crashtests/277950-1.xhtml
content/xbl/crashtests/336744-1-inner.html
content/xbl/crashtests/336744-1.html
content/xbl/crashtests/336960-1-inner.xhtml
content/xbl/crashtests/336960-1.html
content/xbl/crashtests/342954-1.xhtml
content/xbl/crashtests/342954-2-xbl.xml
content/xbl/crashtests/342954-2.xhtml
content/xbl/crashtests/368276-1.xhtml
content/xbl/crashtests/368641-1.xhtml
content/xbl/crashtests/378521-1.xhtml
content/xbl/crashtests/382376-1.xhtml
content/xbl/crashtests/382376-2.xhtml
content/xbl/crashtests/397596-1.xhtml
content/xbl/crashtests/404125-1.xhtml
content/xbl/crashtests/406900-1.xul
content/xbl/crashtests/406904-1.xhtml
content/xbl/crashtests/406904-2.xhtml
content/xbl/crashtests/415192-1.xul
content/xbl/crashtests/415301-1.xul
content/xbl/crashtests/418133-1.xhtml
content/xbl/crashtests/420233-1.xhtml
content/xbl/crashtests/421997-1.xhtml
content/xbl/crashtests/432813-1-xbl.xml
content/xbl/crashtests/432813-1.xhtml
content/xbl/crashtests/454820-1.html
content/xbl/crashtests/460665-1.xhtml
content/xbl/crashtests/463511-1.xhtml
content/xbl/crashtests/464863-1.xhtml
content/xbl/crashtests/472260-1.xhtml
content/xbl/crashtests/477878-1.html
content/xbl/crashtests/492978-1.xul
content/xbl/crashtests/493123-1.xhtml
content/xbl/crashtests/495354-1.xhtml
content/xbl/crashtests/507628-1.xhtml
content/xbl/crashtests/507991-1.xhtml
content/xbl/crashtests/830614-1.xul
content/xbl/crashtests/895805-1.xhtml
content/xbl/crashtests/crashtests.list
content/xbl/crashtests/set-field-bad-this.xhtml
content/xbl/moz.build
content/xbl/src/XBLChildrenElement.cpp
content/xbl/src/XBLChildrenElement.h
content/xbl/src/moz.build
content/xbl/src/nsBindingManager.cpp
content/xbl/src/nsBindingManager.h
content/xbl/src/nsXBLBinding.cpp
content/xbl/src/nsXBLBinding.h
content/xbl/src/nsXBLContentSink.cpp
content/xbl/src/nsXBLContentSink.h
content/xbl/src/nsXBLDocumentInfo.cpp
content/xbl/src/nsXBLDocumentInfo.h
content/xbl/src/nsXBLEventHandler.cpp
content/xbl/src/nsXBLEventHandler.h
content/xbl/src/nsXBLMaybeCompiled.h
content/xbl/src/nsXBLProtoImpl.cpp
content/xbl/src/nsXBLProtoImpl.h
content/xbl/src/nsXBLProtoImplField.cpp
content/xbl/src/nsXBLProtoImplField.h
content/xbl/src/nsXBLProtoImplMember.h
content/xbl/src/nsXBLProtoImplMethod.cpp
content/xbl/src/nsXBLProtoImplMethod.h
content/xbl/src/nsXBLProtoImplProperty.cpp
content/xbl/src/nsXBLProtoImplProperty.h
content/xbl/src/nsXBLPrototypeBinding.cpp
content/xbl/src/nsXBLPrototypeBinding.h
content/xbl/src/nsXBLPrototypeHandler.cpp
content/xbl/src/nsXBLPrototypeHandler.h
content/xbl/src/nsXBLPrototypeResources.cpp
content/xbl/src/nsXBLPrototypeResources.h
content/xbl/src/nsXBLResourceLoader.cpp
content/xbl/src/nsXBLResourceLoader.h
content/xbl/src/nsXBLSerialize.cpp
content/xbl/src/nsXBLSerialize.h
content/xbl/src/nsXBLService.cpp
content/xbl/src/nsXBLService.h
content/xbl/src/nsXBLWindowKeyHandler.cpp
content/xbl/src/nsXBLWindowKeyHandler.h
content/xbl/test/bug310107-resource.xhtml
content/xbl/test/chrome.ini
content/xbl/test/file_bug372769.xhtml
content/xbl/test/file_bug379959_cross.html
content/xbl/test/file_bug379959_data.html
content/xbl/test/file_bug379959_xbl.xml
content/xbl/test/file_bug397934.xhtml
content/xbl/test/file_bug481558.xbl
content/xbl/test/file_bug481558css.sjs
content/xbl/test/file_bug591198_inner.html
content/xbl/test/file_bug591198_xbl.xml
content/xbl/test/file_bug821850.xhtml
content/xbl/test/file_bug844783.xhtml
content/xbl/test/file_bug944407.html
content/xbl/test/file_bug944407.xml
content/xbl/test/file_bug950909.html
content/xbl/test/file_bug950909.xml
content/xbl/test/mochitest.ini
content/xbl/test/moz.build
content/xbl/test/test_bug310107.html
content/xbl/test/test_bug366770.html
content/xbl/test/test_bug371724.xhtml
content/xbl/test/test_bug372769.html
content/xbl/test/test_bug378518.xul
content/xbl/test/test_bug378866.xhtml
content/xbl/test/test_bug379959.html
content/xbl/test/test_bug389322.xhtml
content/xbl/test/test_bug397934.html
content/xbl/test/test_bug398135.xul
content/xbl/test/test_bug398492.xul
content/xbl/test/test_bug400705.xhtml
content/xbl/test/test_bug401907.xhtml
content/xbl/test/test_bug403162.xhtml
content/xbl/test/test_bug468210.xhtml
content/xbl/test/test_bug481558.html
content/xbl/test/test_bug526178.xhtml
content/xbl/test/test_bug542406.xhtml
content/xbl/test/test_bug591198.html
content/xbl/test/test_bug639338.xhtml
content/xbl/test/test_bug721452.xul
content/xbl/test/test_bug723676.xul
content/xbl/test/test_bug772966.xul
content/xbl/test/test_bug790265.xhtml
content/xbl/test/test_bug821850.html
content/xbl/test/test_bug844783.html
content/xbl/test/test_bug944407.xul
content/xbl/test/test_bug950909.xul
docshell/base/nsIDocShellTreeNode.idl
gfx/layers/opengl/GrallocTextureClient.cpp
gfx/layers/opengl/GrallocTextureHost.cpp
gfx/layers/opengl/TextureHostOGL.cpp
mobile/android/app/recommended-addons.json
mobile/android/base/home/BookmarksPage.java
mobile/android/base/home/HistoryPage.java
mobile/android/base/home/LastTabsPage.java
mobile/android/base/home/ListManager.java
mobile/android/base/home/ListPage.java
mobile/android/base/home/MostRecentPage.java
mobile/android/base/home/ReadingListPage.java
mobile/android/base/home/TopSitesPage.java
mobile/android/base/resources/drawable/home_page_title_background.xml
mobile/android/base/resources/layout-large-land-v11/home_history_page.xml
mobile/android/base/resources/layout-xlarge-v11/home_history_page.xml
mobile/android/base/resources/layout/home_bookmarks_page.xml
mobile/android/base/resources/layout/home_history_page.xml
mobile/android/base/resources/layout/home_last_tabs_page.xml
mobile/android/base/resources/layout/home_most_recent_page.xml
mobile/android/base/resources/layout/home_reading_list_page.xml
mobile/android/base/resources/layout/home_top_sites_page.xml
mobile/android/base/tests/testBookmarksPage.java
toolkit/xre/nsUpdateDriver.cpp
--- a/.lldbinit
+++ b/.lldbinit
@@ -1,9 +1,11 @@
 # .lldbinit file for debugging Mozilla
 
 # Mozilla's use of UNIFIED_SOURCES to include multiple source files into a
 # single compiled file breaks lldb breakpoint setting. This works around that.
 # See http://lldb.llvm.org/troubleshooting.html for more info.
 settings set target.inline-breakpoint-strategy always
 
-# Deduce the concrete types of objects and pointers when printing them.
+# Show the dynamic type of an object when using "expr".  This, for example,
+# will show a variable declared as "nsIFrame *" that points to an nsBlockFrame
+# object as being of type "nsBlockFrame *" rather than "nsIFrame *".
 settings set target.prefer-dynamic-value run-target
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 944533 requires clobber to force a Proguard refresh
+Bug 958185 requires clobber on Android to force a Proguard refresh
--- a/accessible/src/base/moz.build
+++ b/accessible/src/base/moz.build
@@ -54,27 +54,27 @@ UNIFIED_SOURCES += [
 ]
 
 if a11y_log:
     UNIFIED_SOURCES += [
         'Logging.cpp',
     ]
 
 LOCAL_INCLUDES += [
-    '../../../content/xbl/src',
-    '../../../ipc/chromium/src',
-    '../../../layout/generic',
-    '../../../layout/style',
-    '../../../layout/svg',
-    '../../../layout/xul',
-    '../../../layout/xul/tree/',
     '../generic',
     '../html',
     '../xpcom',
     '../xul',
+    '/dom/xbl',
+    '/ipc/chromium/src',
+    '/layout/generic',
+    '/layout/style',
+    '/layout/svg',
+    '/layout/xul',
+    '/layout/xul/tree/',
 ]
 
 if CONFIG['MOZ_ENABLE_GTK']:
     LOCAL_INCLUDES += [
         '../atk',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     LOCAL_INCLUDES += [
--- a/accessible/src/generic/DocAccessible.h
+++ b/accessible/src/generic/DocAccessible.h
@@ -16,17 +16,16 @@
 #include "nsDataHashtable.h"
 #include "nsIDocument.h"
 #include "nsIDocumentObserver.h"
 #include "nsIEditor.h"
 #include "nsIObserver.h"
 #include "nsIScrollPositionListener.h"
 #include "nsITimer.h"
 #include "nsIWeakReference.h"
-#include "nsIDocShellTreeNode.h"
 
 class nsAccessiblePivot;
 
 class nsIScrollableView;
 
 const uint32_t kDefaultCacheSize = 256;
 
 namespace mozilla {
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -1145,24 +1145,26 @@ window.addEventListener('ContentStart', 
     if (e.detail.type !== 'take-screenshot')
       return;
 
     try {
       var canvas = document.createElementNS('http://www.w3.org/1999/xhtml',
                                             'canvas');
       var width = window.innerWidth;
       var height = window.innerHeight;
-      canvas.setAttribute('width', width);
-      canvas.setAttribute('height', height);
+      var scale = window.devicePixelRatio;
+      canvas.setAttribute('width', width * scale);
+      canvas.setAttribute('height', height * scale);
 
       var context = canvas.getContext('2d');
       var flags =
         context.DRAWWINDOW_DRAW_CARET |
         context.DRAWWINDOW_DRAW_VIEW |
         context.DRAWWINDOW_USE_WIDGET_LAYERS;
+      context.scale(scale, scale);
       context.drawWindow(window, 0, 0, width, height,
                          'rgb(255,255,255)', flags);
 
       // I can't use sendChromeEvent() here because it doesn't wrap
       // the blob in the detail object correctly. So I use __exposedProps__
       // instead to safely send the chrome detail object to content.
       shell.sendEvent(getContentWindow(), 'mozChromeEvent', {
         __exposedProps__: { type: 'r', file: 'r' },
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1387580658000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1389295339000">
   <emItems>
       <emItem  blockID="i454" id="sqlmoz@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                                 <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i58" id="webmaster@buzzzzvideos.info">
@@ -48,26 +48,26 @@
       <emItem  blockID="i65" id="activity@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i527" id="/^({bfec236d-e122-4102-864f-f5f19d897f5e}|{3f842035-47f4-4f10-846b-6199b07f09b8}|{92ed4bbd-83f2-4c70-bb4e-f8d3716143fe})$/">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i224" id="{336D0C35-8A85-403a-B9D2-65C292C39087}">
+      <emItem  blockID="i535" id="/^ext@WebexpEnhancedV1alpha[0-9]+\.net$/">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i105" id="{95ff02bc-ffc6-45f0-a5c8-619b8226a9de}">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i117" id="{ce7e73df-6a44-4028-8079-5927a588c948}">
-                        <versionRange  minVersion="0" maxVersion="1.0.8" severity="1">
+      <emItem  blockID="i506" id="/^ext@bettersurfplus/">
+                        <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i400" id="{dd6b651f-dfb9-4142-b0bd-09912ad22674}">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i488" id="jid1-4P0kohSJxU1qGg@jetpack">
                         <versionRange  minVersion="1.2.50" maxVersion="1.2.50" severity="1">
@@ -107,20 +107,16 @@
       <emItem  blockID="i64" id="royal@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i72" os="WINNT" id="{4ED1F68A-5463-4931-9384-8FFF5ED91D92}">
                         <versionRange  minVersion="3.4.1" maxVersion="3.4.1.194" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i506" id="ext@bettersurfplus.com">
-                        <versionRange  minVersion="0" maxVersion="*" severity="3">
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i100" id="{394DCBA4-1F92-4f8e-8EC9-8D2CB90CB69B}">
                         <versionRange  minVersion="2.5.0" maxVersion="2.5.0" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i40" id="{28387537-e3f9-4ed7-860c-11e69af4a8a0}">
                         <versionRange  minVersion="0.1" maxVersion="4.3.1.00" severity="1">
                     </versionRange>
                   </emItem>
@@ -452,16 +448,20 @@
       <emItem  blockID="i501" id="xivars@aol.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i482" id="brasilescapeeight@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i226" id="{462be121-2b54-4218-bf00-b9bf8135b23f}">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i246" id="support@vide1flash2.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i48" id="admin@youtubespeedup.com">
                         </emItem>
       <emItem  blockID="i218" id="ffxtlbr@claro.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
@@ -550,16 +550,20 @@
       <emItem  blockID="i504" id="aytac@abc.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i92" id="play5@vide04flash.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i117" id="{ce7e73df-6a44-4028-8079-5927a588c948}">
+                        <versionRange  minVersion="0" maxVersion="1.0.8" severity="1">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i474" id="{906000a4-88d9-4d52-b209-7a772970d91f}">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i453" id="/^brasilescape.*\@facebook\.com$/">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
@@ -867,17 +871,17 @@
       <emItem  blockID="i346" id="{a6e67e6f-8615-4fe0-a599-34a73fc3fba5}">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i220" id="pricepeep@getpricepeep.com">
                         <versionRange  minVersion="0" maxVersion="2.1.0.19.99" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i226" id="{462be121-2b54-4218-bf00-b9bf8135b23f}">
+      <emItem  blockID="i224" id="{336D0C35-8A85-403a-B9D2-65C292C39087}">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i61" id="youtube@youtube3.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                                 <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
@@ -944,16 +948,20 @@
       <emItem  blockID="i489" id="astrovia@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i497" id="{872b5b88-9db5-4310-bdd0-ac189557e5f5}">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i534" id="{f9d03c26-0575-497e-821d-f7956d23e0ca}">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i68" id="flashupdate@adobe.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i445" id="firefoxaddon@youtubeenhancer.com">
                         <versionRange  minVersion="208.7.0" maxVersion="208.7.0" severity="3">
                     </versionRange>
                   </emItem>
--- a/browser/base/content/browser-addons.js
+++ b/browser/base/content/browser-addons.js
@@ -4,17 +4,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 const gXPInstallObserver = {
   _findChildShell: function (aDocShell, aSoughtShell)
   {
     if (aDocShell == aSoughtShell)
       return aDocShell;
 
-    var node = aDocShell.QueryInterface(Components.interfaces.nsIDocShellTreeNode);
+    var node = aDocShell.QueryInterface(Components.interfaces.nsIDocShellTreeItem);
     for (var i = 0; i < node.childCount; ++i) {
       var docShell = node.getChildAt(i);
       docShell = this._findChildShell(docShell, aSoughtShell);
       if (docShell == aSoughtShell)
         return docShell;
     }
     return null;
   },
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -386,17 +386,17 @@ const gSessionHistoryObserver = {
 function findChildShell(aDocument, aDocShell, aSoughtURI) {
   aDocShell.QueryInterface(Components.interfaces.nsIWebNavigation);
   aDocShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
   var doc = aDocShell.getInterface(Components.interfaces.nsIDOMDocument);
   if ((aDocument && doc == aDocument) ||
       (aSoughtURI && aSoughtURI.spec == aDocShell.currentURI.spec))
     return aDocShell;
 
-  var node = aDocShell.QueryInterface(Components.interfaces.nsIDocShellTreeNode);
+  var node = aDocShell.QueryInterface(Components.interfaces.nsIDocShellTreeItem);
   for (var i = 0; i < node.childCount; ++i) {
     var docShell = node.getChildAt(i);
     docShell = findChildShell(aDocument, docShell, aSoughtURI);
     if (docShell)
       return docShell;
   }
   return null;
 }
@@ -1834,18 +1834,20 @@ function BrowserTryToCloseWindow()
     window.close();     // WindowIsClosing does all the necessary checks
 }
 
 function loadURI(uri, referrer, postData, allowThirdPartyFixup) {
   if (postData === undefined)
     postData = null;
 
   var flags = nsIWebNavigation.LOAD_FLAGS_NONE;
-  if (allowThirdPartyFixup)
+  if (allowThirdPartyFixup) {
     flags |= nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
+    flags |= nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
+  }
 
   try {
     gBrowser.loadURIWithFlags(uri, flags, referrer, null, postData);
   } catch (e) {}
 }
 
 function getShortcutOrURIAndPostData(aURL) {
   return Task.spawn(function() {
@@ -5899,18 +5901,19 @@ function WindowIsClosing()
 }
 
 /**
  * Checks if this is the last full *browser* window around. If it is, this will
  * be communicated like quitting. Otherwise, we warn about closing multiple tabs.
  * @returns true if closing can proceed, false if it got cancelled.
  */
 function warnAboutClosingWindow() {
-  // Popups aren't considered full browser windows.
-  let isPBWindow = PrivateBrowsingUtils.isWindowPrivate(window);
+  // Popups aren't considered full browser windows; we also ignore private windows.
+  let isPBWindow = PrivateBrowsingUtils.isWindowPrivate(window) &&
+        !PrivateBrowsingUtils.permanentPrivateBrowsing;
   if (!isPBWindow && !toolbar.visible)
     return gBrowser.warnAboutClosingTabs(gBrowser.closingTabsEnum.ALL);
 
   // Figure out if there's at least one other browser window around.
   let e = Services.wm.getEnumerator("navigator:browser");
   let otherPBWindowExists = false;
   let nonPopupPresent = false;
   while (e.hasMoreElements()) {
--- a/browser/base/content/openLocation.js
+++ b/browser/base/content/openLocation.js
@@ -77,17 +77,18 @@ function open()
     }
 
     try {
       // Whichever target we use for the load, we allow third-party services to
       // fixup the URI
       switch (dialog.openWhereList.value) {
         case "0":
           var webNav = Components.interfaces.nsIWebNavigation;
-          var flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
+          var flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
+                      webNav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
           if (!mayInheritPrincipal)
             flags |= webNav.LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
           browser.gBrowser.loadURIWithFlags(url, flags, null, null, postData);
           break;
         case "1":
           window.opener.delayedOpenWindow(getBrowserURL(), "all,dialog=no",
                                           url, postData, null, null, true);
           break;
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1596,18 +1596,20 @@
             // then let's just continue loading the page normally.
             if (!docShellsSwapped && !uriIsAboutBlank) {
               // pretend the user typed this so it'll be available till
               // the document successfully loads
               if (aURI && gInitialPages.indexOf(aURI) == -1)
                 b.userTypedValue = aURI;
 
               let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
-              if (aAllowThirdPartyFixup)
+              if (aAllowThirdPartyFixup) {
                 flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
+                flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
+              }
               if (aFromExternal)
                 flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL;
               if (aDisableMCB)
                 flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT;
               try {
                 b.loadURIWithFlags(aURI, flags, aReferrerURI, aCharset, aPostData);
               } catch (ex) {
                 Cu.reportError(ex);
@@ -4475,17 +4477,20 @@
           if (!tab || dropEffect == "copy") {
             // We're adding a new tab.
             let newIndex = this._getDropIndex(event);
             let newTab = this.tabbrowser.loadOneTab(url, {inBackground: bgLoad, allowThirdPartyFixup: true});
             this.tabbrowser.moveTabTo(newTab, newIndex);
           } else {
             // Load in an existing tab.
             try {
-              this.tabbrowser.getBrowserForTab(tab).loadURIWithFlags(url, Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
+              let webNav = Ci.nsIWebNavigation;
+              let flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
+                          webNav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
+              this.tabbrowser.getBrowserForTab(tab).loadURIWithFlags(url, flags);
               if (!bgLoad)
                 this.selectedItem = tab;
             } catch(ex) {
               // Just ignore invalid urls
             }
           }
         }
 
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -288,17 +288,19 @@
               addToUrlbarHistory(url);
             } catch (ex) {
               // Things may go wrong when adding url to session history,
               // but don't let that interfere with the loading of the url.
               Cu.reportError(ex);
             }
 
             function loadCurrent() {
-              let flags = Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
+              let webnav = Ci.nsIWebNavigation;
+              let flags = webnav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
+                          webnav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
               // Pass LOAD_FLAGS_DISALLOW_INHERIT_OWNER to prevent any loads from
               // inheriting the currently loaded document's principal, unless this
               // URL is marked as safe to inherit (e.g. came from a bookmark
               // keyword).
               if (!mayInheritPrincipal)
                 flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
               gBrowser.loadURIWithFlags(url, flags, null, null, postData);
             }
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -295,18 +295,20 @@ function openLinkIn(url, where, params) 
 
   // Raise the target window before loading the URI, since loading it may
   // result in a new frontmost window (e.g. "javascript:window.open('');").
   w.focus();
 
   switch (where) {
   case "current":
     let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
-    if (aAllowThirdPartyFixup)
+    if (aAllowThirdPartyFixup) {
       flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
+      flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
+    }
     if (aDisallowInheritPrincipal)
       flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
     w.gBrowser.loadURIWithFlags(url, flags, aReferrerURI, null, aPostData);
     break;
   case "tabshifted":
     loadInBackground = !loadInBackground;
     // fall through
   case "tab":
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -49,36 +49,36 @@ function shouldLoadURI(aURI) {
 
   dump("*** Preventing external load of chrome: URI into browser window\n");
   dump("    Use -chrome <uri> instead\n");
   return false;
 }
 
 function resolveURIInternal(aCmdLine, aArgument) {
   var uri = aCmdLine.resolveURI(aArgument);
+  var urifixup = Components.classes["@mozilla.org/docshell/urifixup;1"]
+                           .getService(nsIURIFixup);
 
   if (!(uri instanceof nsIFileURL)) {
-    return uri;
+    return urifixup.createFixupURI(aArgument,
+                                   urifixup.FIXUP_FLAG_FIX_SCHEME_TYPOS);
   }
 
   try {
     if (uri.file.exists())
       return uri;
   }
   catch (e) {
     Components.utils.reportError(e);
   }
 
   // We have interpreted the argument as a relative file URI, but the file
   // doesn't exist. Try URI fixup heuristics: see bug 290782.
  
   try {
-    var urifixup = Components.classes["@mozilla.org/docshell/urifixup;1"]
-                             .getService(nsIURIFixup);
-
     uri = urifixup.createFixupURI(aArgument, 0);
   }
   catch (e) {
     Components.utils.reportError(e);
   }
 
   return uri;
 }
--- a/browser/components/sessionstore/src/SessionFile.jsm
+++ b/browser/components/sessionstore/src/SessionFile.jsm
@@ -54,16 +54,32 @@ this.SessionFile = {
   },
   /**
    * Write the contents of the session file, asynchronously.
    */
   write: function (aData) {
     return SessionFileInternal.write(aData);
   },
   /**
+   * Gather telemetry statistics.
+   *
+   *
+   * Most of the work is done off the main thread but there is a main
+   * thread cost involved to send data to the worker thread. This method
+   * should therefore be called only when we know that it will not disrupt
+   * the user's experience, e.g. on idle-daily.
+   *
+   * @return {Promise}
+   * @promise {object} An object holding all the information to be submitted
+   * to Telemetry.
+   */
+  gatherTelemetry: function(aData) {
+    return SessionFileInternal.gatherTelemetry(aData);
+  },
+  /**
    * Writes the initial state to disk again only to change the session's load
    * state. This must only be called once, it will throw an error otherwise.
    */
   writeLoadStateOnceAfterStartup: function (aLoadState) {
     SessionFileInternal.writeLoadStateOnceAfterStartup(aLoadState);
   },
   /**
    * Create a backup copy, asynchronously.
@@ -117,16 +133,24 @@ let SessionFileInternal = {
 
   read: function () {
     return SessionWorker.post("read").then(msg => {
       this._recordTelemetry(msg.telemetry);
       return msg.ok;
     });
   },
 
+  gatherTelemetry: function(aStateString) {
+    return Task.spawn(function() {
+      let msg = yield SessionWorker.post("gatherTelemetry", [aStateString]);
+      this._recordTelemetry(msg.telemetry);
+      throw new Task.Result(msg.telemetry);
+    }.bind(this));
+  },
+
   write: function (aData) {
     if (this._isClosed) {
       return Promise.reject(new Error("SessionFile is closed"));
     }
     let refObj = {};
 
     let isFinalWrite = false;
     if (Services.startup.shuttingDown) {
@@ -172,18 +196,28 @@ let SessionFileInternal = {
     return SessionWorker.post("removeBackupCopy", [ext]);
   },
 
   wipe: function () {
     SessionWorker.post("wipe");
   },
 
   _recordTelemetry: function(telemetry) {
-    for (let histogramId in telemetry){
-      Telemetry.getHistogramById(histogramId).add(telemetry[histogramId]);
+    for (let id of Object.keys(telemetry)){
+      let value = telemetry[id];
+      let samples = [];
+      if (Array.isArray(value)) {
+        samples.push(...value);
+      } else {
+        samples.push(value);
+      }
+      let histogram = Telemetry.getHistogramById(id);
+      for (let sample of samples) {
+        histogram.add(sample);
+      }
     }
   }
 };
 
 // Interface to a dedicated thread handling I/O
 let SessionWorker = (function () {
   let worker = new PromiseWorker("resource:///modules/sessionstore/SessionWorker.js",
     OS.Shared.LOG.bind("SessionWorker"));
@@ -191,19 +225,22 @@ let SessionWorker = (function () {
     post: function post(...args) {
       let promise = worker.post.apply(worker, args);
       return promise.then(
         null,
         function onError(error) {
           // Decode any serialized error
           if (error instanceof PromiseWorker.WorkerError) {
             throw OS.File.Error.fromMsg(error.data);
-          } else {
-            throw error;
           }
+          // Extract something meaningful from ErrorEvent
+          if (error instanceof ErrorEvent) {
+            throw new Error(error.message, error.filename, error.lineno);
+          }
+          throw error;
         }
       );
     }
   };
 })();
 
 // Ensure that we can write sessionstore.js cleanly before the profile
 // becomes unaccessible.
--- a/browser/components/sessionstore/src/SessionStore.jsm
+++ b/browser/components/sessionstore/src/SessionStore.jsm
@@ -30,17 +30,18 @@ const NOTIFY_LAST_SESSION_CLEARED = "ses
 const MAX_CONCURRENT_TAB_RESTORES = 3;
 
 // global notifications observed
 const OBSERVING = [
   "domwindowopened", "domwindowclosed",
   "quit-application-requested", "quit-application-granted",
   "browser-lastwindow-close-granted",
   "quit-application", "browser:purge-session-history",
-  "browser:purge-domain-data"
+  "browser:purge-domain-data",
+  "gather-telemetry",
 ];
 
 // XUL Window properties to (re)store
 // Restored in restoreDimensions()
 const WINDOW_ATTRIBUTES = ["width", "height", "screenX", "screenY", "sizemode"];
 
 // Hideable window features to (re)store
 // Restored in restoreWindowFeatures()
@@ -582,16 +583,19 @@ let SessionStoreInternal = {
         this.onPurgeSessionHistory();
         break;
       case "browser:purge-domain-data":
         this.onPurgeDomainData(aData);
         break;
       case "nsPref:changed": // catch pref changes
         this.onPrefChange(aData);
         break;
+      case "gather-telemetry":
+        this.onGatherTelemetry();
+        break;
     }
   },
 
   /**
    * This method handles incoming messages sent by the session store content
    * script and thus enables communication with OOP tabs.
    */
   receiveMessage: function ssi_receiveMessage(aMessage) {
@@ -1452,16 +1456,26 @@ let SessionStoreInternal = {
     // If possible, update cached data without having to invalidate it
     TabStateCache.updateField(aTab, "hidden", true);
 
     // Default delay of 2 seconds gives enough time to catch multiple TabHide
     // events due to changing groups in Panorama.
     this.saveStateDelayed(aWindow);
   },
 
+  onGatherTelemetry: function() {
+    // On the first gather-telemetry notification of the session,
+    // gather telemetry data.
+    Services.obs.removeObserver(this, "gather-telemetry");
+    this.fillTabCachesAsynchronously().then(function() {
+      let stateString = SessionStore.getBrowserState();
+      return SessionFile.gatherTelemetry(stateString);
+    });
+  },
+
   /* ........ nsISessionStore API .............. */
 
   getBrowserState: function ssi_getBrowserState() {
     let state = this.getCurrentState();
 
     // Don't include the last session state in getBrowserState().
     delete state.lastSessionState;
 
--- a/browser/components/sessionstore/src/SessionWorker.js
+++ b/browser/components/sessionstore/src/SessionWorker.js
@@ -126,16 +126,26 @@ let Agent = {
     if (exn) {
       throw exn;
     }
 
     return ret;
   },
 
   /**
+   * Extract all sorts of useful statistics from a state string,
+   * for use with Telemetry.
+   *
+   * @return {object}
+   */
+  gatherTelemetry: function (stateString) {
+    return Statistics.collect(stateString);
+  },
+
+  /**
    * Writes the session state to disk again but changes session.state to
    * 'running' before doing so. This is intended to be called only once, shortly
    * after startup so that we detect crashes on startup correctly.
    */
   writeLoadStateOnceAfterStartup: function (loadState) {
     if (this.hasWrittenLoadStateOnce) {
       throw new Error("writeLoadStateOnceAfterStartup() must only be called once.");
     }
@@ -231,8 +241,149 @@ let Agent = {
 
     return {result: true};
   }
 };
 
 function isNoSuchFileEx(aReason) {
   return aReason instanceof OS.File.Error && aReason.becauseNoSuchFile;
 }
+
+/**
+ * Estimate the number of bytes that a data structure will use on disk
+ * once serialized.
+ */
+function getByteLength(str) {
+  return Encoder.encode(JSON.stringify(str)).byteLength;
+}
+
+/**
+ * Tools for gathering statistics on a state string.
+ */
+let Statistics = {
+  collect: function(stateString) {
+    let start = Date.now();
+    let TOTAL_PREFIX = "FX_SESSION_RESTORE_TOTAL_";
+    let INDIVIDUAL_PREFIX = "FX_SESSION_RESTORE_INDIVIDUAL_";
+    let SIZE_SUFFIX = "_SIZE_BYTES";
+
+    let state = JSON.parse(stateString);
+
+    // Gather all data
+    let subsets = {};
+    this.gatherSimpleData(state, subsets);
+    this.gatherComplexData(state, subsets);
+
+    // Extract telemetry
+    let telemetry = {};
+    for (let k of Object.keys(subsets)) {
+      let obj = subsets[k];
+      telemetry[TOTAL_PREFIX + k + SIZE_SUFFIX] = getByteLength(obj);
+
+      if (Array.isArray(obj)) {
+        let size = obj.map(getByteLength);
+        telemetry[INDIVIDUAL_PREFIX + k + SIZE_SUFFIX] = size;
+      }
+    }
+
+    let stop = Date.now();
+    telemetry["FX_SESSION_RESTORE_EXTRACTING_STATISTICS_DURATION_MS"] = stop - start;
+    return {
+      telemetry: telemetry
+    };
+  },
+
+  /**
+   * Collect data that doesn't require a recursive walk through the
+   * data structure.
+   */
+  gatherSimpleData: function(state, subsets) {
+    // The subset of sessionstore.js dealing with open windows
+    subsets.OPEN_WINDOWS = state.windows;
+
+    // The subset of sessionstore.js dealing with closed windows
+    subsets.CLOSED_WINDOWS = state._closedWindows;
+
+    // The subset of sessionstore.js dealing with closed tabs
+    // in open windows
+    subsets.CLOSED_TABS_IN_OPEN_WINDOWS = [];
+
+    // The subset of sessionstore.js dealing with cookies
+    // in both open and closed windows
+    subsets.COOKIES = [];
+
+    for (let winData of state.windows) {
+      let closedTabs = winData._closedTabs || [];
+      subsets.CLOSED_TABS_IN_OPEN_WINDOWS.push(...closedTabs);
+
+      let cookies = winData.cookies || [];
+      subsets.COOKIES.push(...cookies);
+    }
+
+    for (let winData of state._closedWindows) {
+      let cookies = winData.cookies || [];
+      subsets.COOKIES.push(...cookies);
+    }
+  },
+
+  /**
+   * Walk through a data structure, recursively.
+   *
+   * @param {object} root The object from which to start walking.
+   * @param {function(key, value)} cb Callback, called for each
+   * item except the root. Returns |true| to walk the subtree rooted
+   * at |value|, |false| otherwise   */
+  walk: function(root, cb) {
+    if (!root || typeof root !== "object") {
+      return;
+    }
+    for (let k of Object.keys(root)) {
+      let obj = root[k];
+      let stepIn = cb(k, obj);
+      if (stepIn) {
+        this.walk(obj, cb);
+      }
+    }
+  },
+
+  /**
+   * Collect data that requires walking through the data structure
+   */
+  gatherComplexData: function(state, subsets) {
+    // The subset of sessionstore.js dealing with DOM storage
+    subsets.DOM_STORAGE = [];
+    // The subset of sessionstore.js storing form data
+    subsets.FORMDATA = [];
+    // The subset of sessionstore.js storing POST data in history
+    subsets.POSTDATA = [];
+    // The subset of sessionstore.js storing history
+    subsets.HISTORY = [];
+
+
+    this.walk(state, function(k, value) {
+      let dest;
+      switch (k) {
+        case "entries":
+          subsets.HISTORY.push(value);
+          return true;
+        case "storage":
+          subsets.DOM_STORAGE.push(value);
+          // Never visit storage, it's full of weird stuff
+          return false;
+        case "formdata":
+          subsets.FORMDATA.push(value);
+          // Never visit formdata, it's full of weird stuff
+          return false;
+        case "postdata_b64":
+          subsets.POSTDATA.push(value);
+          return false; // Nothing to visit anyway
+        case "cookies": // Don't visit these places, they are full of weird stuff
+        case "extData":
+          return false;
+        default:
+          return true;
+      }
+    });
+
+    return subsets;
+  },
+
+};
--- a/browser/components/sessionstore/src/TabStateCache.jsm
+++ b/browser/components/sessionstore/src/TabStateCache.jsm
@@ -290,22 +290,18 @@ let TabStateCacheInternal = {
    *        The new data to be stored for the given |browser|.
    */
   updatePersistent: function (browser, newData) {
     let data = this._persistentData.get(browser) || {};
 
     for (let key of Object.keys(newData)) {
       let value = newData[key];
       if (value === null) {
-        // Remove the field if the value is null.
-        this.removeField(browser, key);
         delete data[key];
       } else {
-        // Update the field otherwise.
-        this.updateField(browser, key, value);
         data[key] = value;
       }
     }
 
     this._persistentData.set(browser, data);
   },
 
   _normalizeToBrowser: function(aKey) {
--- a/browser/components/sessionstore/test/browser.ini
+++ b/browser/components/sessionstore/test/browser.ini
@@ -65,16 +65,17 @@ support-files =
 [browser_merge_closed_tabs.js]
 [browser_pageshow.js]
 [browser_pageStyle.js]
 [browser_privatetabs.js]
 [browser_scrollPositions.js]
 [browser_sessionStorage.js]
 [browser_swapDocShells.js]
 [browser_tabStateCache.js]
+[browser_telemetry.js]
 [browser_upgrade_backup.js]
 [browser_windowRestore_perwindowpb.js]
 [browser_248970_b_perwindowpb.js]
 # Disabled because of leaks.
 # Re-enabling and rewriting this test is tracked in bug 936919.
 skip-if = true
 [browser_339445.js]
 [browser_345898.js]
--- a/browser/components/sessionstore/test/browser_broadcast.js
+++ b/browser/components/sessionstore/test/browser_broadcast.js
@@ -1,14 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-const INITIAL_VALUE = "initial-value-" + Date.now();
+const INITIAL_VALUE = "browser_broadcast.js-initial-value-" + Date.now();
 
 /**
  * This test ensures we won't lose tab data queued in the content script when
  * closing a tab.
  */
 add_task(function flush_on_tabclose() {
   let tab = yield createTabWithStorageData(["http://example.com"]);
   let browser = tab.linkedBrowser;
--- a/browser/components/sessionstore/test/browser_privatetabs.js
+++ b/browser/components/sessionstore/test/browser_privatetabs.js
@@ -1,14 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 let Imports = {};
 Cu.import("resource:///modules/sessionstore/SessionSaver.jsm", Imports);
-let {SessionSaver} = Imports;
+let {Task, SessionSaver} = Imports;
 
 add_task(function cleanup() {
   info("Forgetting closed tabs");
   while (ss.getClosedTabCount(window)) {
     ss.forgetClosedTab(window, 0);
   }
 });
 
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser_telemetry.js
@@ -0,0 +1,266 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+
+let tmp = {};
+Cu.import("resource:///modules/sessionstore/SessionFile.jsm", tmp);
+Cu.import("resource:///modules/sessionstore/TabStateCache.jsm", tmp);
+let {SessionFile, TabStateCache} = tmp;
+
+// Shortcuts for histogram names
+let Keys = {};
+for (let k of ["HISTORY", "FORMDATA", "OPEN_WINDOWS", "CLOSED_WINDOWS", "CLOSED_TABS_IN_OPEN_WINDOWS", "DOM_STORAGE", "POSTDATA"]) {
+  Keys[k] = "FX_SESSION_RESTORE_TOTAL_" + k + "_SIZE_BYTES";
+}
+
+function lt(a, b, message) {
+  isnot(a, undefined, message + " (sanity check)");
+  isnot(b, undefined, message + " (sanity check)");
+  ok(a < b, message + " ( " + a + " < " + b + ")");
+}
+function gt(a, b, message) {
+  isnot(a, undefined, message + " (sanity check)");
+  isnot(b, undefined, message + " (sanity check)");
+  ok(a > b, message + " ( " + a + " > " + b + ")");
+}
+
+add_task(function init() {
+  for (let i = ss.getClosedWindowCount() - 1; i >= 0; --i) {
+    ss.forgetClosedWindow(i);
+  }
+  for (let i = ss.getClosedTabCount(window) - 1; i >= 0; --i) {
+    ss.forgetClosedTab(window, i);
+  }
+});
+
+/**
+ * Test that Telemetry collection doesn't cause any error.
+ */
+add_task(function() {
+  info("Checking a little bit of consistency");
+  let statistics = yield promiseStats();
+
+  for (let k of Object.keys(statistics)) {
+    let data = statistics[k];
+    info("Data for " + k + ": " + data);
+    if (Array.isArray(data)) {
+      ok(data.every(x => x >= 0), "Data for " + k + " is >= 0");
+    } else {
+      ok(data >= 0, "Data for " + k + " is >= 0");
+    }
+  }
+});
+
+/**
+ * Test HISTORY key.
+ */
+add_task(function history() {
+  let KEY = Keys.HISTORY;
+  let tab = gBrowser.addTab("http://example.org:80/?");
+  yield promiseBrowserLoaded(tab.linkedBrowser);
+  try {
+    SyncHandlers.get(tab.linkedBrowser).flush();
+    let statistics = yield promiseStats();
+
+    info("Now changing history");
+    tab.linkedBrowser.contentWindow.history.pushState({foo:1}, "ref");
+    SyncHandlers.get(tab.linkedBrowser).flush();
+    let statistics2 = yield promiseStats();
+
+    // We have changed history, so it must have increased
+    isnot(statistics[KEY], undefined, "Key was defined");
+    isnot(statistics2[KEY], undefined, "Key is still defined");
+    gt(statistics2[KEY], statistics[KEY], "The total size of HISTORY has increased");
+
+// Almost nothing else should
+    for (let k of ["FORMDATA", "DOM_STORAGE", "CLOSED_WINDOWS", "CLOSED_TABS_IN_OPEN_WINDOWS"]) {
+      is(statistics2[Keys[k]], statistics[Keys[k]], "The total size of " + k + " has not increased");
+    }
+  } finally {
+    if (tab) {
+      gBrowser.removeTab(tab);
+    }
+  }
+});
+
+/**
+ * Test CLOSED_TABS_IN_OPEN_WINDOWS key.
+ */
+add_task(function close_tab() {
+  let KEY = Keys.CLOSED_TABS_IN_OPEN_WINDOWS;
+  let tab = gBrowser.addTab("http://example.org:80/?close_tab");
+  yield promiseBrowserLoaded(tab.linkedBrowser);
+  try {
+    SyncHandlers.get(tab.linkedBrowser).flush();
+    let statistics = yield promiseStats();
+
+    info("Now closing a tab");
+    gBrowser.removeTab(tab);
+    tab = null;
+    let statistics2 = yield promiseStats();
+
+    isnot(statistics[KEY], undefined, "Key was defined");
+    isnot(statistics2[KEY], undefined, "Key is still defined");
+    gt(statistics2[KEY], statistics[KEY], "The total size of CLOSED_TABS_IN_OPEN_WINDOWS has increased");
+
+    // Almost nothing else should change
+    for (let k of ["FORMDATA", "DOM_STORAGE", "CLOSED_WINDOWS"]) {
+      is(statistics2[Keys[k]], statistics[Keys[k]], "The total size of " + k + " has not increased");
+    }
+
+  } finally {
+    if (tab) {
+      gBrowser.removeTab(tab);
+    }
+  }
+});
+
+/**
+ * Test OPEN_WINDOWS key.
+ */
+add_task(function open_window() {
+  let KEY = Keys.OPEN_WINDOWS;
+  let win;
+  try {
+    let statistics = yield promiseStats();
+    win = yield promiseNewWindowLoaded("http://example.org:80/?open_window");
+    let statistics2 = yield promiseStats();
+
+    isnot(statistics[KEY], undefined, "Key was defined");
+    isnot(statistics2[KEY], undefined, "Key is still defined");
+    gt(statistics2[KEY], statistics[KEY], "The total size of OPEN_WINDOWS has increased");
+
+    // Almost nothing else should change
+    for (let k of ["FORMDATA", "DOM_STORAGE", "CLOSED_WINDOWS", "CLOSED_TABS_IN_OPEN_WINDOWS"]) {
+      is(statistics2[Keys[k]], statistics[Keys[k]], "The total size of " + k + " has not increased");
+    }
+
+  } finally {
+    if (win) {
+      yield promiseWindowClosed(win);
+    }
+  }
+});
+
+/**
+ * Test CLOSED_WINDOWS key.
+ */
+add_task(function close_window() {
+  let KEY = Keys.CLOSED_WINDOWS;
+  let win = yield promiseNewWindowLoaded("http://example.org:80/?close_window");
+
+  // We need to add something to the window, otherwise it won't be saved
+  let tab = win.gBrowser.addTab("http://example.org:80/?close_tab");
+  yield promiseBrowserLoaded(tab.linkedBrowser);
+  try {
+    let statistics = yield promiseStats();
+    yield promiseWindowClosed(win);
+    win = null;
+    let statistics2 = yield promiseStats();
+
+    isnot(statistics[KEY], undefined, "Key was defined");
+    isnot(statistics2[KEY], undefined, "Key is still defined");
+    gt(statistics2[KEY], statistics[KEY], "The total size of CLOSED_WINDOWS has increased");
+    lt(statistics2[Keys.OPEN_WINDOWS], statistics[Keys.OPEN_WINDOWS], "The total size of OPEN_WINDOWS has decreased");
+
+    // Almost nothing else should change
+    for (let k of ["FORMDATA", "DOM_STORAGE", "CLOSED_TABS_IN_OPEN_WINDOWS"]) {
+      is(statistics2[Keys[k]], statistics[Keys[k]], "The total size of " + k + " has not increased");
+    }
+
+  } finally {
+    if (win) {
+      yield promiseWindowClosed(win);
+    }
+  }
+});
+
+
+/**
+ * Test DOM_STORAGE key.
+ */
+add_task(function dom_storage() {
+  let KEY = Keys.DOM_STORAGE;
+  let tab = gBrowser.addTab("http://example.org:80/?dom_storage");
+  yield promiseBrowserLoaded(tab.linkedBrowser);
+  try {
+    SyncHandlers.get(tab.linkedBrowser).flush();
+    let statistics = yield promiseStats();
+
+    info("Now adding some storage");
+    yield modifySessionStorage(tab.linkedBrowser, {foo: "bar"});
+    SyncHandlers.get(tab.linkedBrowser).flush();
+
+    let statistics2 = yield promiseStats();
+
+    isnot(statistics[KEY], undefined, "Key was defined");
+    isnot(statistics2[KEY], undefined, "Key is still defined");
+    gt(statistics2[KEY], statistics[KEY], "The total size of DOM_STORAGE has increased");
+
+    // Almost nothing else should change
+    for (let k of ["CLOSED_TABS_IN_OPEN_WINDOWS", "FORMDATA", "CLOSED_WINDOWS"]) {
+      is(statistics2[Keys[k]], statistics[Keys[k]], "The total size of " + k + " has not increased");
+    }
+
+  } finally {
+    if (tab) {
+      gBrowser.removeTab(tab);
+    }
+  }
+});
+
+/**
+ * Test FORMDATA key.
+ */
+add_task(function formdata() {
+  let KEY = Keys.FORMDATA;
+  let tab = gBrowser.addTab("data:text/html;charset=utf-8,<input%20id='input'>");
+  yield promiseBrowserLoaded(tab.linkedBrowser);
+  try {
+    SyncHandlers.get(tab.linkedBrowser).flush();
+    let statistics = yield promiseStats();
+
+    info("Now changing form data");
+
+    yield modifyFormData(tab.linkedBrowser, {input: "This is some form data "});
+    SyncHandlers.get(tab.linkedBrowser).flush();
+    TabStateCache.delete(tab.linkedBrowser);
+
+    let statistics2 = yield promiseStats();
+
+    isnot(statistics[KEY], undefined, "Key was defined");
+    isnot(statistics2[KEY], undefined, "Key is still defined");
+    gt(statistics2[KEY], statistics[KEY], "The total size of FORMDATA has increased");
+
+    // Almost nothing else should
+    for (let k of ["DOM_STORAGE", "CLOSED_WINDOWS", "CLOSED_TABS_IN_OPEN_WINDOWS"]) {
+      is(statistics2[Keys[k]], statistics[Keys[k]], "The total size of " + k + " has not increased");
+    }
+  } finally {
+    if (tab) {
+      gBrowser.removeTab(tab);
+    }
+  }
+});
+
+
+/**
+ * Get the latest statistics.
+ */
+function promiseStats() {
+  let state = ss.getBrowserState();
+  info("Stats: " + state);
+  return SessionFile.gatherTelemetry(state);
+}
+
+
+function modifySessionStorage(browser, data) {
+  browser.messageManager.sendAsyncMessage("ss-test:modifySessionStorage", data);
+  return promiseContentMessage(browser, "ss-test:MozStorageChanged");
+}
+
+function modifyFormData(browser, data) {
+  browser.messageManager.sendAsyncMessage("ss-test:modifyFormData", data);
+  return promiseContentMessage(browser, "ss-test:modifyFormData:done");
+}
+
--- a/browser/components/sessionstore/test/content.js
+++ b/browser/components/sessionstore/test/content.js
@@ -34,16 +34,23 @@ addMessageListener("ss-test:modifySessio
 });
 
 addMessageListener("ss-test:modifySessionStorage2", function (msg) {
   for (let key of Object.keys(msg.data)) {
     content.frames[0].sessionStorage[key] = msg.data[key];
   }
 });
 
+addMessageListener("ss-test:modifyFormData", function (msg) {
+  for (let id of Object.keys(msg.data)) {
+    content.document.getElementById(id).value = msg.data[id];
+  }
+  sendSyncMessage("ss-test:modifyFormData:done");
+});
+
 addMessageListener("ss-test:purgeDomainData", function ({data: domain}) {
   Services.obs.notifyObservers(null, "browser:purge-domain-data", domain);
   content.setTimeout(() => sendAsyncMessage("ss-test:purgeDomainData"));
 });
 
 addMessageListener("ss-test:getStyleSheets", function (msg) {
   let sheets = content.document.styleSheets;
   let titles = Array.map(sheets, ss => [ss.title, ss.disabled]);
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -612,19 +612,19 @@
 @BINPATH@/libGLESv2.dll
 @BINPATH@/@MOZ_D3DCOMPILER_DLL@
 #endif
 
 ; [Browser Chrome Files]
 @BINPATH@/browser/chrome.manifest
 @BINPATH@/browser/chrome/browser@JAREXT@
 @BINPATH@/browser/chrome/browser.manifest
-#ifdef NIGHTLY_BUILD
 @BINPATH@/browser/chrome/pdfjs.manifest
 @BINPATH@/browser/chrome/pdfjs/*
+#ifdef NIGHTLY_BUILD
 @BINPATH@/browser/chrome/shumway.manifest
 @BINPATH@/browser/chrome/shumway/*
 #endif
 @BINPATH@/browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf
 @BINPATH@/browser/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/icon.png
 @BINPATH@/chrome/toolkit@JAREXT@
 @BINPATH@/chrome/toolkit.manifest
 @BINPATH@/chrome/recording.manifest
@@ -840,19 +840,19 @@ bin/libfreebl_32int64_3.so
 @BINPATH@/metro/chrome/browser.manifest
 @BINPATH@/metro/chrome/chrome@JAREXT@
 @BINPATH@/metro/chrome/chrome.manifest
 @BINPATH@/metro/chrome/@AB_CD@@JAREXT@
 @BINPATH@/metro/chrome/@AB_CD@.manifest
 #ifdef NIGHTLY_BUILD
 @BINPATH@/metro/chrome/shumway.manifest
 @BINPATH@/metro/chrome/shumway/*
-#endif
 @BINPATH@/metro/chrome/pdfjs.manifest
 @BINPATH@/metro/chrome/pdfjs/*
+#endif
 @BINPATH@/metro/components
 @BINPATH@/metro/defaults
 @BINPATH@/metro/modules
 #endif
 
 @BINPATH@/components/DataStore.manifest
 @BINPATH@/components/DataStoreService.js
 @BINPATH@/components/dom_datastore.xpt
--- a/browser/metro/base/content/browser-ui.js
+++ b/browser/metro/base/content/browser-ui.js
@@ -363,22 +363,26 @@ var BrowserUI = {
     // Make sure we're online before attempting to load
     Util.forceOnline();
 
     BrowserUI.showContent(aURI);
     Browser.selectedBrowser.focus();
 
     Task.spawn(function() {
       let postData = {};
+      let webNav = Ci.nsIWebNavigation;
+      let flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
+                  webNav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
       aURI = yield Browser.getShortcutOrURI(aURI, postData);
-      Browser.loadURI(aURI, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP, postData: postData });
+      Browser.loadURI(aURI, { flags: flags, postData: postData });
 
       // Delay doing the fixup so the raw URI is passed to loadURIWithFlags
       // and the proper third-party fixup can be done
-      let fixupFlags = Ci.nsIURIFixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
+      let fixupFlags = Ci.nsIURIFixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP | 
+                       Ci.nsIURIFixup.FIXUP_FLAG_FIX_SCHEME_TYPOS;
       let uri = gURIFixup.createFixupURI(aURI, fixupFlags);
       gHistSvc.markPageAsTyped(uri);
 
       BrowserUI._titleChanged(Browser.selectedBrowser);
     });
   },
 
   doOpenSearch: function doOpenSearch(aName) {
--- a/browser/metro/base/content/browser.js
+++ b/browser/metro/base/content/browser.js
@@ -167,17 +167,20 @@ var Browser = {
 
     Task.spawn(function() {
       // Activation URIs come from protocol activations, secondary tiles, and file activations
       let activationURI = yield this.getShortcutOrURI(Services.metro.activationURI);
 
       let self = this;
       function loadStartupURI() {
         if (activationURI) {
-          self.addTab(activationURI, true, null, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP });
+          let webNav = Ci.nsIWebNavigation;
+          let flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
+                      webNav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
+          self.addTab(activationURI, true, null, { flags: flags });
         } else {
           let uri = commandURL || Browser.getHomePage();
           self.addTab(uri, true);
         }
       }
 
       // Should we restore the previous session (crash or some other event)
       let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -1266,16 +1266,17 @@ nsScriptSecurityManager::CheckLoadURIStr
     // Note: This needs to stay in sync with the nsIURIFixup api.
     nsCOMPtr<nsIURIFixup> fixup = do_GetService(NS_URIFIXUP_CONTRACTID);
     if (!fixup) {
         return rv;
     }
 
     uint32_t flags[] = {
         nsIURIFixup::FIXUP_FLAG_NONE,
+        nsIURIFixup::FIXUP_FLAG_FIX_SCHEME_TYPOS,
         nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP,
         nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI,
         nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP |
         nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI
     };
 
     for (uint32_t i = 0; i < ArrayLength(flags); ++i) {
         rv = fixup->CreateFixupURI(aTargetURIStr, flags[i], nullptr,
--- a/content/base/public/nsIFrameLoader.idl
+++ b/content/base/public/nsIFrameLoader.idl
@@ -9,16 +9,17 @@ interface nsFrameLoader;
 interface nsIDocShell;
 interface nsIURI;
 interface nsIFrame;
 interface nsSubDocumentFrame;
 interface nsIMessageSender;
 interface nsIVariant;
 interface nsIDOMElement;
 interface nsITabParent;
+interface nsILoadContext;
 
 typedef unsigned long long nsContentViewId;
 
 /**
  * These interfaces do *not* scroll or scale the content document;
  * instead they set a "goal" scroll/scale wrt the current content
  * view.  When the content document is painted, the scroll*
  * attributes are used to set a compensating transform.  If the
@@ -106,31 +107,38 @@ interface nsIContentViewManager : nsISup
                          [retval, array, size_is(aLength)] out nsIContentView aResult);
 
   /**
    * The root content view.
    */
   readonly attribute nsIContentView rootContentView;
 };
 
-[scriptable, builtinclass, uuid(5b9949dc-56f1-47b6-b6d2-3785bb90ed6d)]
+[scriptable, builtinclass, uuid(4c9f91c0-7a5d-11e3-981f-0800200c9a66)]
 interface nsIFrameLoader : nsISupports
 {
   /**
    * Get the docshell from the frame loader.
    */
   readonly attribute nsIDocShell docShell;
 
   /**
    * Get this frame loader's TabParent, if it has a remote frame.  Otherwise,
    * returns null.
    */
   readonly attribute nsITabParent tabParent;
 
   /**
+   * Get an nsILoadContext for the top-level docshell. For remote
+   * frames, a shim is returned that contains private browsing and app
+   * information.
+   */
+  readonly attribute nsILoadContext loadContext;
+
+  /**
    * Start loading the frame. This method figures out what to load
    * from the owner content in the frame loader.
    */
   void loadFrame();
 
   /**
    * Loads the specified URI in this frame. Behaves identically to loadFrame,
    * except that this method allows specifying the URI to load.
--- a/content/base/src/moz.build
+++ b/content/base/src/moz.build
@@ -192,25 +192,25 @@ MSVC_ENABLE_PGO = True
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
     '/caps/include',
     '/content/events/src',
     '/content/html/content/src',
     '/content/html/document/src',
-    '/content/xbl/src',
     '/content/xml/content/src',
     '/content/xml/document/src',
     '/content/xul/content/src',
     '/content/xul/document/src',
     '/docshell/base',
     '/dom/base',
     '/dom/ipc',
     '/dom/workers',
+    '/dom/xbl',
     '/dom/xslt/xpath',
     '/image/src',
     '/js/ipc',
     '/js/xpconnect/src',
     '/js/xpconnect/wrappers',
     '/layout/base',
     '/layout/generic',
     '/layout/style',
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -218,17 +218,17 @@ MarkContentViewer(nsIContentViewer* aVie
     }
     nsPIDOMWindow* outer = doc->GetWindow();
     if (outer) {
       outer->MarkUncollectableForCCGeneration(nsCCUncollectableMarker::sGeneration);
     }
   }
 }
 
-void MarkDocShell(nsIDocShellTreeNode* aNode, bool aCleanupJS,
+void MarkDocShell(nsIDocShellTreeItem* aNode, bool aCleanupJS,
                   bool aPrepareForCC);
 
 void
 MarkSHEntry(nsISHEntry* aSHEntry, bool aCleanupJS, bool aPrepareForCC)
 {
   if (!aSHEntry) {
     return;
   }
@@ -251,17 +251,17 @@ MarkSHEntry(nsISHEntry* aSHEntry, bool a
     nsCOMPtr<nsISHEntry> childEntry;
     shCont->GetChildAt(i, getter_AddRefs(childEntry));
     MarkSHEntry(childEntry, aCleanupJS, aPrepareForCC);
   }
   
 }
 
 void
-MarkDocShell(nsIDocShellTreeNode* aNode, bool aCleanupJS, bool aPrepareForCC)
+MarkDocShell(nsIDocShellTreeItem* aNode, bool aCleanupJS, bool aPrepareForCC)
 {
   nsCOMPtr<nsIDocShell> shell = do_QueryInterface(aNode);
   if (!shell) {
     return;
   }
 
   nsCOMPtr<nsIContentViewer> cview;
   shell->GetContentViewer(getter_AddRefs(cview));
@@ -294,18 +294,17 @@ void
 MarkWindowList(nsISimpleEnumerator* aWindowList, bool aCleanupJS,
                bool aPrepareForCC)
 {
   nsCOMPtr<nsISupports> iter;
   while (NS_SUCCEEDED(aWindowList->GetNext(getter_AddRefs(iter))) &&
          iter) {
     nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(iter);
     if (window) {
-      nsCOMPtr<nsIDocShellTreeNode> rootDocShell =
-        do_QueryInterface(window->GetDocShell());
+      nsCOMPtr<nsIDocShell> rootDocShell = window->GetDocShell();
 
       MarkDocShell(rootDocShell, aCleanupJS, aPrepareForCC);
     }
   }
 }
 
 nsresult
 nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic,
@@ -374,28 +373,26 @@ nsCCUncollectableMarker::Observe(nsISupp
   nsCOMPtr<nsIAppShellService> appShell = 
     do_GetService(NS_APPSHELLSERVICE_CONTRACTID);
   if (appShell) {
     nsCOMPtr<nsIXULWindow> hw;
     appShell->GetHiddenWindow(getter_AddRefs(hw));
     if (hw) {
       nsCOMPtr<nsIDocShell> shell;
       hw->GetDocShell(getter_AddRefs(shell));
-      nsCOMPtr<nsIDocShellTreeNode> shellTreeNode = do_QueryInterface(shell);
-      MarkDocShell(shellTreeNode, cleanupJS, prepareForCC);
+      MarkDocShell(shell, cleanupJS, prepareForCC);
     }
     bool hasHiddenPrivateWindow = false;
     appShell->GetHasHiddenPrivateWindow(&hasHiddenPrivateWindow);
     if (hasHiddenPrivateWindow) {
       appShell->GetHiddenPrivateWindow(getter_AddRefs(hw));
       if (hw) {
         nsCOMPtr<nsIDocShell> shell;
         hw->GetDocShell(getter_AddRefs(shell));
-        nsCOMPtr<nsIDocShellTreeNode> shellTreeNode = do_QueryInterface(shell);
-        MarkDocShell(shellTreeNode, cleanupJS, prepareForCC);
+        MarkDocShell(shell, cleanupJS, prepareForCC);
       }
     }
   }
 
 #ifdef MOZ_XUL
   nsXULPrototypeCache* xulCache = nsXULPrototypeCache::GetInstance();
   if (xulCache) {
     xulCache->MarkInCCGeneration(sGeneration);
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -5876,24 +5876,23 @@ nsContentUtils::FlushLayoutForTree(nsIDO
 
     nsCOMPtr<nsIDOMDocument> domDoc;
     aWindow->GetDocument(getter_AddRefs(domDoc));
     nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
     if (doc) {
         doc->FlushPendingNotifications(Flush_Layout);
     }
 
-    nsCOMPtr<nsIDocShellTreeNode> node =
-        do_QueryInterface(piWin->GetDocShell());
-    if (node) {
+    nsCOMPtr<nsIDocShell> docShell = piWin->GetDocShell();
+    if (docShell) {
         int32_t i = 0, i_end;
-        node->GetChildCount(&i_end);
+        docShell->GetChildCount(&i_end);
         for (; i < i_end; ++i) {
             nsCOMPtr<nsIDocShellTreeItem> item;
-            node->GetChildAt(i, getter_AddRefs(item));
+            docShell->GetChildAt(i, getter_AddRefs(item));
             nsCOMPtr<nsIDOMWindow> win = do_GetInterface(item);
             if (win) {
                 FlushLayoutForTree(win);
             }
         }
     }
 }
 
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -708,17 +708,17 @@ SetTreeOwnerAndChromeEventHandlerOnDocsh
  * @param aParentNode if non-null, the docshell we should be added as a child to
  *
  * @return whether aItem is top-level content
  */
 bool
 nsFrameLoader::AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
                                       nsIDocShellTreeOwner* aOwner,
                                       int32_t aParentType,
-                                      nsIDocShellTreeNode* aParentNode)
+                                      nsIDocShell* aParentNode)
 {
   NS_PRECONDITION(aItem, "Must have docshell treeitem");
   NS_PRECONDITION(mOwnerContent, "Must have owning content");
   
   nsAutoString value;
   bool isContent = false;
   mOwnerContent->GetAttr(kNameSpaceID_None, TypeAttrName(), value);
 
@@ -1566,19 +1566,18 @@ nsFrameLoader::MaybeCreateDocShell()
   }
 
   if (doc->IsResourceDoc() || !doc->IsActive()) {
     // Don't allow subframe loads in resource documents, nor
     // in non-active documents.
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  nsCOMPtr<nsISupports> container =
-    doc->GetContainer();
-  nsCOMPtr<nsIWebNavigation> parentAsWebNav = do_QueryInterface(container);
+  nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell();
+  nsCOMPtr<nsIWebNavigation> parentAsWebNav = do_QueryInterface(docShell);
   NS_ENSURE_STATE(parentAsWebNav);
 
   // Create the docshell...
   mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
 
   // Apply sandbox flags even if our owner is not an iframe, as this copies
   // flags from our owning content's owning document.
@@ -1610,63 +1609,51 @@ nsFrameLoader::MaybeCreateDocShell()
       mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, frameName);
     }
   }
 
   if (!frameName.IsEmpty()) {
     mDocShell->SetName(frameName);
   }
 
-  // If our container is a web-shell, inform it that it has a new
-  // child. If it's not a web-shell then some things will not operate
-  // properly.
-
-  nsCOMPtr<nsIDocShellTreeNode> parentAsNode(do_QueryInterface(parentAsWebNav));
-  if (parentAsNode) {
-    // Note: This logic duplicates a lot of logic in
-    // nsSubDocumentFrame::AttributeChanged.  We should fix that.
-
-    nsCOMPtr<nsIDocShellTreeItem> parentAsItem =
-      do_QueryInterface(parentAsNode);
-
-    int32_t parentType;
-    parentAsItem->GetItemType(&parentType);
-
-    // XXXbz why is this in content code, exactly?  We should handle
-    // this some other way.....  Not sure how yet.
-    nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
-    parentAsItem->GetTreeOwner(getter_AddRefs(parentTreeOwner));
-    NS_ENSURE_STATE(parentTreeOwner);
-    mIsTopLevelContent =
-      AddTreeItemToTreeOwner(mDocShell, parentTreeOwner, parentType,
-                             parentAsNode);
-
-    // Make sure all shells have links back to the content element
-    // in the nearest enclosing chrome shell.
-    nsCOMPtr<nsIDOMEventTarget> chromeEventHandler;
-
-    if (parentType == nsIDocShellTreeItem::typeChrome) {
-      // Our parent shell is a chrome shell. It is therefore our nearest
-      // enclosing chrome shell.
-
-      chromeEventHandler = do_QueryInterface(mOwnerContent);
-      NS_ASSERTION(chromeEventHandler,
-                   "This mContent should implement this.");
-    } else {
-      nsCOMPtr<nsIDocShell> parentShell(do_QueryInterface(parentAsNode));
-
-      // Our parent shell is a content shell. Get the chrome event
-      // handler from it and use that for our shell as well.
-
-      parentShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
-    }
-
-    mDocShell->SetChromeEventHandler(chromeEventHandler);
+  // Inform our docShell that it has a new child.
+  // Note: This logic duplicates a lot of logic in
+  // nsSubDocumentFrame::AttributeChanged.  We should fix that.
+
+  int32_t parentType;
+  docShell->GetItemType(&parentType);
+
+  // XXXbz why is this in content code, exactly?  We should handle
+  // this some other way.....  Not sure how yet.
+  nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
+  docShell->GetTreeOwner(getter_AddRefs(parentTreeOwner));
+  NS_ENSURE_STATE(parentTreeOwner);
+  mIsTopLevelContent =
+    AddTreeItemToTreeOwner(mDocShell, parentTreeOwner, parentType, docShell);
+
+  // Make sure all shells have links back to the content element
+  // in the nearest enclosing chrome shell.
+  nsCOMPtr<nsIDOMEventTarget> chromeEventHandler;
+
+  if (parentType == nsIDocShellTreeItem::typeChrome) {
+    // Our parent shell is a chrome shell. It is therefore our nearest
+    // enclosing chrome shell.
+
+    chromeEventHandler = do_QueryInterface(mOwnerContent);
+    NS_ASSERTION(chromeEventHandler,
+                 "This mContent should implement this.");
+  } else {
+    // Our parent shell is a content shell. Get the chrome event
+    // handler from it and use that for our shell as well.
+
+    docShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
   }
 
+  mDocShell->SetChromeEventHandler(chromeEventHandler);
+
   // This is nasty, this code (the do_GetInterface(mDocShell) below)
   // *must* come *after* the above call to
   // mDocShell->SetChromeEventHandler() for the global window to get
   // the right chrome event handler.
 
   // Tell the window about the frame that hosts it.
   nsCOMPtr<Element> frame_element = mOwnerContent;
   NS_ASSERTION(frame_element, "frame loader owner element not a DOM element!");
@@ -2686,8 +2673,23 @@ nsFrameLoader::GetVisible(bool* aVisible
 
 NS_IMETHODIMP
 nsFrameLoader::GetTabParent(nsITabParent** aTabParent)
 {
   nsCOMPtr<nsITabParent> tp = mRemoteBrowser;
   tp.forget(aTabParent);
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsFrameLoader::GetLoadContext(nsILoadContext** aLoadContext)
+{
+  nsCOMPtr<nsILoadContext> loadContext;
+  if (mRemoteBrowser) {
+    loadContext = mRemoteBrowser->GetLoadContext();
+  } else {
+    nsCOMPtr<nsIDocShell> docShell;
+    GetDocShell(getter_AddRefs(docShell));
+    loadContext = do_GetInterface(docShell);
+  }
+  loadContext.forget(aLoadContext);
+  return NS_OK;
+}
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -27,17 +27,16 @@
 class nsIURI;
 class nsSubDocumentFrame;
 class nsView;
 class nsIInProcessContentFrameMessageManager;
 class AutoResetInShow;
 class nsITabParent;
 class nsIDocShellTreeItem;
 class nsIDocShellTreeOwner;
-class nsIDocShellTreeNode;
 class mozIApplication;
 
 namespace mozilla {
 namespace dom {
 class ContentParent;
 class PBrowserParent;
 class TabParent;
 struct StructuredCloneData;
@@ -383,17 +382,17 @@ private:
 
   // Tell the remote browser that it's now "virtually visible"
   bool ShowRemoteFrame(const nsIntSize& size,
                        nsSubDocumentFrame *aFrame = nullptr);
 
   bool AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
                               nsIDocShellTreeOwner* aOwner,
                               int32_t aParentType,
-                              nsIDocShellTreeNode* aParentNode);
+                              nsIDocShell* aParentNode);
 
   nsIAtom* TypeAttrName() const {
     return mOwnerContent->IsXUL() ? nsGkAtoms::type : nsGkAtoms::mozframetype;
   }
 
   // Update the permission manager's app-id refcount based on mOwnerContent's
   // own-or-containing-app.
   void ResetPermissionManagerStatus();
--- a/content/base/test/csp/test_CSP.html
+++ b/content/base/test/csp/test_CSP.html
@@ -1,29 +1,26 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test for Content Security Policy Connections</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
-
-  
 </div>
-
 <iframe style="width:200px;height:200px;" id='cspframe'></iframe>
 <iframe style="width:200px;height:200px;" id='cspframe2'></iframe>
 <script class="testbody" type="text/javascript">
 
 var path = "/tests/content/base/test/csp/";
 
-// These are test results: -1 means it hasn't run, 
+// These are test results: -1 means it hasn't run,
 // true/false is the pass/fail result.
 window.tests = {
   img_good: -1,
   img_bad: -1,
   style_good: -1,
   style_bad: -1,
   frame_good: -1,
   frame_bad: -1,
@@ -50,61 +47,58 @@ window.tests = {
   media_spec_compliant_good: -1,
   media_spec_compliant_bad: -1,
   font_spec_compliant_good: -1,
   font_spec_compliant_bad: -1,
   object_spec_compliant_good: -1,
   object_spec_compliant_bad: -1,
 };
 
-
-// This is used to watch the blocked data bounce off CSP and allowed data 
+// This is used to watch the blocked data bounce off CSP and allowed data
 // get sent out to the wire.
 function examiner() {
   SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
-  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+  SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
 }
 examiner.prototype  = {
   observe: function(subject, topic, data) {
-    // subject should be an nsURI, and should be either allowed or blocked.
-    if (!SpecialPowers.can_QI(subject))
-      return;
-      
     var testpat = new RegExp("testid=([a-z0-9_]+)");
 
     //_good things better be allowed!
     //_bad things better be stopped!
 
-    if (topic === "http-on-modify-request") {
-      //these things were allowed by CSP
-      var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
-      if (!testpat.test(asciiSpec)) return;
-      var testid = testpat.exec(asciiSpec)[1];
+    // This is a special observer topic that is proxied from
+    // http-on-modify-request in the parent process to inform us when a URI is
+    // loaded
+    if (topic === "specialpowers-http-notify-request") {
+      var uri = data;
+      if (!testpat.test(uri)) return;
+      var testid = testpat.exec(uri)[1];
 
       window.testResult(testid,
                         /_good/.test(testid),
-                        asciiSpec + " allowed by csp");
+                        uri + " allowed by csp");
     }
 
-    if(topic === "csp-on-violate-policy") {
-      //these were blocked... record that they were blocked
+    if (topic === "csp-on-violate-policy") {
+      // these were blocked... record that they were blocked
       var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIURI"), "asciiSpec");
       if (!testpat.test(asciiSpec)) return;
       var testid = testpat.exec(asciiSpec)[1];
       window.testResult(testid,
                         /_bad/.test(testid),
                         asciiSpec + " blocked by \"" + data + "\"");
     }
   },
 
-  // must eventually call this to remove the listener, 
+  // must eventually call this to remove the listener,
   // or mochitests might get borked.
   remove: function() {
     SpecialPowers.removeObserver(this, "csp-on-violate-policy");
-    SpecialPowers.removeObserver(this, "http-on-modify-request");
+    SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
   }
 }
 
 window.examiner = new examiner();
 
 window.testResult = function(testname, result, msg) {
   //test already complete.... forget it... remember the first result.
   if (window.tests[testname] != -1)
@@ -121,17 +115,23 @@ window.testResult = function(testname, r
   // ... otherwise, finish
   window.examiner.remove();
   SimpleTest.finish();
 }
 
 SimpleTest.waitForExplicitFinish();
 
 SpecialPowers.pushPrefEnv(
-  {'set':[["security.csp.speccompliant", true]]},
+  {'set':[["security.csp.speccompliant", true],
+          // This defaults to 0 ("preload none") on mobile (B2G/Android), which
+          // blocks loading the resource until the user interacts with a
+          // corresponding widget, which breaks the media_* tests. We set it
+          // back to the default used by desktop Firefox to get consistent
+          // behavior.
+          ["media.preload.default", 2]]},
     function() {
       // save this for last so that our listeners are registered.
       // ... this loads the testbed of good and bad requests.
       document.getElementById('cspframe').src = 'file_CSP_main.html';
       document.getElementById('cspframe2').src = 'file_CSP_main_spec_compliant.html';
     });
 </script>
 </pre>
--- a/content/base/test/csp/test_CSP_bug909029.html
+++ b/content/base/test/csp/test_CSP_bug909029.html
@@ -21,32 +21,26 @@ window.tests = {
   starInlineStyleAllowed: -1,
   starInlineScriptBlocked: -1,
   noneInlineStyleAllowed: -1,
   noneInlineScriptBlocked: -1
 }
 
 function examiner() {
   SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
-  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+  SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
 }
 examiner.prototype  = {
   observe: function(subject, topic, data) {
-    // subject should be an nsURI, and should be either allowed or blocked.
-    if (!SpecialPowers.can_QI(subject))
-      return;
-
     var testpat = new RegExp("testid=([a-zA-Z]+)");
 
-    if (topic === "http-on-modify-request") {
-      //these things were allowed by CSP
-      var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
-      if (!testpat.test(asciiSpec))
-        return;
-      var testid = testpat.exec(asciiSpec)[1];
+    if (topic === "specialpowers-http-notify-request") {
+      var uri = data;
+      if (!testpat.test(uri)) return;
+      var testid = testpat.exec(uri)[1];
       window.testResult(testid,
                         /Loaded/.test(testid),
                         "resource loaded");
     }
 
     if(topic === "csp-on-violate-policy") {
       // these were blocked... record that they were blocked
       // try because the subject could be an nsIURI or an nsISupportsCString
@@ -65,17 +59,17 @@ examiner.prototype  = {
       }
     }
   },
 
   // must eventually call this to remove the listener,
   // or mochitests might get borked.
   remove: function() {
     SpecialPowers.removeObserver(this, "csp-on-violate-policy");
-    SpecialPowers.removeObserver(this, "http-on-modify-request");
+    SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
   }
 }
 
 window.examiner = new examiner();
 
 window.testResult = function(testname, result, msg) {
   //dump("in testResult: testname = " + testname + "\n");
 
--- a/content/base/test/csp/test_CSP_bug916446.html
+++ b/content/base/test/csp/test_CSP_bug916446.html
@@ -14,34 +14,30 @@
 <iframe style="width:200px;height:200px;" id='testframe'></iframe>
 
 <script class="testbody" type="text/javascript">
 
 // This is used to watch the blocked data bounce off CSP and allowed data
 // get sent out to the wire.
 function examiner() {
   SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
-  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+  SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
 }
 examiner.prototype  = {
   completedTests: 0,
   totalTests: 4,
 
   observe: function(subject, topic, data) {
-    // subject should be an nsURI, and should be either allowed or blocked.
-    if (!SpecialPowers.can_QI(subject))
-      return;
-
     var testpat = new RegExp("testid=([a-z0-9_]+)");
 
-    if (topic === "http-on-modify-request") {
-      //these things were allowed by CSP
-      var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
-      if (!testpat.test(asciiSpec)) return;
-      var testid = testpat.exec(asciiSpec)[1];
+    if (topic === "specialpowers-http-notify-request") {
+      // these things were allowed by CSP
+      var uri = data;
+      if (!testpat.test(uri)) return;
+      var testid = testpat.exec(uri)[1];
       if (testid === "img_bad") {
         // img_bad should be *allowed* because the policy is report-only
         ok(true, "Inline scripts should execute (because the policy is report-only)");
         this.completedTests++;
       }
     }
 
     if(topic === "csp-on-violate-policy") {
@@ -64,17 +60,17 @@ examiner.prototype  = {
       }
     }
   },
 
   // must eventually call this to remove the listener,
   // or mochitests might get borked.
   remove: function() {
     SpecialPowers.removeObserver(this, "csp-on-violate-policy");
-    SpecialPowers.removeObserver(this, "http-on-modify-request");
+    SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
   }
 }
 
 window.examiner = new examiner();
 
 function checkInlineScriptExecuted() {
   var green = 'rgb(0, 128, 0)';
   var black = 'rgb(0, 0, 0)';
--- a/content/base/test/csp/test_CSP_bug941404.html
+++ b/content/base/test/csp/test_CSP_bug941404.html
@@ -28,39 +28,35 @@ window.tests = {
 
 
 //csp related
 
 // This is used to watch the blocked data bounce off CSP and allowed data
 // get sent out to the wire.
 function examiner() {
   SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
-  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+  SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
 }
 
 examiner.prototype  = {
   observe: function(subject, topic, data) {
-    // subject should be an nsURI, and should be either allowed or blocked.
-    if (!SpecialPowers.can_QI(subject))
-      return;
-
     var testpat = new RegExp("testid=([a-z0-9_]+)");
 
     //_good things better be allowed!
     //_bad things better be stopped!
 
-    if (topic === "http-on-modify-request") {
+    if (topic === "specialpowers-http-notify-request") {
       //these things were allowed by CSP
-      var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
-      if (!testpat.test(asciiSpec)) return;
-      var testid = testpat.exec(asciiSpec)[1];
+      var uri = data;
+      if (!testpat.test(uri)) return;
+      var testid = testpat.exec(uri)[1];
 
       window.testResult(testid,
                         /_good/.test(testid),
-                        asciiSpec + " allowed by csp");
+                        uri + " allowed by csp");
     }
 
     if(topic === "csp-on-violate-policy") {
       //these were blocked... record that they were blocked
       var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIURI"), "asciiSpec");
       if (!testpat.test(asciiSpec)) return;
       var testid = testpat.exec(asciiSpec)[1];
       window.testResult(testid,
@@ -68,17 +64,17 @@ examiner.prototype  = {
                         asciiSpec + " blocked by \"" + data + "\"");
     }
   },
 
   // must eventually call this to remove the listener,
   // or mochitests might get borked.
   remove: function() {
     SpecialPowers.removeObserver(this, "csp-on-violate-policy");
-    SpecialPowers.removeObserver(this, "http-on-modify-request");
+    SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
   }
 }
 
 window.examiner = new examiner();
 
 window.testResult = function(testname, result, msg) {
   //test already complete.... forget it... remember the first result.
   if (window.tests[testname] != -1)
--- a/content/base/test/csp/test_CSP_evalscript.html
+++ b/content/base/test/csp/test_CSP_evalscript.html
@@ -1,34 +1,30 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test for Content Security Policy "no eval" base restriction</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
-
-  
 </div>
-
 <iframe style="width:100%;height:300px;" id='cspframe'></iframe>
 <iframe style="width:100%;height:300px;" id='cspframe2'></iframe>
 <iframe style="width:100%;height:300px;" id='cspframe3'></iframe>
 <script class="testbody" type="text/javascript">
 
 var path = "/tests/content/base/test/csp/";
 
 var evalScriptsThatRan = 0;
 var evalScriptsBlocked = 0;
 var evalScriptsTotal = 24;
 
-
 // called by scripts that run
 var scriptRan = function(shouldrun, testname, data) {
   evalScriptsThatRan++;
   ok(shouldrun, 'EVAL SCRIPT RAN: ' + testname + '(' + data + ')');
   checkTestResults();
 }
 
 // called when a script is blocked
--- a/content/base/test/csp/test_CSP_evalscript_getCRMFRequest.html
+++ b/content/base/test/csp/test_CSP_evalscript_getCRMFRequest.html
@@ -1,50 +1,45 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test for Content Security Policy "no eval" in crypto.getCRMFRequest()</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
-
-  
 </div>
-
 <iframe style="width:100%;height:300px;" id='cspframe'></iframe>
 <iframe style="width:100%;height:300px;" id='cspframe2'></iframe>
 <iframe style="width:100%;height:300px;" id='cspframe3'></iframe>
 <iframe style="width:100%;height:300px;" id='cspframe4'></iframe>
 <script class="testbody" type="text/javascript">
 
 var path = "/tests/content/base/test/csp/";
 
 var evalScriptsThatRan = 0;
 var evalScriptsBlocked = 0;
 var evalScriptsTotal = 4;
 
-
 // called by scripts that run
 var scriptRan = function(shouldrun, testname, data) {
   evalScriptsThatRan++;
   ok(shouldrun, 'EVAL SCRIPT RAN: ' + testname + '(' + data + ')');
   checkTestResults();
 }
 
 // called when a script is blocked
 var scriptBlocked = function(shouldrun, testname, data) {
   evalScriptsBlocked++;
   ok(!shouldrun, 'EVAL SCRIPT BLOCKED: ' + testname + '(' + data + ')');
   checkTestResults();
 }
 
-
 // Check to see if all the tests have run
 var checkTestResults = function() {
   // if any test is incomplete, keep waiting
   if (evalScriptsTotal - evalScriptsBlocked - evalScriptsThatRan > 0)
     return;
 
   // ... otherwise, finish
   SimpleTest.finish();
--- a/content/base/test/csp/test_CSP_frameancestors.html
+++ b/content/base/test/csp/test_CSP_frameancestors.html
@@ -1,29 +1,26 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test for Content Security Policy Frame Ancestors directive</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
-
-  
 </div>
-
 <iframe style="width:100%;height:300px;" id='cspframe'></iframe>
 <iframe style="width:100%;height:300px;" id='cspframe2'></iframe>
 <script class="testbody" type="text/javascript">
 
 var path = "/tests/content/base/test/csp/";
 
-// These are test results: -1 means it hasn't run, 
+// These are test results: -1 means it hasn't run,
 // true/false is the pass/fail result.
 var framesThatShouldLoad = {
   aa_allow: -1,    /* innermost frame allows a */
   //aa_block: -1,    /* innermost frame denies a */
   //aa2_block: -1,    /* innermost frame denies a */
   ab_allow: -1,    /* innermost frame allows a */
   //ab_block: -1,    /* innermost frame denies a */
   aba_allow: -1,   /* innermost frame allows b,a */
@@ -42,35 +39,35 @@ var framesThatShouldLoad = {
   //aba2_block_spec_compliant: -1,  /* innermost frame denies a */
   abb_allow_spec_compliant: -1,   /* innermost frame allows b,a */
   //abb_block_spec_compliant: -1,   /* innermost frame denies b */
   //abb2_block_spec_compliant: -1,  /* innermost frame denies a */
 };
 
 var expectedViolationsLeft = 14;
 
-// This is used to watch the blocked data bounce off CSP and allowed data 
+// This is used to watch the blocked data bounce off CSP and allowed data
 // get sent out to the wire.
 function examiner() {
   SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
 }
 examiner.prototype  = {
   observe: function(subject, topic, data) {
     // subject should be an nsURI, and should be either allowed or blocked.
     if (!SpecialPowers.can_QI(subject))
       return;
-      
+
     if (topic === "csp-on-violate-policy") {
       //these were blocked... record that they were blocked
       var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIURI"), "asciiSpec");
       window.frameBlocked(asciiSpec, data);
     }
   },
 
-  // must eventually call this to remove the listener, 
+  // must eventually call this to remove the listener,
   // or mochitests might get borked.
   remove: function() {
     SpecialPowers.removeObserver(this, "csp-on-violate-policy");
   }
 }
 
 // called when a frame is loaded
 // -- if it's not enumerated above, it should not load!
--- a/content/base/test/csp/test_bothCSPheaders.html
+++ b/content/base/test/csp/test_bothCSPheaders.html
@@ -19,28 +19,24 @@ var prefixedHeaderImgURL = "http://examp
 var unprefixedHeaderImgURL = "http://mochi.test:8888/unprefixed.jpg";
 var testsRun = 0;
 var totalTests = 2;
 
 // This is used to watch the blocked data bounce off CSP and allowed data
 // get sent out to the wire.
 function examiner() {
   SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
-  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+  SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
 }
 examiner.prototype  = {
   observe: function(subject, topic, data) {
-    // subject should be an nsURI, and should be either allowed or blocked.
-    if(!SpecialPowers.can_QI(subject))
-      return;
-
-    if (topic === "http-on-modify-request") {
-      var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
-      if (asciiSpec == prefixedHeaderImgURL || asciiSpec == unprefixedHeaderImgURL) {
-        is(asciiSpec, unprefixedHeaderImgURL, "Load was allowed - should be allowed by unprefixed header (blocked by prefixed)");
+    if (topic === "specialpowers-http-notify-request") {
+      var allowedUri = data;
+      if (allowedUri == prefixedHeaderImgURL || allowedUri == unprefixedHeaderImgURL) {
+        is(allowedUri, unprefixedHeaderImgURL, "Load was allowed - should be allowed by unprefixed header (blocked by prefixed)");
         testRan();
       }
     }
 
     if (topic === "csp-on-violate-policy") {
       // the load was blocked, this is a pass, the Content-Security-Policy
       // header doesn't allow the load, but the X-Content-Security-Header does
       var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIURI"), "asciiSpec");
@@ -50,17 +46,17 @@ examiner.prototype  = {
       }
     }
   },
 
   // must eventually call this to remove the listener,
   // or mochitests might get borked.
   remove: function() {
     SpecialPowers.removeObserver(this, "csp-on-violate-policy");
-    SpecialPowers.removeObserver(this, "http-on-modify-request");
+    SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
   }
 }
 
 window.examiner = new examiner();
 SimpleTest.waitForExplicitFinish();
 
 function testRan() {
   testsRun++;
--- a/content/base/test/csp/test_bug836922_npolicies.html
+++ b/content/base/test/csp/test_bug836922_npolicies.html
@@ -38,43 +38,37 @@ window.violation_reports = {
   script_self:
   {expected: 0, expected_ro: 1},  /* violates report-only */
 };
 
 // This is used to watch the blocked data bounce off CSP and allowed data
 // get sent out to the wire.  This also watches for violation reports to go out.
 function examiner() {
   SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
-  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+  SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
 }
 examiner.prototype  = {
   observe: function(subject, topic, data) {
-    // subject should be an nsURI, and should be either allowed or blocked.
-    if(!SpecialPowers.can_QI(subject))
-       return;
-
     var testpat = new RegExp("testid=([a-z0-9_]+)");
 
-    if (topic === "http-on-modify-request") {
-      var asciiSpec = SpecialPowers.getPrivilegedProps(
-                        SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"),
-                        "URI.asciiSpec");
-      if (!testpat.test(asciiSpec)) return;
-      var testid = testpat.exec(asciiSpec)[1];
+    if (topic === "specialpowers-http-notify-request") {
+      var uri = data;
+      if (!testpat.test(uri)) return;
+      var testid = testpat.exec(uri)[1];
 
       // violation reports don't come through here, but the requested resources do
       // if the test has already finished, move on.  Some things throw multiple
       // requests (preloads and such)
       try {
         if (window.loads[testid].verified) return;
       } catch(e) { return; }
 
       // these are requests that were allowed by CSP
-      var testid = testpat.exec(asciiSpec)[1];
-      window.testResult(testid, 'allowed', asciiSpec + " allowed by csp");
+      var testid = testpat.exec(uri)[1];
+      window.testResult(testid, 'allowed', uri + " allowed by csp");
     }
 
     if(topic === "csp-on-violate-policy") {
       // if the violated policy was report-only, the resource will still be
       // loaded even if this topic is notified.
       var asciiSpec = SpecialPowers.getPrivilegedProps(
                         SpecialPowers.do_QueryInterface(subject, "nsIURI"),
                         "asciiSpec");
@@ -107,17 +101,17 @@ examiner.prototype  = {
     window.bug836922examiner.remove();
     window.resultPoller.pollForFinish();
   },
 
   // must eventually call this to remove the listener,
   // or mochitests might get borked.
   remove: function() {
     SpecialPowers.removeObserver(this, "csp-on-violate-policy");
-    SpecialPowers.removeObserver(this, "http-on-modify-request");
+    SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
   }
 }
 window.bug836922examiner = new examiner();
 
 
 // Poll for results and see if enough reports came in.  Keep trying
 // for a few seconds before failing with lack of reports.
 // Have to do this because there's a race between the async reporting
--- a/content/base/test/csp/test_bug886164.html
+++ b/content/base/test/csp/test_bug886164.html
@@ -4,20 +4,17 @@
   <meta charset="utf-8">
   <title>Bug 886164 - Enforce CSP in sandboxed iframe</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
-
-
 </div>
-
 <iframe style="width:200px;height:200px;" id='cspframe'  sandbox="allow-same-origin"></iframe>
 <iframe style="width:200px;height:200px;" id='cspframe2' sandbox></iframe>
 <iframe style="width:200px;height:200px;" id='cspframe3' sandbox="allow-same-origin"></iframe>
 <iframe style="width:200px;height:200px;" id='cspframe4' sandbox></iframe>
 <iframe style="width:200px;height:200px;" id='cspframe5' sandbox="allow-scripts"></iframe>
 <iframe style="width:200px;height:200px;" id='cspframe6' sandbox="allow-same-origin allow-scripts"></iframe>
 <script class="testbody" type="text/javascript">
 
@@ -91,38 +88,34 @@ function ok_wrapper(result, desc) {
 
 
 //csp related
 
 // This is used to watch the blocked data bounce off CSP and allowed data
 // get sent out to the wire.
 function examiner() {
   SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
-  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+  SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
 }
 examiner.prototype  = {
   observe: function(subject, topic, data) {
-    // subject should be an nsURI, and should be either allowed or blocked.
-    if (!SpecialPowers.can_QI(subject))
-      return;
-
     var testpat = new RegExp("testid=([a-z0-9_]+)");
 
     //_good things better be allowed!
     //_bad things better be stopped!
 
-    if (topic === "http-on-modify-request") {
+    if (topic === "specialpowers-http-notify-request") {
       //these things were allowed by CSP
-      var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
-      if (!testpat.test(asciiSpec)) return;
-      var testid = testpat.exec(asciiSpec)[1];
+      var uri = data;
+      if (!testpat.test(uri)) return;
+      var testid = testpat.exec(uri)[1];
 
       window.testResult(testid,
                         /_good/.test(testid),
-                        asciiSpec + " allowed by csp");
+                        uri + " allowed by csp");
     }
 
     if(topic === "csp-on-violate-policy") {
       //these were blocked... record that they were blocked
       var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIURI"), "asciiSpec");
       if (!testpat.test(asciiSpec)) return;
       var testid = testpat.exec(asciiSpec)[1];
       window.testResult(testid,
@@ -130,17 +123,17 @@ examiner.prototype  = {
                         asciiSpec + " blocked by \"" + data + "\"");
     }
   },
 
   // must eventually call this to remove the listener,
   // or mochitests might get borked.
   remove: function() {
     SpecialPowers.removeObserver(this, "csp-on-violate-policy");
-    SpecialPowers.removeObserver(this, "http-on-modify-request");
+    SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
   }
 }
 
 window.examiner = new examiner();
 
 window.testResult = function(testname, result, msg) {
   //test already complete.... forget it... remember the first result.
   if (window.tests[testname] != -1)
--- a/content/base/test/csp/test_csp_redirects.html
+++ b/content/base/test/csp/test_csp_redirects.html
@@ -15,43 +15,40 @@
 <pre id="log"></pre>
 <script class="testbody" type="text/javascript">
 
 var path = "/tests/content/base/test/csp/";
 
 // debugging
 function log(s) {
   return;
+  dump("**" + s + "\n");
   var log = document.getElementById("log");
   log.textContent = log.textContent+s+"\n";
 }
 
 // used to watch if requests are blocked by CSP or allowed through
 function examiner() {
   SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
-  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+  SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
 }
 examiner.prototype  = {
   observe: function(subject, topic, data) {
-    // subject should be an nsURI, and should be either allowed or blocked.
-    if (!SpecialPowers.can_QI(subject))
-      return;
-
     var testpat = new RegExp("testid=([a-z0-9-]+)");
     var asciiSpec;
     var testid;
 
-    if (topic === "http-on-modify-request") {
+    if (topic === "specialpowers-http-notify-request") {
       // request was sent
-      asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
-      if (!testpat.test(asciiSpec)) return;
-      testid = testpat.exec(asciiSpec)[1];
+      var allowedUri = data;
+      if (!testpat.test(allowedUri)) return;
+      testid = testpat.exec(allowedUri)[1];
       if (testExpectedResults[testid] == "completed") return;
-      log("allowed: "+asciiSpec);
-      window.testResult(testid, asciiSpec, true);
+      log("allowed: "+allowedUri);
+      window.testResult(testid, allowedUri, true);
     }
 
     else if (topic === "csp-on-violate-policy") {
       // request was blocked
       asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIURI"), "asciiSpec");
       if (!testpat.test(asciiSpec)) return;
       testid = testpat.exec(asciiSpec)[1];
       // had to add this check because http-on-modify-request can fire after
@@ -60,17 +57,17 @@ examiner.prototype  = {
       if (testExpectedResults[testid] == "completed") return;
       log("BLOCKED: "+asciiSpec);
       window.testResult(testid, asciiSpec, false);
     }
   },
 
   remove: function() {
     SpecialPowers.removeObserver(this, "csp-on-violate-policy");
-    SpecialPowers.removeObserver(this, "http-on-modify-request");
+    SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
   }
 }
 window.examiner = new examiner();
 
 // contains { test_frame_id : expected_result }
 var testExpectedResults = { "font-src": true,
                             "font-src-redir": false,
                             "frame-src": true,
@@ -127,17 +124,23 @@ var testResult = function(testName, url,
 
   window.examiner.remove();
   SimpleTest.finish();
 }
 
 SimpleTest.waitForExplicitFinish();
 
 SpecialPowers.pushPrefEnv(
-  {'set':[["security.csp.speccompliant", true]]},
+  {'set':[["security.csp.speccompliant", true],
+          // This defaults to 0 ("preload none") on mobile (B2G/Android), which
+          // blocks loading the resource until the user interacts with a
+          // corresponding widget, which breaks the media_* tests. We set it
+          // back to the default used by desktop Firefox to get consistent
+          // behavior.
+          ["media.preload.default", 2]]},
   function() {
     // save this for last so that our listeners are registered.
     // ... this loads the testbed of good and bad requests.
     document.getElementById("harness").src = "file_csp_redirects_main.html";
   });
 </script>
 </pre>
 
--- a/content/base/test/csp/test_nonce_source.html
+++ b/content/base/test/csp/test_nonce_source.html
@@ -21,64 +21,61 @@ var totalInlineScriptTests = 4;
 
 var scriptNonceViolations = 0;
 var expectedScriptNonceViolations = 2;
 var scriptInlineViolations = 0;
 var expectedScriptInlineViolations = 1;
 
 // This is used to watch the blocked data bounce off CSP
 function examiner() {
-  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+  SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
   SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
 }
 
 examiner.prototype = {
   observe: function(subject, topic, data) {
-    if (!SpecialPowers.can_QI(subject))
-      return;
-
     var testid_re = new RegExp("testid=([a-z0-9_]+)");
 
     //_good things better be allowed!
     //_bad things better be blocked!
 
-    if (topic === "http-on-modify-request") {
-      // these things were allowed by CSP
-      var allowed_uri = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
-      if (!testid_re.test(allowed_uri)) return;
-      var testid = testid_re.exec(allowed_uri)[1];
+    if (topic === "specialpowers-http-notify-request") {
+      var uri = data;
+      if (!testid_re.test(uri)) return;
+      var testid = testid_re.exec(uri)[1];
       ok(/_good/.test(testid), "Allowed URI with testid " + testid);
       ranTests(1);
     }
 
     if (topic === "csp-on-violate-policy") {
       try {
         // if it is an blocked external load, subject will be the URI of the resource
         var blocked_uri = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIURI"), "asciiSpec");
         if (!testid_re.test(blocked_uri)) return;
         var testid = testid_re.exec(blocked_uri)[1];
         ok(/_bad/.test(testid), "Blocked URI with testid " + testid);
         ranTests(1);
       } catch (e) {
         // if the subject is blocked inline, data will be a violation msg (defined at the top of contentSecurityPolicy.js)
+        //dump("** exception in csp-on-violate-policy: " + e + "\n");
         var violation_msg = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsISupportsCString"), "data");
         if (/Inline Script/.test(violation_msg)) {
           if (/Inline Script had invalid nonce/.test(violation_msg))
             scriptNonceViolations++;
           if (/Inline Scripts will not execute/.test(violation_msg))
             scriptInlineViolations++;
           window.inlineScriptTestResult("blocked", "blocked",
                                         "Blocked because " + violation_msg);
         }
       }
     }
   },
   // must eventually call this to remove the listener, or mochitests might get borked.
   remove: function() {
-    SpecialPowers.removeObserver(this, "http-on-modify-request");
+    SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
     SpecialPowers.removeObserver(this, "csp-on-violate-policy");
   }
 }
 
 var inlineScriptTestResult = function(testIs, testShouldBe, description) {
   if (testIs !== testShouldBe) {
     ok(false, description);
   } else {
--- a/content/base/test/unit/test_csputils.js
+++ b/content/base/test/unit/test_csputils.js
@@ -637,18 +637,17 @@ test(function test_FrameAncestor_ignores
                        .createInstance(Ci.nsIContentSecurityPolicy);
         cspObj.appendPolicy(testPolicy, aChildUri, false, false);
         let docshellparent = Cc["@mozilla.org/docshell;1"]
                                .createInstance(Ci.nsIDocShell);
         let docshellchild  = Cc["@mozilla.org/docshell;1"]
                                .createInstance(Ci.nsIDocShell);
         docshellparent.setCurrentURI(aParentUri);
         docshellchild.setCurrentURI(aChildUri);
-        docshellparent.QueryInterface(Ci.nsIDocShellTreeNode)
-                      .addChild(docshellchild);
+        docshellparent.addChild(docshellchild);
         return cspObj.permitsAncestry(docshellchild);
       };
 
       // check parent without userpass
       do_check_true(testPermits(URI("http://username:password@self.com/foo"),
                                 URI("http://self.com/bar")));
       do_check_true(testPermits(URI("http://user1:pass1@self.com/foo"),
                                 URI("http://self.com/bar")));
--- a/content/canvas/src/CanvasGradient.h
+++ b/content/canvas/src/CanvasGradient.h
@@ -40,17 +40,17 @@ public:
   {
     if (mStops && mStops->GetBackendType() == aRT->GetType()) {
       return mStops;
     }
 
     mStops =
       gfx::gfxGradientCache::GetOrCreateGradientStops(aRT,
                                                       mRawStops,
-                                                      gfx::EXTEND_CLAMP);
+                                                      gfx::ExtendMode::CLAMP);
 
     return mStops;
   }
 
   // WebIDL
   void AddColorStop(float offset, const nsAString& colorstr, ErrorResult& rv);
 
   JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -245,19 +245,19 @@ public:
         CanvasUtils::DoDrawImageSecurityCheck(aCtx->mCanvasElement,
                                               state.patternStyles[aStyle]->mPrincipal,
                                               state.patternStyles[aStyle]->mForceWriteOnly,
                                               state.patternStyles[aStyle]->mCORSUsed);
       }
 
       ExtendMode mode;
       if (state.patternStyles[aStyle]->mRepeat == CanvasPattern::NOREPEAT) {
-        mode = EXTEND_CLAMP;
+        mode = ExtendMode::CLAMP;
       } else {
-        mode = EXTEND_REPEAT;
+        mode = ExtendMode::REPEAT;
       }
       mPattern = new (mSurfacePattern.addr())
         SurfacePattern(state.patternStyles[aStyle]->mSurface, mode);
     }
 
     return *mPattern;
   }
 
@@ -327,17 +327,17 @@ public:
 
     mTempRect.ScaleRoundOut(1.0f);
 
     transform._31 -= mTempRect.x;
     transform._32 -= mTempRect.y;
 
     mTarget =
       mCtx->mTarget->CreateShadowDrawTarget(IntSize(int32_t(mTempRect.width), int32_t(mTempRect.height)),
-                                            FORMAT_B8G8R8A8, mSigma);
+                                            SurfaceFormat::B8G8R8A8, mSigma);
 
     if (!mTarget) {
       // XXX - Deal with the situation where our temp size is too big to
       // fit in a texture.
       mTarget = ctx->mTarget;
       mCtx = nullptr;
     } else {
       mTarget->SetTransform(transform);
@@ -353,16 +353,21 @@ public:
     RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
 
     mCtx->mTarget->DrawSurfaceWithShadow(snapshot, mTempRect.TopLeft(),
                                          Color::FromABGR(mCtx->CurrentState().shadowColor),
                                          mCtx->CurrentState().shadowOffset, mSigma,
                                          mCtx->CurrentState().op);
   }
 
+  operator DrawTarget*() 
+  {
+    return mTarget;
+  }
+
   DrawTarget* operator->()
   {
     return mTarget;
   }
 
 private:
   RefPtr<DrawTarget> mTarget;
   CanvasRenderingContext2D *mCtx;
@@ -868,17 +873,17 @@ CanvasRenderingContext2D::EnsureTarget()
 
         nsRefPtr<GLContext> glContext;
         nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
         nsString vendor;
 
         if (!mForceSoftware && CheckSizeForSkiaGL(size))
         {
           glContext = GLContextProvider::CreateOffscreen(gfxIntSize(size.width, size.height),
-                                                         caps, gl::ContextFlagsNone);
+                                                         caps);
         }
 
         if (glContext) {
           SkAutoTUnref<GrGLInterface> i(CreateGrGLInterfaceFromGLContext(glContext));
           mTarget = Factory::CreateDrawTargetSkiaWithGLContextAndGrGLInterface(glContext, i, size, format);
           AddDemotableContext(this);
         } else {
           mTarget = layerManager->CreateDrawTarget(size, format);
@@ -1125,17 +1130,17 @@ CanvasRenderingContext2D::GetInputStream
 
   return ImageEncoder::GetInputStream(mWidth, mHeight, imageBuffer, format,
                                       encoder, aEncoderOptions, aStream);
 }
 
 SurfaceFormat
 CanvasRenderingContext2D::GetSurfaceFormat() const
 {
-  return mOpaque ? FORMAT_B8G8R8X8 : FORMAT_B8G8R8A8;
+  return mOpaque ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8;
 }
 
 //
 // state
 //
 
 void
 CanvasRenderingContext2D::Save()
@@ -1376,32 +1381,32 @@ CanvasRenderingContext2D::SetStyleFromUn
 }
 
 void
 CanvasRenderingContext2D::SetFillRule(const nsAString& aString)
 {
   FillRule rule;
 
   if (aString.EqualsLiteral("evenodd"))
-    rule = FILL_EVEN_ODD;
+    rule = FillRule::FILL_EVEN_ODD;
   else if (aString.EqualsLiteral("nonzero"))
-    rule = FILL_WINDING;
+    rule = FillRule::FILL_WINDING;
   else
     return;
 
   CurrentState().fillRule = rule;
 }
 
 void
 CanvasRenderingContext2D::GetFillRule(nsAString& aString)
 {
   switch (CurrentState().fillRule) {
-  case FILL_WINDING:
+  case FillRule::FILL_WINDING:
     aString.AssignLiteral("nonzero"); break;
-  case FILL_EVEN_ODD:
+  case FillRule::FILL_EVEN_ODD:
     aString.AssignLiteral("evenodd"); break;
   }
 }
 //
 // gradients and patterns
 //
 already_AddRefed<CanvasGradient>
 CanvasRenderingContext2D::CreateLinearGradient(double x0, double y0, double x1, double y1)
@@ -1615,36 +1620,36 @@ CanvasRenderingContext2D::StrokeRect(dou
 
   if (NeedToDrawShadow()) {
     bounds = mgfx::Rect(x - state.lineWidth / 2.0f, y - state.lineWidth / 2.0f,
                         w + state.lineWidth, h + state.lineWidth);
     bounds = mTarget->GetTransform().TransformBounds(bounds);
   }
 
   if (!h) {
-    CapStyle cap = CAP_BUTT;
-    if (state.lineJoin == JOIN_ROUND) {
-      cap = CAP_ROUND;
+    CapStyle cap = CapStyle::BUTT;
+    if (state.lineJoin == JoinStyle::ROUND) {
+      cap = CapStyle::ROUND;
     }
     AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
       StrokeLine(Point(x, y), Point(x + w, y),
                   CanvasGeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
                   StrokeOptions(state.lineWidth, state.lineJoin,
                                 cap, state.miterLimit,
                                 state.dash.Length(),
                                 state.dash.Elements(),
                                 state.dashOffset),
                   DrawOptions(state.globalAlpha, UsedOperation()));
     return;
   }
 
   if (!w) {
-    CapStyle cap = CAP_BUTT;
-    if (state.lineJoin == JOIN_ROUND) {
-      cap = CAP_ROUND;
+    CapStyle cap = CapStyle::BUTT;
+    if (state.lineJoin == JoinStyle::ROUND) {
+      cap = CapStyle::ROUND;
     }
     AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
       StrokeLine(Point(x, y), Point(x, y + h),
                   CanvasGeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
                   StrokeOptions(state.lineWidth, state.lineJoin,
                                 cap, state.miterLimit,
                                 state.dash.Length(),
                                 state.dash.Elements(),
@@ -1742,20 +1747,20 @@ void CanvasRenderingContext2D::DrawSyste
     Save();
 
     // set state to conforming focus state
     ContextState& state = CurrentState();
     state.globalAlpha = 1.0;
     state.shadowBlur = 0;
     state.shadowOffset.x = 0;
     state.shadowOffset.y = 0;
-    state.op = mozilla::gfx::OP_OVER;
-
-    state.lineCap = CAP_BUTT;
-    state.lineJoin = mozilla::gfx::JOIN_MITER_OR_BEVEL;
+    state.op = mozilla::gfx::CompositionOp::OP_OVER;
+
+    state.lineCap = CapStyle::BUTT;
+    state.lineJoin = mozilla::gfx::JoinStyle::MITER_OR_BEVEL;
     state.lineWidth = 1;
     CurrentState().dash.Clear();
 
     // color and style of the rings is the same as for image maps
     // set the background focus color
     CurrentState().SetColorStyle(STYLE_STROKE, NS_RGBA(255, 255, 255, 255));
     // draw the focus ring
     Stroke();
@@ -1958,17 +1963,17 @@ CanvasRenderingContext2D::EnsureWritable
   }
 }
 
 void
 CanvasRenderingContext2D::EnsureUserSpacePath(const CanvasWindingRule& winding)
 {
   FillRule fillRule = CurrentState().fillRule;
   if(winding == CanvasWindingRule::Evenodd)
-    fillRule = FILL_EVEN_ODD;
+    fillRule = FillRule::FILL_EVEN_ODD;
 
   if (!mPath && !mPathBuilder && !mDSPathBuilder) {
     EnsureTarget();
     mPathBuilder = mTarget->CreatePathBuilder(fillRule);
   }
 
   if (mPathBuilder) {
     mPath = mPathBuilder->Finish();
@@ -2835,75 +2840,75 @@ gfxFontGroup *CanvasRenderingContext2D::
 //
 
 void
 CanvasRenderingContext2D::SetLineCap(const nsAString& capstyle)
 {
   CapStyle cap;
 
   if (capstyle.EqualsLiteral("butt")) {
-    cap = CAP_BUTT;
+    cap = CapStyle::BUTT;
   } else if (capstyle.EqualsLiteral("round")) {
-    cap = CAP_ROUND;
+    cap = CapStyle::ROUND;
   } else if (capstyle.EqualsLiteral("square")) {
-    cap = CAP_SQUARE;
+    cap = CapStyle::SQUARE;
   } else {
     // XXX ERRMSG we need to report an error to developers here! (bug 329026)
     return;
   }
 
   CurrentState().lineCap = cap;
 }
 
 void
 CanvasRenderingContext2D::GetLineCap(nsAString& capstyle)
 {
   switch (CurrentState().lineCap) {
-  case CAP_BUTT:
+  case CapStyle::BUTT:
     capstyle.AssignLiteral("butt");
     break;
-  case CAP_ROUND:
+  case CapStyle::ROUND:
     capstyle.AssignLiteral("round");
     break;
-  case CAP_SQUARE:
+  case CapStyle::SQUARE:
     capstyle.AssignLiteral("square");
     break;
   }
 }
 
 void
 CanvasRenderingContext2D::SetLineJoin(const nsAString& joinstyle)
 {
   JoinStyle j;
 
   if (joinstyle.EqualsLiteral("round")) {
-    j = JOIN_ROUND;
+    j = JoinStyle::ROUND;
   } else if (joinstyle.EqualsLiteral("bevel")) {
-    j = JOIN_BEVEL;
+    j = JoinStyle::BEVEL;
   } else if (joinstyle.EqualsLiteral("miter")) {
-    j = JOIN_MITER_OR_BEVEL;
+    j = JoinStyle::MITER_OR_BEVEL;
   } else {
     // XXX ERRMSG we need to report an error to developers here! (bug 329026)
     return;
   }
 
   CurrentState().lineJoin = j;
 }
 
 void
 CanvasRenderingContext2D::GetLineJoin(nsAString& joinstyle, ErrorResult& error)
 {
   switch (CurrentState().lineJoin) {
-  case JOIN_ROUND:
+  case JoinStyle::ROUND:
     joinstyle.AssignLiteral("round");
     break;
-  case JOIN_BEVEL:
+  case JoinStyle::BEVEL:
     joinstyle.AssignLiteral("bevel");
     break;
-  case JOIN_MITER_OR_BEVEL:
+  case JoinStyle::MITER_OR_BEVEL:
     joinstyle.AssignLiteral("miter");
     break;
   default:
     error.Throw(NS_ERROR_FAILURE);
   }
 }
 
 void
@@ -3089,24 +3094,27 @@ CanvasRenderingContext2D::DrawImage(cons
       HTMLVideoElement* video = &image.GetAsHTMLVideoElement();
       element = video;
     }
 
     srcSurf =
       CanvasImageCache::Lookup(element, mCanvasElement, &imgSize);
   }
 
+  nsLayoutUtils::DirectDrawInfo drawInfo;
+
   if (!srcSurf) {
     // The canvas spec says that drawImage should draw the first frame
-    // of animated images
-    uint32_t sfeFlags = nsLayoutUtils::SFE_WANT_FIRST_FRAME;
+    // of animated images. We also don't want to rasterize vector images.
+    uint32_t sfeFlags = nsLayoutUtils::SFE_WANT_FIRST_FRAME |
+                        nsLayoutUtils::SFE_NO_RASTERIZING_VECTORS;
     nsLayoutUtils::SurfaceFromElementResult res =
       nsLayoutUtils::SurfaceFromElement(element, sfeFlags, mTarget);
 
-    if (!res.mSourceSurface) {
+    if (!res.mSourceSurface && !res.mDrawInfo.mImgContainer) {
       // Spec says to silently do nothing if the element is still loading.
       if (!res.mIsStillLoading) {
         error.Throw(NS_ERROR_NOT_AVAILABLE);
       }
       return;
     }
 
     imgSize = res.mSize;
@@ -3121,22 +3129,26 @@ CanvasRenderingContext2D::DrawImage(cons
     }
 
     if (mCanvasElement) {
       CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
                                             res.mPrincipal, res.mIsWriteOnly,
                                             res.mCORSUsed);
     }
 
-    if (res.mImageRequest) {
-      CanvasImageCache::NotifyDrawImage(element, mCanvasElement, res.mImageRequest,
-                                        res.mSourceSurface, imgSize);
+    if (res.mSourceSurface) {
+      if (res.mImageRequest) {
+        CanvasImageCache::NotifyDrawImage(element, mCanvasElement, res.mImageRequest,
+                                          res.mSourceSurface, imgSize);
+      }
+
+      srcSurf = res.mSourceSurface;
+    } else {
+      drawInfo = res.mDrawInfo;
     }
-
-    srcSurf = res.mSourceSurface;
   }
 
   if (optional_argc == 0) {
     sx = sy = 0.0;
     dw = sw = (double) imgSize.width;
     dh = sh = (double) imgSize.height;
   } else if (optional_argc == 2) {
     sx = sy = 0.0;
@@ -3162,64 +3174,110 @@ CanvasRenderingContext2D::DrawImage(cons
     // XXX - Unresolved spec issues here, for now return error.
     error.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
   }
 
   Filter filter;
 
   if (CurrentState().imageSmoothingEnabled)
-    filter = mgfx::FILTER_LINEAR;
+    filter = mgfx::Filter::LINEAR;
   else
-    filter = mgfx::FILTER_POINT;
+    filter = mgfx::Filter::POINT;
 
   mgfx::Rect bounds;
 
   if (NeedToDrawShadow()) {
     bounds = mgfx::Rect(dx, dy, dw, dh);
     bounds = mTarget->GetTransform().TransformBounds(bounds);
   }
 
-  AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
-    DrawSurface(srcSurf,
-                mgfx::Rect(dx, dy, dw, dh),
-                mgfx::Rect(sx, sy, sw, sh),
-                DrawSurfaceOptions(filter),
-                DrawOptions(CurrentState().globalAlpha, UsedOperation()));
+  if (srcSurf) {
+    AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
+      DrawSurface(srcSurf,
+                  mgfx::Rect(dx, dy, dw, dh),
+                  mgfx::Rect(sx, sy, sw, sh),
+                  DrawSurfaceOptions(filter),
+                  DrawOptions(CurrentState().globalAlpha, UsedOperation()));
+  } else {
+    DrawDirectlyToCanvas(drawInfo, &bounds, dx, dy, dw, dh,
+                         sx, sy, sw, sh, imgSize);
+  }
 
   RedrawUser(gfxRect(dx, dy, dw, dh));
 }
 
+void
+CanvasRenderingContext2D::DrawDirectlyToCanvas(
+                          const nsLayoutUtils::DirectDrawInfo& image,
+                          mgfx::Rect* bounds, double dx, double dy,
+                          double dw, double dh, double sx, double sy,
+                          double sw, double sh, gfxIntSize imgSize)
+{
+  gfxMatrix contextMatrix;
+
+  AdjustedTarget tempTarget(this, bounds->IsEmpty() ? nullptr: bounds);
+
+  // get any already existing transforms on the context. Include transformations used for context shadow
+  if (tempTarget) {
+    Matrix matrix = tempTarget->GetTransform();
+    contextMatrix = gfxMatrix(matrix._11, matrix._12, matrix._21,
+                              matrix._22, matrix._31, matrix._32);
+  }
+
+  gfxMatrix transformMatrix;
+  transformMatrix.Translate(gfxPoint(sx, sy));
+  if (dw > 0 && dh > 0) {
+    transformMatrix.Scale(sw/dw, sh/dh);
+  }
+  transformMatrix.Translate(gfxPoint(-dx, -dy));
+
+  nsRefPtr<gfxContext> context = new gfxContext(tempTarget);
+  context->SetMatrix(contextMatrix);
+  
+  // FLAG_CLAMP is added for increased performance
+  uint32_t modifiedFlags = image.mDrawingFlags | imgIContainer::FLAG_CLAMP;
+
+  nsresult rv = image.mImgContainer->
+    Draw(context, GraphicsFilter::FILTER_GOOD, transformMatrix,
+         gfxRect(gfxPoint(dx, dy), gfxIntSize(dw, dh)),
+         nsIntRect(nsIntPoint(0, 0), gfxIntSize(imgSize.width, imgSize.height)),
+         gfxIntSize(imgSize.width, imgSize.height), nullptr, image.mWhichFrame,
+         modifiedFlags);
+
+  NS_ENSURE_SUCCESS_VOID(rv);
+}
+
 #ifdef USE_SKIA_GPU
 static bool
 IsStandardCompositeOp(CompositionOp op)
 {
-    return (op == OP_SOURCE ||
-            op == OP_ATOP ||
-            op == OP_IN ||
-            op == OP_OUT ||
-            op == OP_OVER ||
-            op == OP_DEST_IN ||
-            op == OP_DEST_OUT ||
-            op == OP_DEST_OVER ||
-            op == OP_DEST_ATOP ||
-            op == OP_ADD ||
-            op == OP_XOR);
+    return (op == CompositionOp::OP_SOURCE ||
+            op == CompositionOp::OP_ATOP ||
+            op == CompositionOp::OP_IN ||
+            op == CompositionOp::OP_OUT ||
+            op == CompositionOp::OP_OVER ||
+            op == CompositionOp::OP_DEST_IN ||
+            op == CompositionOp::OP_DEST_OUT ||
+            op == CompositionOp::OP_DEST_OVER ||
+            op == CompositionOp::OP_DEST_ATOP ||
+            op == CompositionOp::OP_ADD ||
+            op == CompositionOp::OP_XOR);
 }
 #endif
 
 void
 CanvasRenderingContext2D::SetGlobalCompositeOperation(const nsAString& op,
                                                       ErrorResult& error)
 {
   CompositionOp comp_op;
 
 #define CANVAS_OP_TO_GFX_OP(cvsop, op2d) \
   if (op.EqualsLiteral(cvsop))   \
-    comp_op = OP_##op2d;
+    comp_op = CompositionOp::OP_##op2d;
 
   CANVAS_OP_TO_GFX_OP("copy", SOURCE)
   else CANVAS_OP_TO_GFX_OP("source-atop", ATOP)
   else CANVAS_OP_TO_GFX_OP("source-in", IN)
   else CANVAS_OP_TO_GFX_OP("source-out", OUT)
   else CANVAS_OP_TO_GFX_OP("source-over", OVER)
   else CANVAS_OP_TO_GFX_OP("destination-in", DEST_IN)
   else CANVAS_OP_TO_GFX_OP("destination-out", DEST_OUT)
@@ -3257,17 +3315,17 @@ CanvasRenderingContext2D::SetGlobalCompo
 
 void
 CanvasRenderingContext2D::GetGlobalCompositeOperation(nsAString& op,
                                                       ErrorResult& error)
 {
   CompositionOp comp_op = CurrentState().op;
 
 #define CANVAS_OP_TO_GFX_OP(cvsop, op2d) \
-  if (comp_op == OP_##op2d) \
+  if (comp_op == CompositionOp::OP_##op2d) \
     op.AssignLiteral(cvsop);
 
   CANVAS_OP_TO_GFX_OP("copy", SOURCE)
   else CANVAS_OP_TO_GFX_OP("destination-atop", DEST_ATOP)
   else CANVAS_OP_TO_GFX_OP("destination-in", DEST_IN)
   else CANVAS_OP_TO_GFX_OP("destination-out", DEST_OUT)
   else CANVAS_OP_TO_GFX_OP("destination-over", DEST_OVER)
   else CANVAS_OP_TO_GFX_OP("lighter", ADD)
@@ -3389,17 +3447,17 @@ CanvasRenderingContext2D::DrawWindow(nsG
   RefPtr<DrawTarget> drawDT;
   if (gfxPlatform::GetPlatform()->SupportsAzureContentForDrawTarget(mTarget)) {
     thebes = new gfxContext(mTarget);
     thebes->SetMatrix(gfxMatrix(matrix._11, matrix._12, matrix._21,
                                 matrix._22, matrix._31, matrix._32));
   } else if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
     drawDT =
       gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(IntSize(ceil(sw), ceil(sh)),
-                                                                   FORMAT_B8G8R8A8);
+                                                                   SurfaceFormat::B8G8R8A8);
     if (!drawDT) {
       error.Throw(NS_ERROR_FAILURE);
       return;
     }
 
     thebes = new gfxContext(drawDT);
     thebes->Scale(matrix._11, matrix._22);
   } else {
@@ -3429,17 +3487,17 @@ CanvasRenderingContext2D::DrawWindow(nsG
         error.Throw(NS_ERROR_FAILURE);
         return;
       }
 
       source =
         mTarget->CreateSourceSurfaceFromData(img->Data(),
                                              IntSize(size.width, size.height),
                                              img->Stride(),
-                                             FORMAT_B8G8R8A8);
+                                             SurfaceFormat::B8G8R8A8);
     } else {
       RefPtr<SourceSurface> snapshot = drawDT->Snapshot();
       RefPtr<DataSourceSurface> data = snapshot->GetDataSurface();
 
       source =
         mTarget->CreateSourceSurfaceFromData(data->GetData(),
                                              data->GetSize(),
                                              data->Stride(),
@@ -3449,18 +3507,18 @@ CanvasRenderingContext2D::DrawWindow(nsG
     if (!source) {
       error.Throw(NS_ERROR_FAILURE);
       return;
     }
 
     mgfx::Rect destRect(0, 0, w, h);
     mgfx::Rect sourceRect(0, 0, sw, sh);
     mTarget->DrawSurface(source, destRect, sourceRect,
-                         DrawSurfaceOptions(mgfx::FILTER_POINT),
-                         DrawOptions(1.0f, OP_SOURCE, AA_NONE));
+                         DrawSurfaceOptions(mgfx::Filter::POINT),
+                         DrawOptions(1.0f, CompositionOp::OP_SOURCE, AntialiasMode::NONE));
     mTarget->Flush();
   } else {
     mTarget->SetTransform(matrix);
   }
 
   // note that x and y are coordinates in the document that
   // we're drawing; x and y are drawn to 0,0 in current user
   // space.
@@ -3728,17 +3786,17 @@ CanvasRenderingContext2D::GetImageDataAr
 
 void
 CanvasRenderingContext2D::EnsureErrorTarget()
 {
   if (sErrorTarget) {
     return;
   }
 
-  RefPtr<DrawTarget> errorTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(IntSize(1, 1), FORMAT_B8G8R8A8);
+  RefPtr<DrawTarget> errorTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(IntSize(1, 1), SurfaceFormat::B8G8R8A8);
   MOZ_ASSERT(errorTarget, "Failed to allocate the error target!");
 
   sErrorTarget = errorTarget;
   NS_ADDREF(sErrorTarget);
 }
 
 void
 CanvasRenderingContext2D::FillRuleChanged()
@@ -3874,17 +3932,17 @@ CanvasRenderingContext2D::PutImageData_e
   }
 
   EnsureTarget();
   if (!IsTargetValid()) {
     return NS_ERROR_FAILURE;
   }
 
   RefPtr<SourceSurface> sourceSurface =
-    mTarget->CreateSourceSurfaceFromData(imgsurf->Data(), IntSize(w, h), imgsurf->Stride(), FORMAT_B8G8R8A8);
+    mTarget->CreateSourceSurfaceFromData(imgsurf->Data(), IntSize(w, h), imgsurf->Stride(), SurfaceFormat::B8G8R8A8);
 
   // In certain scenarios, requesting larger than 8k image fails.  Bug 803568
   // covers the details of how to run into it, but the full detailed
   // investigation hasn't been done to determine the underlying cause.  We
   // will just handle the failure to allocate the surface to avoid a crash.
   if (!sourceSurface) {
     return NS_ERROR_FAILURE;
   }
--- a/content/canvas/src/CanvasRenderingContext2D.h
+++ b/content/canvas/src/CanvasRenderingContext2D.h
@@ -18,16 +18,17 @@
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/CanvasGradient.h"
 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 #include "mozilla/dom/CanvasPattern.h"
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/gfx/2D.h"
 #include "gfx2DGlue.h"
 #include "imgIEncoder.h"
+#include "nsLayoutUtils.h"
 
 class nsGlobalWindow;
 class nsXULElement;
 
 namespace mozilla {
 namespace gfx {
 class SourceSurface;
 }
@@ -574,16 +575,21 @@ protected:
     */
   mozilla::gfx::SurfaceFormat GetSurfaceFormat() const;
 
   void DrawImage(const HTMLImageOrCanvasOrVideoElement &imgElt,
                  double sx, double sy, double sw, double sh,
                  double dx, double dy, double dw, double dh, 
                  uint8_t optional_argc, mozilla::ErrorResult& error);
 
+  void DrawDirectlyToCanvas(const nsLayoutUtils::DirectDrawInfo& image,
+                            mozilla::gfx::Rect* bounds, double dx, double dy,
+                            double dw, double dh, double sx, double sy,
+                            double sw, double sh, gfxIntSize imgSize);
+
   nsString& GetFont()
   {
     /* will initilize the value if not set, else does nothing */
     GetCurrentFontStyle();
 
     return CurrentState().font;
   }
 
@@ -688,17 +694,17 @@ protected:
     return NS_GET_A(state.shadowColor) != 0 && 
       (state.shadowBlur != 0 || state.shadowOffset.x != 0 || state.shadowOffset.y != 0);
   }
 
   mozilla::gfx::CompositionOp UsedOperation()
   {
     if (NeedToDrawShadow()) {
       // In this case the shadow rendering will use the operator.
-      return mozilla::gfx::OP_OVER;
+      return mozilla::gfx::CompositionOp::OP_OVER;
     }
 
     return CurrentState().op;
   }
 
   /**
     * Gets the pres shell from either the canvas element or the doc shell
     */
@@ -754,20 +760,20 @@ protected:
   public:
     ContextState() : textAlign(TEXT_ALIGN_START),
                      textBaseline(TEXT_BASELINE_ALPHABETIC),
                      lineWidth(1.0f),
                      miterLimit(10.0f),
                      globalAlpha(1.0f),
                      shadowBlur(0.0),
                      dashOffset(0.0f),
-                     op(mozilla::gfx::OP_OVER),
-                     fillRule(mozilla::gfx::FILL_WINDING),
-                     lineCap(mozilla::gfx::CAP_BUTT),
-                     lineJoin(mozilla::gfx::JOIN_MITER_OR_BEVEL),
+                     op(mozilla::gfx::CompositionOp::OP_OVER),
+                     fillRule(mozilla::gfx::FillRule::FILL_WINDING),
+                     lineCap(mozilla::gfx::CapStyle::BUTT),
+                     lineJoin(mozilla::gfx::JoinStyle::MITER_OR_BEVEL),
                      imageSmoothingEnabled(true)
     { }
 
     ContextState(const ContextState& other)
         : fontGroup(other.fontGroup),
           font(other.font),
           textAlign(other.textAlign),
           textBaseline(other.textBaseline),
--- a/content/canvas/src/WebGL2Context.cpp
+++ b/content/canvas/src/WebGL2Context.cpp
@@ -67,17 +67,17 @@ WebGLContext::InitWebGL2()
         OES_element_index_uint,
         OES_standard_derivatives,
         OES_texture_float,
         OES_texture_float_linear,
         OES_vertex_array_object,
         WEBGL_depth_texture,
         WEBGL_draw_buffers
     };
-    const GLFeature::Enum sFeatureRequiredArr[] = {
+    const GLFeature sFeatureRequiredArr[] = {
         GLFeature::blend_minmax,
         GLFeature::instanced_non_arrays,
         GLFeature::transform_feedback
     };
 
     // check WebGL extensions that are supposed to be natively supported
     for (size_t i = 0; i < size_t(MOZ_ARRAY_LENGTH(sExtensionNativelySupportedArr)); i++)
     {
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -434,18 +434,16 @@ WebGLContext::SetDimensions(int32_t widt
 #ifdef XP_WIN
     bool preferEGL =
         Preferences::GetBool("webgl.prefer-egl", false);
     bool preferOpenGL =
         Preferences::GetBool("webgl.prefer-native-gl", false);
 #endif
     bool forceEnabled =
         Preferences::GetBool("webgl.force-enabled", false);
-    bool useMesaLlvmPipe =
-        Preferences::GetBool("gfx.prefer-mesa-llvmpipe", false);
     bool disabled =
         Preferences::GetBool("webgl.disabled", false);
     bool prefer16bit =
         Preferences::GetBool("webgl.prefer-16bpp", false);
 
     ScopedGfxFeatureReporter reporter("WebGL", forceEnabled);
 
     if (disabled)
@@ -528,17 +526,17 @@ WebGLContext::SetDimensions(int32_t widt
                 useANGLE = false;
             }
         }
 #endif
     }
 
 #ifdef XP_WIN
     // allow forcing GL and not EGL/ANGLE
-    if (useMesaLlvmPipe || PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL")) {
+    if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL")) {
         preferEGL = false;
         useANGLE = false;
         useOpenGL = true;
     }
 #endif
 
     gfxIntSize size(width, height);
 
@@ -550,23 +548,19 @@ WebGLContext::SetDimensions(int32_t widt
             GenerateWarning("Error during ANGLE OpenGL ES initialization");
             return NS_ERROR_FAILURE;
         }
     }
 #endif
 
     // try the default provider, whatever that is
     if (!gl && useOpenGL) {
-        gl::ContextFlags flag = useMesaLlvmPipe
-                                ? gl::ContextFlagsMesaLLVMPipe
-                                : gl::ContextFlagsNone;
-        gl = gl::GLContextProvider::CreateOffscreen(size, caps, flag);
+        gl = gl::GLContextProvider::CreateOffscreen(size, caps);
         if (gl && !InitAndValidateGL()) {
-            GenerateWarning("Error during %s initialization",
-                            useMesaLlvmPipe ? "Mesa LLVMpipe" : "OpenGL");
+            GenerateWarning("Error during OpenGL initialization");
             return NS_ERROR_FAILURE;
         }
     }
 
     if (!gl) {
         GenerateWarning("Can't get a usable WebGL context");
         return NS_ERROR_FAILURE;
     }
@@ -1291,17 +1285,17 @@ WebGLContext::RobustnessTimerCallback(ns
 
 void
 WebGLContext::MaybeRestoreContext()
 {
     // Don't try to handle it if we already know it's busted.
     if (mContextStatus != ContextNotLost || gl == nullptr)
         return;
 
-    bool isEGL = gl->GetContextType() == gl::ContextTypeEGL,
+    bool isEGL = gl->GetContextType() == gl::GLContextType::EGL,
          isANGLE = gl->IsANGLE();
 
     GLContext::ContextResetARB resetStatus = GLContext::CONTEXT_NO_ERROR;
     if (mHasRobustness) {
         gl->MakeCurrent();
         resetStatus = (GLContext::ContextResetARB) gl->fGetGraphicsResetStatus();
     } else if (isEGL) {
         // Simulate a ARB_robustness guilty context loss for when we
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -1420,39 +1420,41 @@ WebGLContext::GetFramebufferAttachmentPa
                 if (IsExtensionEnabled(EXT_sRGB)) {
                     const GLenum internalFormat = fba.Renderbuffer()->InternalFormat();
                     return (internalFormat == LOCAL_GL_SRGB_EXT ||
                             internalFormat == LOCAL_GL_SRGB_ALPHA_EXT ||
                             internalFormat == LOCAL_GL_SRGB8_ALPHA8_EXT) ?
                         JS::NumberValue(uint32_t(LOCAL_GL_SRGB_EXT)) :
                         JS::NumberValue(uint32_t(LOCAL_GL_LINEAR));
                 }
+                break;
+
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
                 return JS::NumberValue(uint32_t(LOCAL_GL_RENDERBUFFER));
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
             {
                 return WebGLObjectAsJSValue(cx, fba.Renderbuffer(), rv);
             }
-
-            default:
-                ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: pname", pname);
-                return JS::NullValue();
         }
+
+        ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: pname", pname);
+        return JS::NullValue();
     } else if (fba.Texture()) {
         switch (pname) {
              case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT:
                 if (IsExtensionEnabled(EXT_sRGB)) {
                     const GLenum internalFormat =
                         fba.Texture()->ImageInfoBase().InternalFormat();
                     return (internalFormat == LOCAL_GL_SRGB_EXT ||
                             internalFormat == LOCAL_GL_SRGB_ALPHA_EXT) ?
                         JS::NumberValue(uint32_t(LOCAL_GL_SRGB_EXT)) :
                         JS::NumberValue(uint32_t(LOCAL_GL_LINEAR));
                 }
+                break;
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
                 return JS::NumberValue(uint32_t(LOCAL_GL_TEXTURE));
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
             {
                 return WebGLObjectAsJSValue(cx, fba.Texture(), rv);
             }
@@ -1462,21 +1464,20 @@ WebGLContext::GetFramebufferAttachmentPa
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
             {
                 GLenum face = fba.TexImageTarget();
                 if (face == LOCAL_GL_TEXTURE_2D)
                     face = 0;
                 return JS::Int32Value(face);
             }
-
-            default:
-                ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: pname", pname);
-                return JS::NullValue();
         }
+
+        ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: pname", pname);
+        return JS::NullValue();
     } else {
         switch (pname) {
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
                 return JS::NumberValue(uint32_t(LOCAL_GL_NONE));
 
             default:
                 ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: pname", pname);
                 return JS::NullValue();
@@ -2146,17 +2147,17 @@ WebGLContext::LinkProgram(WebGLProgram *
             }
         }
     }
 
     if (ok) {
         // Bug 750527
         if (gl->WorkAroundDriverBugs() &&
             updateInfoSucceeded &&
-            gl->Vendor() == gl::GLContext::VendorNVIDIA)
+            gl->Vendor() == gl::GLVendor::NVIDIA)
         {
             if (program == mCurrentProgram)
                 gl->fUseProgram(progname);
         }
     } else {
         program->SetLinkStatus(false);
 
         if (ShouldGenerateWarnings()) {
@@ -2684,26 +2685,26 @@ WebGLContext::SurfaceFromElementResultTo
         return NS_ERROR_DOM_SECURITY_ERR;
     }
 
     // End of security checks, now we should be safe regarding cross-domain images
     // Notice that there is never a need to mark the WebGL canvas as write-only, since we reject write-only/cross-domain
     // texture sources in the first place.
 
     switch (data->GetFormat()) {
-        case FORMAT_B8G8R8A8:
+        case SurfaceFormat::B8G8R8A8:
             *format = WebGLTexelFormat::BGRA8; // careful, our ARGB means BGRA
             break;
-        case FORMAT_B8G8R8X8:
+        case SurfaceFormat::B8G8R8X8:
             *format = WebGLTexelFormat::BGRX8; // careful, our RGB24 is not tightly packed. Whence BGRX8.
             break;
-        case FORMAT_A8:
+        case SurfaceFormat::A8:
             *format = WebGLTexelFormat::A8;
             break;
-        case FORMAT_R5G6B5:
+        case SurfaceFormat::R5G6B5:
             *format = WebGLTexelFormat::RGB565;
             break;
         default:
             NS_ASSERTION(false, "Unsupported image format. Unimplemented.");
             return NS_ERROR_NOT_IMPLEMENTED;
     }
 
     imageOut = data;
@@ -3113,17 +3114,17 @@ WebGLContext::CompileShader(WebGLShader 
             resources.EXT_draw_buffers = 1;
 
         // Tell ANGLE to allow highp in frag shaders. (unless disabled)
         // If underlying GLES doesn't have highp in frag shaders, it should complain anyways.
         resources.FragmentPrecisionHigh = mDisableFragHighP ? 0 : 1;
 
         if (gl->WorkAroundDriverBugs()) {
 #ifdef XP_MACOSX
-            if (gl->Vendor() == gl::GLContext::VendorNVIDIA) {
+            if (gl->Vendor() == gl::GLVendor::NVIDIA) {
                 // Work around bug 890432
                 resources.MaxExpressionComplexity = 1000;
             }
 #endif
         }
 
         // We're storing an actual instance of StripComments because, if we don't, the 
         // cleanSource nsAString instance will be destroyed before the reference is
@@ -3217,22 +3218,22 @@ WebGLContext::CompileShader(WebGLShader 
 
         if (useShaderSourceTranslation) {
             compileOptions |= SH_OBJECT_CODE
                             | SH_MAP_LONG_VARIABLE_NAMES;
 
 #ifdef XP_MACOSX
             if (gl->WorkAroundDriverBugs()) {
                 // Work around bug 665578 and bug 769810
-                if (gl->Vendor() == gl::GLContext::VendorATI) {
+                if (gl->Vendor() == gl::GLVendor::ATI) {
                     compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
                 }
 
                 // Work around bug 735560
-                if (gl->Vendor() == gl::GLContext::VendorIntel) {
+                if (gl->Vendor() == gl::GLVendor::Intel) {
                     compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
                 }
             }
 #endif
         }
 
 #ifdef WEBGL2_BYPASS_ANGLE
         if (!ShCompile(compiler, &angleShaderCode, 1, compileOptions)) {
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -975,17 +975,17 @@ WebGLContext::InitAndValidateGL()
         //   http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=261472
         // Note that this used to cause crashes on old ATI drivers... hopefully not a significant
         // problem anymore. See bug 602183.
         gl->fEnable(LOCAL_GL_POINT_SPRITE);
     }
 
 #ifdef XP_MACOSX
     if (gl->WorkAroundDriverBugs() &&
-        gl->Vendor() == gl::GLContext::VendorATI) {
+        gl->Vendor() == gl::GLVendor::ATI) {
         // The Mac ATI driver, in all known OSX version up to and including 10.8,
         // renders points sprites upside-down. Apple bug 11778921
         gl->fPointParameterf(LOCAL_GL_POINT_SPRITE_COORD_ORIGIN, LOCAL_GL_LOWER_LEFT);
     }
 #endif
 
     // Check the shader validator pref
     NS_ENSURE_TRUE(Preferences::GetRootBranch(), false);
--- a/content/canvas/src/WebGLContextVertices.cpp
+++ b/content/canvas/src/WebGLContextVertices.cpp
@@ -719,17 +719,17 @@ void WebGLContext::Draw_cleanup()
 
     if (!mBoundFramebuffer) {
         Invalidate();
         mShouldPresent = true;
         mIsScreenCleared = false;
     }
 
     if (gl->WorkAroundDriverBugs()) {
-        if (gl->Renderer() == gl::GLContext::RendererTegra) {
+        if (gl->Renderer() == gl::GLRenderer::Tegra) {
             mDrawCallsSinceLastFlush++;
 
             if (mDrawCallsSinceLastFlush >= MAX_DRAW_CALLS_SINCE_FLUSH) {
                 gl->fFlush();
                 mDrawCallsSinceLastFlush = 0;
             }
         }
     }
--- a/content/canvas/src/WebGLRenderbuffer.cpp
+++ b/content/canvas/src/WebGLRenderbuffer.cpp
@@ -190,17 +190,17 @@ WebGLRenderbuffer::FramebufferRenderbuff
 GLint
 WebGLRenderbuffer::GetRenderbufferParameter(GLenum target, GLenum pname) const {
     GLContext* gl = mContext->gl;
 
     switch (pname) {
         case LOCAL_GL_RENDERBUFFER_STENCIL_SIZE: {
             if (NeedsDepthStencilEmu(mContext->gl, InternalFormatForGL())) {
                 if (gl->WorkAroundDriverBugs() &&
-                    gl->Renderer() == GLContext::RendererTegra)
+                    gl->Renderer() == GLRenderer::Tegra)
                 {
                     return 8;
                 }
 
                 ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
 
                 GLint i = 0;
                 gl->fGetRenderbufferParameteriv(target, pname, &i);
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -1485,35 +1485,34 @@ nsEventStateManager::GetAccessKeyLabelPr
 void
 nsEventStateManager::HandleAccessKey(nsPresContext* aPresContext,
                                      WidgetKeyboardEvent* aEvent,
                                      nsEventStatus* aStatus,
                                      nsIDocShellTreeItem* aBubbledFrom,
                                      ProcessingAccessKeyState aAccessKeyState,
                                      int32_t aModifierMask)
 {
-  nsCOMPtr<nsISupports> pcContainer = aPresContext->GetContainerWeak();
+  nsCOMPtr<nsIDocShell> docShell = aPresContext->GetDocShell();
 
   // Alt or other accesskey modifier is down, we may need to do an accesskey
   if (mAccessKeys.Count() > 0 &&
-      aModifierMask == GetAccessModifierMaskFor(pcContainer)) {
+      aModifierMask == GetAccessModifierMaskFor(docShell)) {
     // Someone registered an accesskey.  Find and activate it.
     nsAutoTArray<uint32_t, 10> accessCharCodes;
     nsContentUtils::GetAccessKeyCandidates(aEvent, accessCharCodes);
     if (ExecuteAccessKey(accessCharCodes, aEvent->mFlags.mIsTrusted)) {
       *aStatus = nsEventStatus_eConsumeNoDefault;
       return;
     }
   }
 
   // after the local accesskey handling
   if (nsEventStatus_eConsumeNoDefault != *aStatus) {
     // checking all sub docshells
 
-    nsCOMPtr<nsIDocShellTreeNode> docShell(do_QueryInterface(pcContainer));
     if (!docShell) {
       NS_WARNING("no docShellTreeNode for presContext");
       return;
     }
 
     int32_t childCount;
     docShell->GetChildCount(&childCount);
     for (int32_t counter = 0; counter < childCount; counter++) {
@@ -1547,17 +1546,16 @@ nsEventStateManager::HandleAccessKey(nsP
         if (nsEventStatus_eConsumeNoDefault == *aStatus)
           break;
       }
     }
   }// if end . checking all sub docshell ends here.
 
   // bubble up the process to the parent docshell if necessary
   if (eAccessKeyProcessingDown != aAccessKeyState && nsEventStatus_eConsumeNoDefault != *aStatus) {
-    nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryInterface(pcContainer));
     if (!docShell) {
       NS_WARNING("no docShellTreeItem for presContext");
       return;
     }
 
     nsCOMPtr<nsIDocShellTreeItem> parentShellItem;
     docShell->GetParent(getter_AddRefs(parentShellItem));
     nsCOMPtr<nsIDocShell> parentDS = do_QueryInterface(parentShellItem);
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -17,17 +17,16 @@
 #include "mozilla/TimeStamp.h"
 #include "nsIFrame.h"
 #include "Units.h"
 
 class nsFrameLoader;
 class nsIContent;
 class nsIDocument;
 class nsIDocShell;
-class nsIDocShellTreeNode;
 class nsIDocShellTreeItem;
 class imgIContainer;
 class nsDOMDataTransfer;
 class MouseEnterLeaveDispatcher;
 class nsIMarkupDocumentViewer;
 class nsIScrollableFrame;
 class nsITimer;
 
--- a/content/html/content/src/HTMLFrameElement.cpp
+++ b/content/html/content/src/HTMLFrameElement.cpp
@@ -75,41 +75,16 @@ HTMLFrameElement::ParseAttribute(int32_t
       return ParseScrollingValue(aValue, aResult);
     }
   }
 
   return nsGenericHTMLFrameElement::ParseAttribute(aNamespaceID, aAttribute,
                                                    aValue, aResult);
 }
 
-void
-HTMLFrameElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                        nsRuleData* aData)
-{
-  nsGenericHTMLElement::MapScrollingAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
-}
-
-NS_IMETHODIMP_(bool)
-HTMLFrameElement::IsAttributeMapped(const nsIAtom* aAttribute) const
-{
-  static const MappedAttributeEntry* const map[] = {
-    sScrollingAttributeMap,
-    sCommonAttributeMap,
-  };
-  
-  return FindAttributeDependence(aAttribute, map);
-}
-
-nsMapRuleToAttributesFunc
-HTMLFrameElement::GetAttributeMappingFunction() const
-{
-  return &MapAttributesIntoRule;
-}
-
 JSObject*
 HTMLFrameElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return HTMLFrameElementBinding::Wrap(aCx, aScope, this);
 }
 
 } // namespace mozilla
 } // namespace dom
--- a/content/html/content/src/HTMLFrameElement.h
+++ b/content/html/content/src/HTMLFrameElement.h
@@ -32,18 +32,16 @@ public:
   // nsIDOMHTMLFrameElement
   NS_DECL_NSIDOMHTMLFRAMEELEMENT
 
   // nsIContent
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) MOZ_OVERRIDE;
-  NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
-  nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   // WebIDL API
   // The XPCOM GetFrameBorder is OK for us
   void SetFrameBorder(const nsAString& aFrameBorder, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::frameborder, aFrameBorder, aError);
   }
--- a/content/html/content/src/HTMLIFrameElement.cpp
+++ b/content/html/content/src/HTMLIFrameElement.cpp
@@ -153,34 +153,32 @@ HTMLIFrameElement::MapAttributesIntoRule
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
       if (value && value->Type() == nsAttrValue::eInteger)
         height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
       else if (value && value->Type() == nsAttrValue::ePercent)
         height->SetPercentValue(value->GetPercentValue());
     }
   }
 
-  nsGenericHTMLElement::MapScrollingAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLIFrameElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::width },
     { &nsGkAtoms::height },
     { &nsGkAtoms::frameborder },
     { nullptr },
   };
 
   static const MappedAttributeEntry* const map[] = {
     attributes,
-    sScrollingAttributeMap,
     sImageAlignAttributeMap,
     sCommonAttributeMap,
   };
   
   return FindAttributeDependence(aAttribute, map);
 }
 
 
@@ -215,18 +213,18 @@ HTMLIFrameElement::AfterSetAttr(int32_t 
                                 bool aNotify)
 {
   if (aName == nsGkAtoms::sandbox && aNameSpaceID == kNameSpaceID_None && mFrameLoader) {
     // If we have an nsFrameLoader, apply the new sandbox flags.
     // Since this is called after the setter, the sandbox flags have
     // alreay been updated.
     mFrameLoader->ApplySandboxFlags(GetSandboxFlags());
   }
-  return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
-                                            aNotify);
+  return nsGenericHTMLFrameElement::AfterSetAttr(aNameSpaceID, aName, aValue,
+                                                 aNotify);
 }
 
 nsresult
 HTMLIFrameElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify)
 {
   // Invoke on the superclass.
   nsresult rv = nsGenericHTMLFrameElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
--- a/content/html/content/src/moz.build
+++ b/content/html/content/src/moz.build
@@ -166,19 +166,19 @@ include('/ipc/chromium/chromium-config.m
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
     '/content/base/src',
     '/content/canvas/src',
     '/content/events/src',
     '/content/html/document/src',
     '/content/media/',
-    '/content/xbl/src',
     '/content/xul/content/src',
     '/dom/base',
+    '/dom/xbl',
     '/editor/libeditor/base',
     '/editor/libeditor/text',
     '/editor/txmgr/src',
     '/layout/forms',
     '/layout/generic',
     '/layout/style',
     '/layout/tables',
     '/layout/xul',
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -1426,22 +1426,16 @@ nsGenericHTMLElement::sBackgroundAttribu
 };
 
 /* static */ const Element::MappedAttributeEntry
 nsGenericHTMLElement::sBackgroundColorAttributeMap[] = {
   { &nsGkAtoms::bgcolor },
   { nullptr }
 };
 
-/* static */ const Element::MappedAttributeEntry
-nsGenericHTMLElement::sScrollingAttributeMap[] = {
-  { &nsGkAtoms::scrolling },
-  { nullptr }
-};
-
 void
 nsGenericHTMLElement::MapImageAlignAttributeInto(const nsMappedAttributes* aAttributes,
                                                  nsRuleData* aRuleData)
 {
   if (aRuleData->mSIDs & (NS_STYLE_INHERIT_BIT(Display) |
                           NS_STYLE_INHERIT_BIT(TextReset))) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
     if (value && value->Type() == nsAttrValue::eEnum) {
@@ -1670,61 +1664,16 @@ nsGenericHTMLElement::MapBGColorInto(con
 void
 nsGenericHTMLElement::MapBackgroundAttributesInto(const nsMappedAttributes* aAttributes,
                                                   nsRuleData* aData)
 {
   MapBackgroundInto(aAttributes, aData);
   MapBGColorInto(aAttributes, aData);
 }
 
-void
-nsGenericHTMLElement::MapScrollingAttributeInto(const nsMappedAttributes* aAttributes,
-                                                nsRuleData* aData)
-{
-  if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)))
-    return;
-
-  // scrolling
-  nsCSSValue* overflowValues[2] = {
-    aData->ValueForOverflowX(),
-    aData->ValueForOverflowY(),
-  };
-  for (uint32_t i = 0; i < ArrayLength(overflowValues); ++i) {
-    if (overflowValues[i]->GetUnit() == eCSSUnit_Null) {
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::scrolling);
-      if (value && value->Type() == nsAttrValue::eEnum) {
-        int32_t mappedValue;
-        switch (value->GetEnumValue()) {
-          case NS_STYLE_FRAME_ON:
-          case NS_STYLE_FRAME_SCROLL:
-          case NS_STYLE_FRAME_YES:
-            mappedValue = NS_STYLE_OVERFLOW_SCROLL;
-            break;
-
-          case NS_STYLE_FRAME_OFF:
-          case NS_STYLE_FRAME_NOSCROLL:
-          case NS_STYLE_FRAME_NO:
-            mappedValue = NS_STYLE_OVERFLOW_HIDDEN;
-            break;
-        
-          case NS_STYLE_FRAME_AUTO:
-            mappedValue = NS_STYLE_OVERFLOW_AUTO;
-            break;
-
-          default:
-            NS_NOTREACHED("unexpected value");
-            mappedValue = NS_STYLE_OVERFLOW_AUTO;
-            break;
-        }
-        overflowValues[i]->SetIntValue(mappedValue, eCSSUnit_Enumerated);
-      }
-    }
-  }
-}
-
 //----------------------------------------------------------------------
 
 nsresult
 nsGenericHTMLElement::SetAttrHelper(nsIAtom* aAttr, const nsAString& aValue)
 {
   return SetAttr(kNameSpaceID_None, aAttr, aValue, true);
 }
 
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -748,17 +748,16 @@ public:
 
   static const MappedAttributeEntry sCommonAttributeMap[];
   static const MappedAttributeEntry sImageMarginSizeAttributeMap[];
   static const MappedAttributeEntry sImageBorderAttributeMap[];
   static const MappedAttributeEntry sImageAlignAttributeMap[];
   static const MappedAttributeEntry sDivAlignAttributeMap[];
   static const MappedAttributeEntry sBackgroundAttributeMap[];
   static const MappedAttributeEntry sBackgroundColorAttributeMap[];
-  static const MappedAttributeEntry sScrollingAttributeMap[];
   
   /**
    * Helper to map the align attribute into a style struct.
    *
    * @param aAttributes the list of attributes to map
    * @param aData the returned rule data [INOUT]
    * @see GetAttributeMappingFunction
    */
--- a/content/html/content/src/nsGenericHTMLFrameElement.cpp
+++ b/content/html/content/src/nsGenericHTMLFrameElement.cpp
@@ -2,26 +2,32 @@
 /* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=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 "nsGenericHTMLFrameElement.h"
 
-#include "nsIDOMDocument.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsContentUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ErrorResult.h"
-#include "nsIAppsService.h"
-#include "nsServiceManagerUtils.h"
+#include "GeckoProfiler.h"
 #include "mozIApplication.h"
+#include "nsAttrValueInlines.h"
+#include "nsContentUtils.h"
+#include "nsIAppsService.h"
+#include "nsIDocShell.h"
+#include "nsIDOMDocument.h"
+#include "nsIFrame.h"
+#include "nsIInterfaceRequestorUtils.h"
 #include "nsIPermissionManager.h"
-#include "GeckoProfiler.h"
+#include "nsIPresShell.h"
+#include "nsIScrollable.h"
+#include "nsPresContext.h"
+#include "nsServiceManagerUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericHTMLFrameElement)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement,
                                                   nsGenericHTMLElement)
@@ -270,16 +276,65 @@ nsGenericHTMLFrameElement::UnsetAttr(int
     if (docShell) {
       docShell->SetName(EmptyString());
     }
   }
 
   return NS_OK;
 }
 
+/* static */ int32_t
+nsGenericHTMLFrameElement::MapScrollingAttribute(const nsAttrValue* aValue)
+{
+  int32_t mappedValue = nsIScrollable::Scrollbar_Auto;
+  if (aValue && aValue->Type() == nsAttrValue::eEnum) {
+    switch (aValue->GetEnumValue()) {
+      case NS_STYLE_FRAME_OFF:
+      case NS_STYLE_FRAME_NOSCROLL:
+      case NS_STYLE_FRAME_NO:
+        mappedValue = nsIScrollable::Scrollbar_Never;
+        break;
+    }
+  }
+  return mappedValue;
+}
+
+/* virtual */ nsresult
+nsGenericHTMLFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+                                        const nsAttrValue* aValue,
+                                        bool aNotify)
+{
+  if (aName == nsGkAtoms::scrolling && aNameSpaceID == kNameSpaceID_None) {
+    if (mFrameLoader) {
+      nsIDocShell* docshell = mFrameLoader->GetExistingDocShell();
+      nsCOMPtr<nsIScrollable> scrollable = do_QueryInterface(docshell);
+      if (scrollable) {
+        int32_t cur;
+        scrollable->GetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X, &cur);
+        int32_t val = MapScrollingAttribute(aValue);
+        if (cur != val) {
+          scrollable->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X, val);
+          scrollable->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y, val);
+          nsRefPtr<nsPresContext> presContext;
+          docshell->GetPresContext(getter_AddRefs(presContext));
+          nsIPresShell* shell = presContext ? presContext->GetPresShell() : nullptr;
+          nsIFrame* rootScroll = shell ? shell->GetRootScrollFrame() : nullptr;
+          if (rootScroll) {
+            shell->FrameNeedsReflow(rootScroll, nsIPresShell::eStyleChange,
+                                    NS_FRAME_IS_DIRTY);
+          }
+        }
+      }
+    }
+  }
+
+  return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
+                                            aNotify);
+}
+
 void
 nsGenericHTMLFrameElement::DestroyContent()
 {
   if (mFrameLoader) {
     mFrameLoader->Destroy();
     mFrameLoader = nullptr;
   }
 
--- a/content/html/content/src/nsGenericHTMLFrameElement.h
+++ b/content/html/content/src/nsGenericHTMLFrameElement.h
@@ -56,28 +56,42 @@ public:
   {
     return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
   }
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            bool aNotify) MOZ_OVERRIDE;
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify) MOZ_OVERRIDE;
+  virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+                                const nsAttrValue* aValue,
+                                bool aNotify) MOZ_OVERRIDE;
   virtual void DestroyContent() MOZ_OVERRIDE;
 
   nsresult CopyInnerTo(mozilla::dom::Element* aDest);
 
   virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsGenericHTMLFrameElement,
                                                      nsGenericHTMLElement)
 
   void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& aError);
 
   static bool BrowserFramesEnabled();
+
+  /**
+   * Helper method to map a HTML 'scrolling' attribute value to a nsIScrollable
+   * enum value.  scrolling="no" (and its synonyms) maps to
+   * nsIScrollable::Scrollbar_Never, and anything else (including nullptr) maps
+   * to nsIScrollable::Scrollbar_Auto.
+   * @param aValue the attribute value to map or nullptr
+   * @return nsIScrollable::Scrollbar_Never or nsIScrollable::Scrollbar_Auto
+   */
+  static int32_t MapScrollingAttribute(const nsAttrValue* aValue);
+
 protected:
   // This doesn't really ensure a frame loade in all cases, only when
   // it makes sense.
   void EnsureFrameLoader();
   nsresult LoadSrc();
   nsIDocument* GetContentDocument();
   nsresult GetContentDocument(nsIDOMDocument** aContentDocument);
   already_AddRefed<nsPIDOMWindow> GetContentWindow();
--- a/content/moz.build
+++ b/content/moz.build
@@ -9,13 +9,12 @@ PARALLEL_DIRS += [
     'canvas',
     'events',
     'html',
     'mathml/content/src',
     'media',
     'svg',
     'xml',
     'xul',
-    'xbl',
 ]
 
 TEST_TOOL_DIRS += ['test']
 
--- a/content/svg/content/src/SVGPathData.cpp
+++ b/content/svg/content/src/SVGPathData.cpp
@@ -812,17 +812,17 @@ SVGPathData::ToPathForLengthOrPositionMe
   // Since the path that we return will not be used for painting it doesn't
   // matter what we pass to BuildPath as aFillRule. Hawever, we do want to
   // pass something other than NS_STYLE_STROKE_LINECAP_SQUARE as aStrokeLineCap
   // to avoid the insertion of extra little lines (by
   // ApproximateZeroLengthSubpathSquareCaps), in which case the value that we
   // pass as aStrokeWidth doesn't matter (since it's only used to determine the
   // length of those extra little lines).
 
-  return BuildPath(FILL_WINDING, NS_STYLE_STROKE_LINECAP_BUTT, 0);
+  return BuildPath(FillRule::FILL_WINDING, NS_STYLE_STROKE_LINECAP_BUTT, 0);
 }
 
 static double
 AngleOfVector(const gfxPoint& aVector)
 {
   // C99 says about atan2 "A domain error may occur if both arguments are
   // zero" and "On a domain error, the function returns an implementation-
   // defined value". In the case of atan2 the implementation-defined value
--- a/content/svg/content/src/moz.build
+++ b/content/svg/content/src/moz.build
@@ -247,18 +247,18 @@ FAIL_ON_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
     '/content/base/src',
     '/content/events/src',
     '/content/html/content/src',
-    '/content/xbl/src',
     '/content/xml/content/src',
     '/dom',
     '/dom/smil',
+    '/dom/xbl',
     '/layout/generic',
     '/layout/style',
     '/layout/svg',
     '/layout/xul',
 ]
 
--- a/content/svg/content/src/nsSVGPathGeometryElement.cpp
+++ b/content/svg/content/src/nsSVGPathGeometryElement.cpp
@@ -84,30 +84,30 @@ nsSVGPathGeometryElement::CreatePathBuil
   // with the path that we return.
 
   return drawTarget->CreatePathBuilder(GetFillRule());
 }
 
 FillRule
 nsSVGPathGeometryElement::GetFillRule()
 {
-  FillRule fillRule = FILL_WINDING; // Equivalent to NS_STYLE_FILL_RULE_NONZERO
+  FillRule fillRule = FillRule::FILL_WINDING; // Equivalent to NS_STYLE_FILL_RULE_NONZERO
 
   nsRefPtr<nsStyleContext> styleContext =
     nsComputedDOMStyle::GetStyleContextForElementNoFlush(this, nullptr,
                                                          nullptr);
   
   if (styleContext) {
     MOZ_ASSERT(styleContext->StyleSVG()->mFillRule ==
                                            NS_STYLE_FILL_RULE_NONZERO ||
                styleContext->StyleSVG()->mFillRule ==
                                            NS_STYLE_FILL_RULE_EVENODD);
 
     if (styleContext->StyleSVG()->mFillRule == NS_STYLE_FILL_RULE_EVENODD) {
-      fillRule = FILL_EVEN_ODD;
+      fillRule = FillRule::FILL_EVEN_ODD;
     }
   } else {
     // ReportToConsole
     NS_WARNING("Couldn't get style context for content in GetFillRule");
   }
 
   return fillRule;
 }
deleted file mode 100644
--- a/content/xbl/moz.build
+++ /dev/null
@@ -1,8 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-PARALLEL_DIRS += ['src', 'builtin']
-TEST_DIRS += ['test']
--- a/content/xul/content/src/moz.build
+++ b/content/xul/content/src/moz.build
@@ -16,18 +16,18 @@ if CONFIG['MOZ_XUL']:
 FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
     '../../document/src',
     '../../templates/src',
     '/content/base/src',
     '/content/events/src',
     '/content/html/content/src',
-    '/content/xbl/src',
     '/content/xml/content/src',
     '/content/xml/document/src',
+    '/dom/xbl',
     '/layout/generic',
     '/layout/style',
     '/layout/xul',
     '/xpcom/ds',
 ]
 
 FINAL_LIBRARY = 'gklayout'
--- a/content/xul/document/src/moz.build
+++ b/content/xul/document/src/moz.build
@@ -19,22 +19,22 @@ if CONFIG['MOZ_XUL']:
 
 FAIL_ON_WARNINGS = True
 
 MSVC_ENABLE_PGO = True
 
 LOCAL_INCLUDES += [
     '/content/base/src',
     '/content/events/src',
-    '/content/xbl/src',
     '/content/xml/document/src',
     '/content/xul/content/src',
     '/content/xul/templates/src',
     '/docshell/base',
     '/dom/base',
+    '/dom/xbl',
     '/layout/base',
     '/layout/generic',
     '/layout/style',
     '/layout/xul',
     '/xpcom/ds',
 ]
 
 FINAL_LIBRARY = 'gklayout'
--- a/docshell/base/LoadContext.h
+++ b/docshell/base/LoadContext.h
@@ -49,16 +49,31 @@ public:
     , mIsContent(aToCopy.mIsContent)
     , mUsePrivateBrowsing(aToCopy.mUsePrivateBrowsing)
     , mIsInBrowserElement(aInBrowser)
 #ifdef DEBUG
     , mIsNotNull(aToCopy.mIsNotNull)
 #endif
   {}
 
+  LoadContext(dom::Element* aTopFrameElement,
+              uint32_t aAppId,
+              bool aIsContent,
+              bool aUsePrivateBrowsing,
+              bool aIsInBrowserElement)
+    : mTopFrameElement(do_GetWeakReference(aTopFrameElement))
+    , mAppId(aAppId)
+    , mIsContent(aIsContent)
+    , mUsePrivateBrowsing(aUsePrivateBrowsing)
+    , mIsInBrowserElement(aIsInBrowserElement)
+#ifdef DEBUG
+    , mIsNotNull(true)
+#endif
+  {}
+
   // Constructor taking reserved appId for the safebrowsing cookie.
   LoadContext(uint32_t aAppId)
     : mTopFrameElement(nullptr)
     , mAppId(aAppId)
     , mIsContent(false)
     , mUsePrivateBrowsing(false)
     , mIsInBrowserElement(false)
 #ifdef DEBUG
--- a/docshell/base/moz.build
+++ b/docshell/base/moz.build
@@ -10,17 +10,16 @@ XPIDL_SOURCES += [
     'nsIContentViewer.idl',
     'nsIContentViewerContainer.idl',
     'nsIContentViewerEdit.idl',
     'nsIContentViewerFile.idl',
     'nsIDocCharset.idl',
     'nsIDocShell.idl',
     'nsIDocShellLoadInfo.idl',
     'nsIDocShellTreeItem.idl',
-    'nsIDocShellTreeNode.idl',
     'nsIDocShellTreeOwner.idl',
     'nsIDocumentLoaderFactory.idl',
     'nsIDownloadHistory.idl',
     'nsIGlobalHistory2.idl',
     'nsILoadContext.idl',
     'nsIMarkupDocumentViewer.idl',
     'nsIPrivacyTransitionObserver.idl',
     'nsIReflowObserver.idl',
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -969,17 +969,16 @@ nsDocShell::DestroyChildren()
 //*****************************************************************************   
 
 NS_IMPL_ADDREF_INHERITED(nsDocShell, nsDocLoader)
 NS_IMPL_RELEASE_INHERITED(nsDocShell, nsDocLoader)
 
 NS_INTERFACE_MAP_BEGIN(nsDocShell)
     NS_INTERFACE_MAP_ENTRY(nsIDocShell)
     NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)
-    NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeNode)
     NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)
     NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
     NS_INTERFACE_MAP_ENTRY(nsIScrollable)
     NS_INTERFACE_MAP_ENTRY(nsITextScroll)
     NS_INTERFACE_MAP_ENTRY(nsIDocCharset)
     NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)
     NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
     NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
@@ -1579,16 +1578,19 @@ nsDocShell::LoadURI(nsIURI * aURI,
         flags |= INTERNAL_LOAD_FLAGS_INHERIT_OWNER;
 
     if (!sendReferrer)
         flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER;
             
     if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP)
         flags |= INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
 
+    if (aLoadFlags & LOAD_FLAGS_FIXUP_SCHEME_TYPOS)
+        flags |= INTERNAL_LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
+
     if (aLoadFlags & LOAD_FLAGS_FIRST_LOAD)
         flags |= INTERNAL_LOAD_FLAGS_FIRST_LOAD;
 
     if (aLoadFlags & LOAD_FLAGS_BYPASS_CLASSIFIER)
         flags |= INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER;
 
     if (aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_COOKIES)
         flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES;
@@ -3603,20 +3605,16 @@ nsDocShell::GetHistoryID(uint64_t* aID)
 
 NS_IMETHODIMP
 nsDocShell::GetIsInUnload(bool* aIsInUnload)
 {
     *aIsInUnload = mFiredUnloadEvent;
     return NS_OK;
 }
 
-//*****************************************************************************
-// nsDocShell::nsIDocShellTreeNode
-//*****************************************************************************   
-
 NS_IMETHODIMP
 nsDocShell::GetChildCount(int32_t * aChildCount)
 {
     NS_ENSURE_ARG_POINTER(aChildCount);
     *aChildCount = mChildList.Length();
     return NS_OK;
 }
 
@@ -4272,16 +4270,19 @@ nsDocShell::LoadURI(const char16_t * aUR
         // Call the fixup object.  This will clobber the rv from NS_NewURI
         // above, but that's fine with us.  Note that we need to do this even
         // if NS_NewURI returned a URI, because fixup handles nested URIs, etc
         // (things like view-source:mozilla.org for example).
         uint32_t fixupFlags = 0;
         if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
           fixupFlags |= nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
         }
+        if (aLoadFlags & LOAD_FLAGS_FIXUP_SCHEME_TYPOS) {
+          fixupFlags |= nsIURIFixup::FIXUP_FLAG_FIX_SCHEME_TYPOS;
+        }
         nsCOMPtr<nsIInputStream> fixupStream;
         rv = sURIFixup->CreateFixupURI(uriString, fixupFlags,
                                        getter_AddRefs(fixupStream),
                                        getter_AddRefs(uri));
         if (fixupStream) {
             // CreateFixupURI only returns a post data stream if it succeeded
             // and changed the URI, in which case we should override the
             // passed-in post data.
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -6,17 +6,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsDocShell_h__
 #define nsDocShell_h__
 
 #include "nsITimer.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
-#include "nsIDocShellTreeNode.h"
 #include "nsIBaseWindow.h"
 #include "nsIScrollable.h"
 #include "nsITextScroll.h"
 #include "nsIContentViewerContainer.h"
 #include "nsIDOMStorageManager.h"
 #include "nsDocLoader.h"
 #include "mozilla/WeakPtr.h"
 
@@ -150,17 +149,16 @@ public:
     NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
 
     virtual nsresult Init();
 
     NS_DECL_ISUPPORTS_INHERITED
 
     NS_DECL_NSIDOCSHELL
     NS_DECL_NSIDOCSHELLTREEITEM
-    NS_DECL_NSIDOCSHELLTREENODE
     NS_DECL_NSIWEBNAVIGATION
     NS_DECL_NSIBASEWINDOW
     NS_DECL_NSISCROLLABLE
     NS_DECL_NSITEXTSCROLL
     NS_DECL_NSIDOCCHARSET
     NS_DECL_NSIINTERFACEREQUESTOR
     NS_DECL_NSIWEBPROGRESSLISTENER
     NS_DECL_NSIREFRESHURI
--- a/docshell/base/nsDocShellEnumerator.cpp
+++ b/docshell/base/nsDocShellEnumerator.cpp
@@ -3,17 +3,16 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "nsDocShellEnumerator.h"
 
 #include "nsIDocShellTreeItem.h"
-#include "nsIDocShellTreeNode.h"
 
 nsDocShellEnumerator::nsDocShellEnumerator(int32_t inEnumerationDirection)
 : mRootItem(nullptr)
 , mCurIndex(0)
 , mDocShellType(nsIDocShellTreeItem::typeAll)
 , mArrayValid(false)
 , mEnumerationDirection(inEnumerationDirection)
 {
@@ -118,60 +117,56 @@ nsresult nsDocShellEnumerator::BuildDocS
   inItemArray.Clear();
   nsCOMPtr<nsIDocShellTreeItem> item = do_QueryReferent(mRootItem);
   return BuildArrayRecursive(item, inItemArray);
 }
 
 nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsWeakPtr>& inItemArray)
 {
   nsresult rv;
-  nsCOMPtr<nsIDocShellTreeNode> itemAsNode = do_QueryInterface(inItem, &rv);
-  if (NS_FAILED(rv)) return rv;
 
   int32_t   itemType;
   // add this item to the array
   if ((mDocShellType == nsIDocShellTreeItem::typeAll) ||
       (NS_SUCCEEDED(inItem->GetItemType(&itemType)) && (itemType == mDocShellType)))
   {
     if (!inItemArray.AppendElement(do_GetWeakReference(inItem)))
       return NS_ERROR_OUT_OF_MEMORY;
   }
 
   int32_t   numChildren;
-  rv = itemAsNode->GetChildCount(&numChildren);
+  rv = inItem->GetChildCount(&numChildren);
   if (NS_FAILED(rv)) return rv;
   
   for (int32_t i = 0; i < numChildren; ++i)
   {
     nsCOMPtr<nsIDocShellTreeItem> curChild;
-    rv = itemAsNode->GetChildAt(i, getter_AddRefs(curChild));
+    rv = inItem->GetChildAt(i, getter_AddRefs(curChild));
     if (NS_FAILED(rv)) return rv;
       
     rv = BuildArrayRecursive(curChild, inItemArray);
     if (NS_FAILED(rv)) return rv;
   }
 
   return NS_OK;
 }
 
 
 nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray<nsWeakPtr>& inItemArray)
 {
   nsresult rv;
-  nsCOMPtr<nsIDocShellTreeNode> itemAsNode = do_QueryInterface(inItem, &rv);
-  if (NS_FAILED(rv)) return rv;
 
   int32_t   numChildren;
-  rv = itemAsNode->GetChildCount(&numChildren);
+  rv = inItem->GetChildCount(&numChildren);
   if (NS_FAILED(rv)) return rv;
   
   for (int32_t i = numChildren - 1; i >= 0; --i)
   {
     nsCOMPtr<nsIDocShellTreeItem> curChild;
-    rv = itemAsNode->GetChildAt(i, getter_AddRefs(curChild));
+    rv = inItem->GetChildAt(i, getter_AddRefs(curChild));
     if (NS_FAILED(rv)) return rv;
       
     rv = BuildArrayRecursive(curChild, inItemArray);
     if (NS_FAILED(rv)) return rv;
   }
 
   int32_t   itemType;
   // add this item to the array
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -39,17 +39,17 @@ interface nsIDOMStorage;
 interface nsIPrincipal;
 interface nsIWebBrowserPrint;
 interface nsIVariant;
 interface nsIPrivacyTransitionObserver;
 interface nsIReflowObserver;
 
 typedef unsigned long nsLoadFlags;
 
-[scriptable, builtinclass, uuid(55ca6545-7ce4-49ad-8117-8286ca9c61bb)]
+[scriptable, builtinclass, uuid(e3ea830d-2614-4aeb-9ec3-b8f744b03b80)]
 interface nsIDocShell : nsIDocShellTreeItem
 {
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
    * in the object implementing	this interface.  If it can't be loaded here
    * however, the URL dispatcher will go through its normal process of content
    * loading.
    *
@@ -106,16 +106,18 @@ interface nsIDocShell : nsIDocShellTreeI
   const long INTERNAL_LOAD_FLAGS_FIRST_LOAD              = 0x8;
 
   const long INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER       = 0x10;
   const long INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES     = 0x20;
 
   // Whether the load should be treated as srcdoc load, rather than a URI one.
   const long INTERNAL_LOAD_FLAGS_IS_SRCDOC               = 0x40;
 
+  const long INTERNAL_LOAD_FLAGS_FIXUP_SCHEME_TYPOS      = 0x80;
+
   /**
    * Loads the given URI.  This method is identical to loadURI(...) except
    * that its parameter list is broken out instead of being packaged inside
    * of an nsIDocShellLoadInfo object...
    *
    * @param aURI            - The URI to load.
    * @param aReferrer       - Referring URI
    * @param aOwner          - Owner (security principal) 
--- a/docshell/base/nsIDocShellTreeItem.idl
+++ b/docshell/base/nsIDocShellTreeItem.idl
@@ -1,27 +1,27 @@
 /* -*- Mode: IDL; tab-width: 4; 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 "nsIDocShellTreeNode.idl"
+#include "nsISupports.idl"
 
 interface nsIDocShellTreeOwner;
 
 
 /**
  * The nsIDocShellTreeItem supplies the methods that are required of any item
  * that wishes to be able to live within the docshell tree either as a middle
  * node or a leaf. 
  */
 
-[scriptable, uuid(e35bbb39-985b-4d62-81da-73c330222e5f)]
-interface nsIDocShellTreeItem : nsIDocShellTreeNode
+[scriptable, uuid(cb16a98d-a9e4-4ee2-a450-709b92ad8a89)]
+interface nsIDocShellTreeItem : nsISupports
 {
 	/*
 	name of the DocShellTreeItem
 	*/
 	attribute AString name;
 
         /**
          * Compares the provided name against the item's name and
@@ -120,10 +120,59 @@ interface nsIDocShellTreeItem : nsIDocSh
 	Implementers of this interface are guaranteed that when treeOwner is
 	set that the poitner is valid without having to addref.
 	
 	Further note however when others try to get the interface it should be 
 	addref'd before handing it to them. 
 	*/
 	readonly attribute nsIDocShellTreeOwner treeOwner;
 	[noscript] void setTreeOwner(in nsIDocShellTreeOwner treeOwner);
+
+	/*
+	The current number of DocShells which are immediate children of the 
+	this object.
+	*/
+	readonly attribute long childCount;
+
+	/*
+	Add a new child DocShellTreeItem.  Adds to the end of the list.
+	Note that this does NOT take a reference to the child.  The child stays
+	alive only as long as it's referenced from outside the docshell tree.
+	@throws NS_ERROR_ILLEGAL_VALUE if child corresponds to the same
+	        object as this treenode or an ancestor of this treenode
+	@throws NS_ERROR_UNEXPECTED if this node is a leaf in the tree.
+	*/
+	void addChild(in nsIDocShellTreeItem child);
+
+	/*
+	Removes a child DocShellTreeItem.
+	@throws NS_ERROR_UNEXPECTED if this node is a leaf in the tree.
+	*/
+	void removeChild(in nsIDocShellTreeItem child);
+
+	/**
+	 * Return the child at the index requested.  This is 0-based.
+	 *
+	 * @throws NS_ERROR_UNEXPECTED if the index is out of range
+	 */
+	nsIDocShellTreeItem getChildAt(in long index);
+
+	/*
+	Return the child DocShellTreeItem with the specified name.
+	aName - This is the name of the item that is trying to be found.
+	aRecurse - Is used to tell the function to recurse through children.
+		Note, recursion will only happen through items of the same type.
+	aSameType - If this is set only children of the same type will be returned.
+	aRequestor - This is the docshellTreeItem that is requesting the find.  This
+		parameter is used when recursion is being used to avoid searching the same
+		tree again when a child has asked a parent to search for children.
+	aOriginalRequestor - The original treeitem that made the request, if any.
+    	This is used to ensure that we don't run into cross-site issues.
+
+	Note the search is depth first when recursing.
+	*/
+	nsIDocShellTreeItem findChildWithName(in wstring aName,
+	                                      in boolean aRecurse,
+	                                      in boolean aSameType,
+	                                      in nsIDocShellTreeItem aRequestor,
+	                                      in nsIDocShellTreeItem aOriginalRequestor);
 };
 
deleted file mode 100644
--- a/docshell/base/nsIDocShellTreeNode.idl
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIDocShellTreeItem;
-
-/**
- * The nsIDocShellTreeNode supplies the methods for interacting with children
- * of a docshell.  These are essentially the methods that turn a single docshell
- * into a docshell tree. 
- */
-
-/*
- * Long-term, we probably want to merge this interface into
- * nsIDocShellTreeItem.  Need to eliminate uses of this interface
- * first.
- */
-
-[scriptable, uuid(37f1ab73-f224-44b1-82f0-d2834ab1cec0)]
-interface nsIDocShellTreeNode : nsISupports
-{
-	/*
-	The current number of DocShells which are immediate children of the 
-	this object.
-	*/
-	readonly attribute long childCount;
-
-	/*
-	Add a new child DocShellTreeItem.  Adds to the end of the list.
-	Note that this does NOT take a reference to the child.  The child stays
-	alive only as long as it's referenced from outside the docshell tree.
-	@throws NS_ERROR_ILLEGAL_VALUE if child corresponds to the same
-	        object as this treenode or an ancestor of this treenode
-	@throws NS_ERROR_UNEXPECTED if this node is a leaf in the tree.
-	*/
-	void addChild(in nsIDocShellTreeItem child);
-
-	/*
-	Removes a child DocShellTreeItem.
-	@throws NS_ERROR_UNEXPECTED if this node is a leaf in the tree.
-	*/
-	void removeChild(in nsIDocShellTreeItem child);
-
-	/**
-	 * Return the child at the index requested.  This is 0-based.
-	 *
-	 * @throws NS_ERROR_UNEXPECTED if the index is out of range
-	 */
-	nsIDocShellTreeItem getChildAt(in long index);
-
-	/*
-	Return the child DocShellTreeItem with the specified name.
-	aName - This is the name of the item that is trying to be found.
-	aRecurse - Is used to tell the function to recurse through children.
-		Note, recursion will only happen through items of the same type.
-	aSameType - If this is set only children of the same type will be returned.
-	aRequestor - This is the docshellTreeItem that is requesting the find.  This
-		parameter is used when recursion is being used to avoid searching the same
-		tree again when a child has asked a parent to search for children.
-	aOriginalRequestor - The original treeitem that made the request, if any.
-    	This is used to ensure that we don't run into cross-site issues.
-
-	Note the search is depth first when recursing.
-	*/
-	nsIDocShellTreeItem findChildWithName(in wstring aName,
-	                                      in boolean aRecurse,
-	                                      in boolean aSameType,
-	                                      in nsIDocShellTreeItem aRequestor,
-	                                      in nsIDocShellTreeItem aOriginalRequestor);
-};
-
--- a/docshell/base/nsIWebNavigation.idl
+++ b/docshell/base/nsIWebNavigation.idl
@@ -11,17 +11,17 @@ interface nsISHistory;
 interface nsIURI;
 
 /**
  * The nsIWebNavigation interface defines an interface for navigating the web.
  * It provides methods and attributes to direct an object to navigate to a new
  * location, stop or restart an in process load, or determine where the object
  * has previously gone.
  */
-[scriptable, uuid(28404f7e-0f17-4dc3-a21a-2074d8659b02)]
+[scriptable, uuid(dbd6241d-c76e-42c0-9410-930589d803a2)]
 interface nsIWebNavigation : nsISupports
 {
   /**
    * Indicates if the object can go back.  If true this indicates that
    * there is back session history available for navigation.
    */
   readonly attribute boolean canGoBack;
 
@@ -186,16 +186,21 @@ interface nsIWebNavigation : nsISupports
 
   /**
    * This flag specifies that the URI may be submitted to a third-party
    * server for correction. This should only be applied to non-sensitive
    * URIs entered by users.  This flag must not be passed to Reload.
    */
   const unsigned long LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP = 0x100000;
 
+  /**
+   * This flag specifies that common scheme typos should be corrected.
+   */
+  const unsigned long LOAD_FLAGS_FIXUP_SCHEME_TYPOS = 0x200000;
+
   /* Note that flag 0x80000 is available. */
 
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
    * in the object implementing	this interface.  If it can't be loaded here
    * however, the URI dispatcher will go through its normal process of content
    * loading.
    *
--- a/docshell/shistory/src/nsSHistory.cpp
+++ b/docshell/shistory/src/nsSHistory.cpp
@@ -12,17 +12,16 @@
 #include "mozilla/Preferences.h"
 
 // Interfaces Needed
 #include "nsILayoutHistoryState.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellLoadInfo.h"
 #include "nsISHContainer.h"
 #include "nsIDocShellTreeItem.h"
-#include "nsIDocShellTreeNode.h"
 #include "nsIURI.h"
 #include "nsIContentViewer.h"
 #include "nsICacheService.h"
 #include "nsIObserverService.h"
 #include "prclist.h"
 #include "mozilla/Services.h"
 #include "nsTArray.h"
 #include "nsCOMArray.h"
@@ -1631,32 +1630,31 @@ nsSHistory::CompareFrames(nsISHEntry * a
     InitiateLoad(aNextEntry, aParent, aLoadType);
     return NS_OK;
   }
 
   /* The root entries are the same, so compare any child frames */
   int32_t pcnt=0, ncnt=0, dsCount=0;
   nsCOMPtr<nsISHContainer>  prevContainer(do_QueryInterface(aPrevEntry));
   nsCOMPtr<nsISHContainer>  nextContainer(do_QueryInterface(aNextEntry));
-  nsCOMPtr<nsIDocShellTreeNode> dsTreeNode(do_QueryInterface(aParent));
 
-  if (!dsTreeNode)
+  if (!aParent)
     return NS_ERROR_FAILURE;
   if (!prevContainer || !nextContainer)
     return NS_ERROR_FAILURE;
 
   prevContainer->GetChildCount(&pcnt);
   nextContainer->GetChildCount(&ncnt);
-  dsTreeNode->GetChildCount(&dsCount);
+  aParent->GetChildCount(&dsCount);
 
   // Create an array for child docshells.
   nsCOMArray<nsIDocShell> docshells;
   for (int32_t i = 0; i < dsCount; ++i) {
     nsCOMPtr<nsIDocShellTreeItem> treeItem;
-    dsTreeNode->GetChildAt(i, getter_AddRefs(treeItem));
+    aParent->GetChildAt(i, getter_AddRefs(treeItem));
     nsCOMPtr<nsIDocShell> shell = do_QueryInterface(treeItem);
     if (shell) {
       docshells.AppendObject(shell);
     }
   }
 
   // Search for something to load next.
   for (int32_t i = 0; i < ncnt; ++i) {
--- a/docshell/test/navigation/NavigationUtils.js
+++ b/docshell/test/navigation/NavigationUtils.js
@@ -106,17 +106,17 @@ function xpcEnumerateContentWindows(call
 
   var contentWindows = [];
 
   while (enumerator.hasMoreElements()) {
     var win = enumerator.getNext();
     if (/ChromeWindow/.exec(win)) {
       var docshellTreeNode = win.QueryInterface(Ci.nsIInterfaceRequestor)
                                 .getInterface(Ci.nsIWebNavigation)
-                                .QueryInterface(Ci.nsIDocShellTreeNode);
+                                .QueryInterface(Ci.nsIDocShellTreeItem);
       var childCount = docshellTreeNode.childCount;
       for (var i = 0; i < childCount; ++i) {
         var childTreeNode = docshellTreeNode.getChildAt(i);
 
         // we're only interested in content docshells
         if (SpecialPowers.unwrap(childTreeNode.itemType) != Ci.nsIDocShellTreeItem.typeContent)
           continue;
 
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -138,20 +138,20 @@ MSVC_ENABLE_PGO = True
 LOCAL_INCLUDES += [
     '../battery',
     '../bluetooth',
     '../media',
     '../network/src',
     '../src/geolocation',
     '../src/storage',
     '../time',
+    '../xbl',
     '/content/base/src',
     '/content/events/src',
     '/content/html/document/src',
-    '/content/xbl/src',
     '/content/xul/document/src',
     '/layout/generic',
     '/layout/style',
     '/layout/xul',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     LOCAL_INCLUDES += [
--- a/dom/base/nsDOMWindowList.cpp
+++ b/dom/base/nsDOMWindowList.cpp
@@ -33,18 +33,17 @@ NS_IMPL_RELEASE(nsDOMWindowList)
 NS_INTERFACE_MAP_BEGIN(nsDOMWindowList)
    NS_INTERFACE_MAP_ENTRY(nsIDOMWindowCollection)
    NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMETHODIMP
 nsDOMWindowList::SetDocShell(nsIDocShell* aDocShell)
 {
-  nsCOMPtr<nsIDocShellTreeNode> docShellAsNode(do_QueryInterface(aDocShell));
-  mDocShellNode = docShellAsNode; // Weak Reference
+  mDocShellNode = aDocShell; // Weak Reference
 
   return NS_OK;
 }
 
 void
 nsDOMWindowList::EnsureFresh()
 {
   nsCOMPtr<nsIWebNavigation> shellAsNav = do_QueryInterface(mDocShellNode);
--- a/dom/base/nsDOMWindowList.h
+++ b/dom/base/nsDOMWindowList.h
@@ -3,17 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef nsDOMWindowList_h___
 #define nsDOMWindowList_h___
 
 #include "nsCOMPtr.h"
 #include "nsIDOMWindowCollection.h"
 #include <stdint.h>
-#include "nsIDocShellTreeItem.h"
+#include "nsIDocShell.h"
 
 class nsIDocShell;
 class nsIDOMWindow;
 
 class nsDOMWindowList : public nsIDOMWindowCollection
 {
 public:
   nsDOMWindowList(nsIDocShell *aDocShell);
@@ -36,12 +36,12 @@ public:
     }
     return item.forget();
   }
 
 protected:
   // Note: this function may flush and cause mDocShellNode to become null.
   void EnsureFresh();
 
-  nsIDocShellTreeNode* mDocShellNode; //Weak Reference
+  nsIDocShell* mDocShellNode; //Weak Reference
 };
 
 #endif // nsDOMWindowList_h___
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -5463,23 +5463,23 @@ nsGlobalWindow::GetLength(uint32_t* aLen
 {
   *aLength = Length();
   return NS_OK;
 }
 
 already_AddRefed<nsIDOMWindow>
 nsGlobalWindow::GetChildWindow(const nsAString& aName)
 {
-  nsCOMPtr<nsIDocShellTreeNode> dsn(do_QueryInterface(GetDocShell()));
-  NS_ENSURE_TRUE(dsn, nullptr);
+  nsCOMPtr<nsIDocShell> docShell(GetDocShell());
+  NS_ENSURE_TRUE(docShell, nullptr);
 
   nsCOMPtr<nsIDocShellTreeItem> child;
-  dsn->FindChildWithName(PromiseFlatString(aName).get(),
-                         false, true, nullptr, nullptr,
-                         getter_AddRefs(child));
+  docShell->FindChildWithName(PromiseFlatString(aName).get(),
+                              false, true, nullptr, nullptr,
+                              getter_AddRefs(child));
 
   nsCOMPtr<nsIDOMWindow> child_win(do_GetInterface(child));
   return child_win.forget();
 }
 
 bool
 nsGlobalWindow::DispatchCustomEvent(const char *aEventName)
 {
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1921,17 +1921,20 @@ nsJSContext::GarbageCollectNow(JS::gcrea
     // We're in the middle of incremental GC. Do another slice.
     JS::PrepareForIncrementalGC(sRuntime);
     JS::IncrementalGC(sRuntime, aReason, aSliceMillis);
     return;
   }
 
   JS::PrepareForFullGC(sRuntime);
   if (aIncremental == IncrementalGC) {
+    MOZ_ASSERT(aShrinking == NonShrinkingGC);
     JS::IncrementalGC(sRuntime, aReason, aSliceMillis);
+  } else if (aShrinking == ShrinkingGC) {
+    JS::ShrinkingGC(sRuntime, aReason);
   } else {
     JS::GCForReason(sRuntime, aReason);
   }
 }
 
 //static
 void
 nsJSContext::ShrinkGCBuffersNow()
--- a/dom/bindings/ErrorResult.h
+++ b/dom/bindings/ErrorResult.h
@@ -34,17 +34,22 @@ bool
 ThrowErrorMessage(JSContext* aCx, const ErrNum aErrorNumber, ...);
 
 } // namespace dom
 
 class ErrorResult {
 public:
   ErrorResult() {
     mResult = NS_OK;
+
 #ifdef DEBUG
+    // ErrorResult is extremely performance-sensitive code, where literally
+    // every machine instruction matters. Initialize mMessage only to suppress
+    // a debug-only warning from gcc 4.6.
+    mMessage = nullptr;
     mMightHaveUnreportedJSException = false;
 #endif
   }
 
 #ifdef DEBUG
   ~ErrorResult() {
     MOZ_ASSERT_IF(IsTypeError(), !mMessage);
     MOZ_ASSERT(!mMightHaveUnreportedJSException);
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -41,28 +41,28 @@ LOCAL_INCLUDES += [
     '/content/base/src',
     '/content/canvas/src',
     '/content/events/src',
     '/content/html/content/src',
     '/content/html/document/src',
     '/content/media/webaudio',
     '/content/media/webspeech/recognition',
     '/content/svg/content/src',
-    '/content/xbl/src',
     '/content/xml/content/src',
     '/content/xul/content/src',
     '/content/xul/document/src',
     '/dom/base',
     '/dom/battery',
     '/dom/bluetooth',
     '/dom/camera',
     '/dom/file',
     '/dom/indexedDB',
     '/dom/src/geolocation',
     '/dom/workers',
+    '/dom/xbl',
     '/dom/xslt/base',
     '/dom/xslt/xpath',
     '/js/ipc',
     '/js/xpconnect/src',
     '/js/xpconnect/wrappers',
     '/layout/style',
     '/layout/xul/tree',
     '/media/mtransport',
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -203,16 +203,19 @@ IDBFactory::Create(JSContext* aCx,
   nsRefPtr<IDBFactory> factory = new IDBFactory();
   factory->mGroup = group;
   factory->mASCIIOrigin = origin;
   factory->mPrivilege = privilege;
   factory->mDefaultPersistenceType = defaultPersistenceType;
   factory->mOwningObject = aOwningObject;
   factory->mContentParent = aContentParent;
 
+  mozilla::HoldJSObjects(factory.get());
+  factory->mRootedOwningObject = true;
+
   if (!IndexedDatabaseManager::IsMainProcess()) {
     ContentChild* contentChild = ContentChild::GetSingleton();
     NS_ENSURE_TRUE(contentChild, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
     IndexedDBChild* actor = new IndexedDBChild(origin);
 
     contentChild->SendPIndexedDBConstructor(actor);
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -63,16 +63,17 @@
 #include "nsIAlertsService.h"
 #include "nsIAppsService.h"
 #include "nsIClipboard.h"
 #include "nsIDOMGeoGeolocation.h"
 #include "mozilla/dom/WakeLock.h"
 #include "nsIDOMWindow.h"
 #include "nsIExternalProtocolService.h"
 #include "nsIFilePicker.h"
+#include "nsIGfxInfo.h"
 #include "nsIIdleService.h"
 #include "nsIMemoryReporter.h"
 #include "nsIMozBrowserFrame.h"
 #include "nsIMutable.h"
 #include "nsIObserverService.h"
 #include "nsIPresShell.h"
 #include "nsIRemoteBlob.h"
 #include "nsIScriptError.h"
@@ -511,18 +512,16 @@ ContentParent::CreateBrowserOrApp(const 
                                   Element* aFrameElement)
 {
     if (!sCanLaunchSubprocesses) {
         return nullptr;
     }
 
     if (aContext.IsBrowserElement() || !aContext.HasOwnApp()) {
         if (nsRefPtr<ContentParent> cp = GetNewOrUsed(aContext.IsBrowserElement())) {
-            nsRefPtr<TabParent> tp(new TabParent(cp, aContext));
-            tp->SetOwnerElement(aFrameElement);
             uint32_t chromeFlags = 0;
 
             // Propagate the private-browsing status of the element's parent
             // docshell to the remote docshell, via the chrome flags.
             nsCOMPtr<Element> frameElement = do_QueryInterface(aFrameElement);
             MOZ_ASSERT(frameElement);
             nsIDocShell* docShell =
                 frameElement->OwnerDoc()->GetWindow()->GetDocShell();
@@ -532,16 +531,19 @@ ContentParent::CreateBrowserOrApp(const 
                 chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
             }
             bool affectLifetime;
             docShell->GetAffectPrivateSessionLifetime(&affectLifetime);
             if (affectLifetime) {
                 chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME;
             }
 
+            nsRefPtr<TabParent> tp(new TabParent(cp, aContext, chromeFlags));
+            tp->SetOwnerElement(aFrameElement);
+
             PBrowserParent* browser = cp->SendPBrowserConstructor(
                 tp.forget().get(), // DeallocPBrowserParent() releases this ref.
                 aContext.AsIPCTabContext(),
                 chromeFlags);
             return static_cast<TabParent*>(browser);
         }
         return nullptr;
     }
@@ -594,22 +596,24 @@ ContentParent::CreateBrowserOrApp(const 
                                   /* isForPreallocated = */ false,
                                   privs,
                                   initialPriority);
             p->Init();
         }
         sAppContentParents->Put(manifestURL, p);
     }
 
-    nsRefPtr<TabParent> tp = new TabParent(p, aContext);
+    uint32_t chromeFlags = 0;
+
+    nsRefPtr<TabParent> tp = new TabParent(p, aContext, chromeFlags);
     tp->SetOwnerElement(aFrameElement);
     PBrowserParent* browser = p->SendPBrowserConstructor(
         nsRefPtr<TabParent>(tp).forget().get(), // DeallocPBrowserParent() releases this ref.
         aContext.AsIPCTabContext(),
-        /* chromeFlags */ 0);
+        chromeFlags);
 
     p->MaybeTakeCPUWakeLock(aFrameElement);
 
     return static_cast<TabParent*>(browser);
 }
 
 void
 ContentParent::GetAll(nsTArray<ContentParent*>& aArray)
@@ -2031,17 +2035,17 @@ ContentParent::AllocPBrowserParent(const
     MaybeInvalidTabContext tc(aContext);
     if (!tc.IsValid()) {
         NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext.  (%s)  "
                                  "Aborting AllocPBrowserParent.",
                                  tc.GetInvalidReason()).get());
         return nullptr;
     }
 
-    TabParent* parent = new TabParent(this, tc.GetTabContext());
+    TabParent* parent = new TabParent(this, tc.GetTabContext(), aChromeFlags);
 
     // We release this ref in DeallocPBrowserParent()
     NS_ADDREF(parent);
     return parent;
 }
 
 bool
 ContentParent::DeallocPBrowserParent(PBrowserParent* frame)
@@ -3182,16 +3186,31 @@ ContentParent::RecvRecordingDeviceEvents
                              aRecordingStatus.get());
     } else {
         NS_WARNING("Could not get the Observer service for ContentParent::RecvRecordingDeviceEvents.");
     }
     return true;
 }
 
 bool
+ContentParent::RecvGetGraphicsFeatureStatus(const int32_t& aFeature,
+                                            int32_t* aStatus,
+                                            bool* aSuccess)
+{
+    nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
+    if (!gfxInfo) {
+        *aSuccess = false;
+        return true;
+    }
+
+    *aSuccess = NS_SUCCEEDED(gfxInfo->GetFeatureStatus(aFeature, aStatus));
+    return true;
+}
+
+bool
 ContentParent::RecvAddIdleObserver(const uint64_t& aObserver, const uint32_t& aIdleTimeInS)
 {
   nsresult rv;
   nsCOMPtr<nsIIdleService> idleService =
     do_GetService("@mozilla.org/widget/idleservice;1", &rv);
   NS_ENSURE_SUCCESS(rv, false);
 
   nsCOMPtr<ParentIdleListener> listener = new ParentIdleListener(this, aObserver);
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -510,16 +510,20 @@ private:
 
     virtual bool RecvSetFakeVolumeState(const nsString& fsName, const int32_t& fsState) MOZ_OVERRIDE;
 
     virtual bool RecvKeywordToURI(const nsCString& aKeyword, OptionalInputStreamParams* aPostData,
                                   OptionalURIParams* aURI);
 
     virtual void ProcessingError(Result what) MOZ_OVERRIDE;
 
+    virtual bool RecvGetGraphicsFeatureStatus(const int32_t& aFeature,
+                                              int32_t* aStatus,
+                                              bool* aSuccess);
+
     virtual bool RecvAddIdleObserver(const uint64_t& observerId, const uint32_t& aIdleTimeInS);
     virtual bool RecvRemoveIdleObserver(const uint64_t& observerId, const uint32_t& aIdleTimeInS);
 
     // If you add strong pointers to cycle collected objects here, be sure to
     // release these objects in ShutDownProcess.  See the comment there for more
     // details.
 
     GeckoChildProcessHost* mSubprocess;
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -502,16 +502,18 @@ parent:
      * @param isAudio recording start with microphone
      * @param isVideo recording start with camera
      */
     async RecordingDeviceEvents(nsString recordingStatus,
                                 nsString pageURL,
                                 bool isAudio,
                                 bool isVideo);
 
+    sync GetGraphicsFeatureStatus(int32_t aFeature) returns (int32_t aStatus, bool aSuccess);
+
     AddIdleObserver(uint64_t observerId, uint32_t idleTimeInS);
     RemoveIdleObserver(uint64_t observerId, uint32_t idleTimeInS);
 both:
      AsyncMessage(nsString aMessage, ClonedMessageData aData,
                   CpowEntry[] aCpows, Principal aPrincipal);
 };
 
 }
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -51,16 +51,17 @@
 #include "nsPrintfCString.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "private/pprio.h"
 #include "PermissionMessageUtils.h"
 #include "StructuredCloneUtils.h"
 #include "JavaScriptParent.h"
 #include "TabChild.h"
+#include "LoadContext.h"
 #include "nsNetCID.h"
 #include <algorithm>
 
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
 using namespace mozilla::layout;
 using namespace mozilla::services;
@@ -192,17 +193,17 @@ namespace mozilla {
 namespace dom {
 
 TabParent* sEventCapturer;
 
 TabParent *TabParent::mIMETabParent = nullptr;
 
 NS_IMPL_ISUPPORTS3(TabParent, nsITabParent, nsIAuthPromptProvider, nsISecureBrowserUI)
 
-TabParent::TabParent(ContentParent* aManager, const TabContext& aContext)
+TabParent::TabParent(ContentParent* aManager, const TabContext& aContext, uint32_t aChromeFlags)
   : TabContext(aContext)
   , mFrameElement(nullptr)
   , mIMESelectionAnchor(0)
   , mIMESelectionFocus(0)
   , mIMEComposing(false)
   , mIMECompositionEnding(false)
   , mIMECompositionStart(0)
   , mIMESeqno(0)
@@ -213,16 +214,17 @@ TabParent::TabParent(ContentParent* aMan
   , mDPI(0)
   , mDefaultScale(0)
   , mShown(false)
   , mUpdatedDimensions(false)
   , mManager(aManager)
   , mMarkedDestroying(false)
   , mIsDestroyed(false)
   , mAppPackageFileDescriptorSent(false)
+  , mChromeFlags(aChromeFlags)
 {
 }
 
 TabParent::~TabParent()
 {
 }
 
 void
@@ -1726,10 +1728,27 @@ TabParent::RecvContentReceivedTouch(cons
                                     const bool& aPreventDefault)
 {
   if (RenderFrameParent* rfp = GetRenderFrame()) {
     rfp->ContentReceivedTouch(aGuid, aPreventDefault);
   }
   return true;
 }
 
+already_AddRefed<nsILoadContext>
+TabParent::GetLoadContext()
+{
+  nsCOMPtr<nsILoadContext> loadContext;
+  if (mLoadContext) {
+    loadContext = mLoadContext;
+  } else {
+    loadContext = new LoadContext(GetOwnerElement(),
+                                  OwnOrContainingAppId(),
+                                  true /* aIsContent */,
+                                  mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW,
+                                  IsBrowserElement());
+    mLoadContext = loadContext;
+  }
+  return loadContext.forget();
+}
+
 } // namespace tabs
 } // namespace mozilla
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -21,16 +21,17 @@
 #include "js/TypeDecls.h"
 
 struct gfxMatrix;
 class nsFrameLoader;
 class nsIContent;
 class nsIPrincipal;
 class nsIURI;
 class nsIWidget;
+class nsILoadContext;
 class CpowHolder;
 
 namespace mozilla {
 
 namespace layers {
 struct FrameMetrics;
 struct TextureFactoryIdentifier;
 }
@@ -53,17 +54,17 @@ class TabParent : public PBrowserParent
                 , public nsIAuthPromptProvider
                 , public nsISecureBrowserUI
                 , public TabContext
 {
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
     typedef mozilla::layout::ScrollingBehavior ScrollingBehavior;
 
 public:
-    TabParent(ContentParent* aManager, const TabContext& aContext);
+    TabParent(ContentParent* aManager, const TabContext& aContext, uint32_t aChromeFlags);
     virtual ~TabParent();
     Element* GetOwnerElement() const { return mFrameElement; }
     void SetOwnerElement(Element* aElement);
 
     /**
      * Get the mozapptype attribute from this TabParent's owner DOM element.
      */
     void GetAppType(nsAString& aOut);
@@ -76,16 +77,18 @@ public:
      */
     bool IsVisible();
 
     nsIBrowserDOMWindow *GetBrowserDOMWindow() { return mBrowserDOMWindow; }
     void SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserDOMWindow) {
         mBrowserDOMWindow = aBrowserDOMWindow;
     }
 
+    already_AddRefed<nsILoadContext> GetLoadContext();
+
     /**
      * Return the TabParent that has decided it wants to capture an
      * event series for fast-path dispatch to its subprocess, if one
      * has.
      *
      * DOM event dispatch and widget are free to ignore capture
      * requests from TabParents; the end result wrt remote content is
      * (must be) always the same, albeit usually slower without
@@ -367,14 +370,18 @@ private:
     // When true, we've initiated normal shutdown and notified our
     // managing PContent.
     bool mMarkedDestroying;
     // When true, the TabParent is invalid and we should not send IPC messages
     // anymore.
     bool mIsDestroyed;
     // Whether we have already sent a FileDescriptor for the app package.
     bool mAppPackageFileDescriptorSent;
+
+    uint32_t mChromeFlags;
+
+    nsCOMPtr<nsILoadContext> mLoadContext;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -1843,24 +1843,23 @@ MediaManager::MediaCaptureWindowStateInt
           if (*aAudio && *aVideo) {
             return NS_OK; // no need to continue iterating
           }
         }
       }
     }
 
     // iterate any children of *this* window (iframes, etc)
-    nsCOMPtr<nsIDocShellTreeNode> node =
-      do_QueryInterface(piWin->GetDocShell());
-    if (node) {
+    nsCOMPtr<nsIDocShell> docShell = piWin->GetDocShell();
+    if (docShell) {
       int32_t i, count;
-      node->GetChildCount(&count);
+      docShell->GetChildCount(&count);
       for (i = 0; i < count; ++i) {
         nsCOMPtr<nsIDocShellTreeItem> item;
-        node->GetChildAt(i, getter_AddRefs(item));
+        docShell->GetChildAt(i, getter_AddRefs(item));
         nsCOMPtr<nsPIDOMWindow> win = do_GetInterface(item);
 
         MediaCaptureWindowStateInternal(win, aVideo, aAudio);
         if (*aAudio && *aVideo) {
           return NS_OK; // no need to continue iterating
         }
       }
     }
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -72,16 +72,17 @@ PARALLEL_DIRS += [
     'workers',
     'camera',
     'audiochannel',
     'promise',
     'smil',
     'telephony',
     'inputmethod',
     'webidl',
+    'xbl',
     'xslt',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     PARALLEL_DIRS += ['plugins/ipc/hangui']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     PARALLEL_DIRS += [
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -135,19 +135,19 @@ public:
     if (!EnsureGLContext())
       return 0;
 
     if (mTextureInfo.mWidth == 0 || mTextureInfo.mHeight == 0)
       return 0;
 
     SharedTextureHandle handle =
       gl::CreateSharedHandle(sPluginContext,
-                             gl::SameProcess,
+                             gl::SharedTextureShareType::SameProcess,
                              (void*)mTextureInfo.mTexture,
-                             gl::TextureID);
+                             gl::SharedTextureBufferType::TextureID);
 
     // We want forget about this now, so delete the texture. Assigning it to zero
     // ensures that we create a new one in Lock()
     sPluginContext->fDeleteTextures(1, &mTextureInfo.mTexture);
     mTextureInfo.mTexture = 0;
     
     return handle;
   }
@@ -1016,19 +1016,19 @@ void* nsNPAPIPluginInstance::AcquireCont
 
 SharedTextureHandle nsNPAPIPluginInstance::CreateSharedHandle()
 {
   if (mContentTexture) {
     return mContentTexture->CreateSharedHandle();
   } else if (mContentSurface) {
     EnsureGLContext();
     return gl::CreateSharedHandle(sPluginContext,
-                                  gl::SameProcess,
+                                  gl::SharedTextureShareType::SameProcess,
                                   mContentSurface,
-                                  gl::SurfaceTexture);
+                                  gl::SharedTextureBufferType::SurfaceTexture);
   } else return 0;
 }
 
 void* nsNPAPIPluginInstance::AcquireVideoWindow()
 {
   nsSurfaceTexture* surface = CreateSurfaceTexture();
   if (!surface)
     return nullptr;
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -171,17 +171,17 @@ nsPluginInstanceOwner::GetImageContainer
   
   container = LayerManager::CreateImageContainer();
 
   ImageFormat format = ImageFormat::SHARED_TEXTURE;
   nsRefPtr<Image> img = container->CreateImage(&format, 1);
 
   SharedTextureImage::Data data;
   data.mHandle = mInstance->CreateSharedHandle();
-  data.mShareType = mozilla::gl::SameProcess;
+  data.mShareType = mozilla::gl::SharedTextureShareType::SameProcess;
   data.mInverted = mInstance->Inverted();
 
   LayoutDeviceRect r = GetPluginRect();
   data.mSize = gfx::IntSize(r.width, r.height);
 
   SharedTextureImage* pluginImage = static_cast<SharedTextureImage*>(img.get());
   pluginImage->SetData(data);
 
@@ -1498,21 +1498,21 @@ already_AddRefed<ImageContainer> nsPlugi
 {
   nsRefPtr<ImageContainer> container = LayerManager::CreateImageContainer();
 
   ImageFormat format = ImageFormat::SHARED_TEXTURE;
   nsRefPtr<Image> img = container->CreateImage(&format, 1);
 
   SharedTextureImage::Data data;
 
-  data.mShareType = gl::SameProcess;
+  data.mShareType = gl::SharedTextureShareType::SameProcess;
   data.mHandle = gl::CreateSharedHandle(mInstance->GLContext(),
                                         data.mShareType,
                                         aVideoInfo->mSurfaceTexture,
-                                        gl::SurfaceTexture);
+                                        gl::SharedTextureBufferType::SurfaceTexture);
 
   // The logic below for Honeycomb is just a guess, but seems to work. We don't have a separate
   // inverted flag for video.
   data.mInverted = AndroidBridge::Bridge()->IsHoneycomb() ? true : mInstance->Inverted();
   data.mSize = gfx::IntSize(aVideoInfo->mDimensions.width, aVideoInfo->mDimensions.height);
 
   SharedTextureImage* pluginImage = static_cast<SharedTextureImage*>(img.get());
   pluginImage->SetData(data);
--- a/dom/plugins/ipc/PluginProcessChild.cpp
+++ b/dom/plugins/ipc/PluginProcessChild.cpp
@@ -114,21 +114,19 @@ PluginProcessChild::Init()
 #  error Sorry
 #endif
 
     if (NS_FAILED(nsRegion::InitStatic())) {
       NS_ERROR("Could not initialize nsRegion");
       return false;
     }
 
-    mPlugin.Init(pluginFilename, ParentHandle(),
-                 IOThreadChild::message_loop(),
-                 IOThreadChild::channel());
-
-    return true;
+    return mPlugin.Init(pluginFilename, ParentHandle(),
+                        IOThreadChild::message_loop(),
+                        IOThreadChild::channel());
 }
 
 void
 PluginProcessChild::CleanUp()
 {
 #ifdef XP_WIN
     ::OleUninitialize();
 #endif
--- a/dom/plugins/ipc/PluginProcessParent.h
+++ b/dom/plugins/ipc/PluginProcessParent.h
@@ -40,17 +40,16 @@ public:
     {
         return true;
     }
 
     const std::string& GetPluginFilePath() { return mPluginFilePath; }
 
     using mozilla::ipc::GeckoChildProcessHost::GetShutDownEvent;
     using mozilla::ipc::GeckoChildProcessHost::GetChannel;
-    using mozilla::ipc::GeckoChildProcessHost::GetChildProcessHandle;
 
 private:
     std::string mPluginFilePath;
 
     DISALLOW_EVIL_CONSTRUCTORS(PluginProcessParent);
 };
 
 
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -556,22 +556,26 @@ Promise::MaybeReportRejected()
     isChromeError = nsContentUtils::IsSystemPrincipal(principal);
   } else {
     WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
     MOZ_ASSERT(worker);
     isChromeError = worker->IsChromeWorker();
   }
 
   // Now post an event to do the real reporting async
-  NS_DispatchToMainThread(
+  // Since Promises preserve their wrapper, it is essential to nsRefPtr<> the
+  // AsyncErrorReporter, otherwise if the call to DispatchToMainThread fails, it
+  // will leak. See Bug 958684.
+  nsRefPtr<AsyncErrorReporter> r =
     new AsyncErrorReporter(JS_GetObjectRuntime(&mResult.toObject()),
                            report,
                            nullptr,
                            isChromeError,
-                           win));
+                           win);
+  NS_DispatchToMainThread(r);
 }
 
 void
 Promise::MaybeResolveInternal(JSContext* aCx,
                               JS::Handle<JS::Value> aValue,
                               PromiseTaskSync aAsynchronous)
 {
   if (mResolvePending) {
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -172,16 +172,23 @@ private:
   { }
 
   virtual bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) MOZ_OVERRIDE;
 
   virtual void
   PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, bool aRunResult)
           MOZ_OVERRIDE;
+
+  NS_DECL_NSICANCELABLERUNNABLE
+
+  void
+  ShutdownScriptLoader(JSContext* aCx,
+                       WorkerPrivate* aWorkerPrivate,
+                       bool aResult);
 };
 
 class ScriptLoaderRunnable MOZ_FINAL : public WorkerFeature,
                                        public nsIRunnable,
                                        public nsIStreamLoaderObserver
 {
   friend class ScriptExecutorRunnable;
 
@@ -735,21 +742,36 @@ ScriptExecutorRunnable::PostRun(JSContex
     bool result = true;
     for (uint32_t index = 0; index < loadInfos.Length(); index++) {
       if (!loadInfos[index].mExecutionResult) {
         result = false;
         break;
       }
     }
 
-    aWorkerPrivate->RemoveFeature(aCx, &mScriptLoader);
-    aWorkerPrivate->StopSyncLoop(mSyncLoopTarget, result);
+    ShutdownScriptLoader(aCx, aWorkerPrivate, result);
   }
 }
 
+NS_IMETHODIMP
+ScriptExecutorRunnable::Cancel()
+{
+  ShutdownScriptLoader(mWorkerPrivate->GetJSContext(), mWorkerPrivate, false);
+  return NS_OK;
+}
+
+void
+ScriptExecutorRunnable::ShutdownScriptLoader(JSContext* aCx,
+                                             WorkerPrivate* aWorkerPrivate,
+                                             bool aResult)
+{
+  aWorkerPrivate->RemoveFeature(aCx, &mScriptLoader);
+  aWorkerPrivate->StopSyncLoop(mSyncLoopTarget, aResult);
+}
+
 bool
 LoadAllScripts(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
                nsTArray<ScriptLoadInfo>& aLoadInfos, bool aIsWorkerScript)
 {
   aWorkerPrivate->AssertIsOnWorkerThread();
   NS_ASSERTION(!aLoadInfos.IsEmpty(), "Bad arguments!");
 
   AutoSyncLoopHolder syncLoop(aWorkerPrivate);
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1062,18 +1062,18 @@ class NotifyRunnable MOZ_FINAL : public 
 {
   Status mStatus;
 
 public:
   NotifyRunnable(WorkerPrivate* aWorkerPrivate, Status aStatus)
   : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
     mStatus(aStatus)
   {
-    MOZ_ASSERT(aStatus == Terminating || aStatus == Canceling ||
-               aStatus == Killing);
+    MOZ_ASSERT(aStatus == Closing || aStatus == Terminating ||
+               aStatus == Canceling || aStatus == Killing);
   }
 
 private:
   virtual bool
   PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate) MOZ_OVERRIDE
   {
     // Modify here, but not in PostRun! This busy count addition will be matched
     // by the CloseEventRunnable.
@@ -4868,39 +4868,54 @@ WorkerPrivate::RunCurrentSyncLoop()
 
     MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(thread, false));
 
     // Now *might* be a good time to GC. Let the JS engine make the decision.
     JS_MaybeGC(cx);
   }
 
   // Make sure that the stack didn't change underneath us.
+  MOZ_ASSERT(mSyncLoopStack[currentLoopIndex] == loopInfo);
+
+  return DestroySyncLoop(currentLoopIndex);
+}
+
+bool
+WorkerPrivate::DestroySyncLoop(uint32_t aLoopIndex, nsIThreadInternal* aThread)
+{
   MOZ_ASSERT(!mSyncLoopStack.IsEmpty());
-  MOZ_ASSERT(mSyncLoopStack.Length() - 1 == currentLoopIndex);
-  MOZ_ASSERT(mSyncLoopStack[currentLoopIndex] == loopInfo);
-
-  // We're about to delete |loop|, stash its event target and result.
+  MOZ_ASSERT(mSyncLoopStack.Length() - 1 == aLoopIndex);
+
+  if (!aThread) {
+    nsCOMPtr<nsIThreadInternal> thread = do_QueryInterface(mThread);
+    MOZ_ASSERT(thread);
+
+    aThread = thread.get();
+  }
+
+  // We're about to delete the loop, stash its event target and result.
+  SyncLoopInfo* loopInfo = mSyncLoopStack[aLoopIndex];
   nsIEventTarget* nestedEventTarget =
     loopInfo->mEventTarget->GetWeakNestedEventTarget();
   MOZ_ASSERT(nestedEventTarget);
 
   bool result = loopInfo->mResult;
 
   {
     // Modifications must be protected by mMutex in DEBUG builds, see comment
     // about mSyncLoopStack in WorkerPrivate.h.
 #ifdef DEBUG
     MutexAutoLock lock(mMutex);
 #endif
 
-    // This will delete |loop|!
-    mSyncLoopStack.RemoveElementAt(currentLoopIndex);
-  }
-
-  MOZ_ALWAYS_TRUE(NS_SUCCEEDED(thread->PopEventQueue(nestedEventTarget)));
+    // This will delete |loopInfo|!
+    mSyncLoopStack.RemoveElementAt(aLoopIndex);
+  }
+
+  MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aThread->PopEventQueue(nestedEventTarget)));
 
   return result;
 }
 
 void
 WorkerPrivate::StopSyncLoop(nsIEventTarget* aSyncLoopTarget, bool aResult)
 {
   AssertIsOnWorkerThread();
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -29,16 +29,17 @@
 
 class JSAutoStructuredCloneBuffer;
 class nsIChannel;
 class nsIDocument;
 class nsIEventTarget;
 class nsIPrincipal;
 class nsIScriptContext;
 class nsIThread;
+class nsIThreadInternal;
 class nsITimer;
 class nsIURI;
 
 namespace JS {
 class RuntimeStats;
 }
 
 namespace mozilla {
@@ -1093,16 +1094,19 @@ private:
   }
 
   already_AddRefed<nsIEventTarget>
   CreateNewSyncLoop();
 
   bool
   RunCurrentSyncLoop();
 
+  bool
+  DestroySyncLoop(uint32_t aLoopIndex, nsIThreadInternal* aThread = nullptr);
+
   void
   InitializeGCTimers();
 
   void
   SetGCTimerMode(GCTimerMode aMode);
 
   void
   ShutdownGCTimers();
@@ -1152,29 +1156,33 @@ WorkerStructuredCloneCallbacks(bool aMai
 
 JSStructuredCloneCallbacks*
 ChromeWorkerStructuredCloneCallbacks(bool aMainRuntime);
 
 class AutoSyncLoopHolder
 {
   WorkerPrivate* mWorkerPrivate;
   nsCOMPtr<nsIEventTarget> mTarget;
+  uint32_t mIndex;
 
 public:
   AutoSyncLoopHolder(WorkerPrivate* aWorkerPrivate)
-  : mWorkerPrivate(aWorkerPrivate), mTarget(aWorkerPrivate->CreateNewSyncLoop())
+  : mWorkerPrivate(aWorkerPrivate)
+  , mTarget(aWorkerPrivate->CreateNewSyncLoop())
+  , mIndex(aWorkerPrivate->mSyncLoopStack.Length() - 1)
   {
     aWorkerPrivate->AssertIsOnWorkerThread();
   }
 
   ~AutoSyncLoopHolder()
   {
     if (mWorkerPrivate) {
       mWorkerPrivate->AssertIsOnWorkerThread();
       mWorkerPrivate->StopSyncLoop(mTarget, false);
+      mWorkerPrivate->DestroySyncLoop(mIndex);
     }
   }
 
   bool
   Run()
   {
     WorkerPrivate* workerPrivate = mWorkerPrivate;
     mWorkerPrivate = nullptr;
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -503,18 +503,18 @@ private:
     ~ResponseRunnable()
     { }
 
     virtual void
     MaybeSetException(JSContext* aCx) MOZ_OVERRIDE
     {
       MOZ_ASSERT(NS_FAILED(mErrorCode));
 
-        Throw(aCx, mErrorCode);
-      }
+      Throw(aCx, mErrorCode);
+    }
   };
 
 public:
   WorkerThreadProxySyncRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy)
   : mWorkerPrivate(aWorkerPrivate), mProxy(aProxy)
   {
     MOZ_ASSERT(aWorkerPrivate);
     MOZ_ASSERT(aProxy);
@@ -1802,24 +1802,16 @@ XMLHttpRequest::SendInternal(const nsASt
   }
 
   if (!isSyncXHR)  {
     autoUnpin.Clear();
     MOZ_ASSERT(autoSyncLoop.empty());
     return;
   }
 
-  // If our sync XHR was canceled during the send call the worker is going
-  // away.  We have no idea how far through the send call we got.  There may
-  // be a ProxyCompleteRunnable in the sync loop, but rather than run the loop
-  // to get it we just let our RAII helpers clean up.
-  if (mCanceled) {
-    return;
-  }
-
   autoUnpin.Clear();
 
   if (!autoSyncLoop.ref().Run()) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 }
 
 bool
rename from content/xbl/src/XBLChildrenElement.cpp
rename to dom/xbl/XBLChildrenElement.cpp
rename from content/xbl/src/XBLChildrenElement.h
rename to dom/xbl/XBLChildrenElement.h
rename from content/xbl/builtin/android/jar.mn
rename to dom/xbl/builtin/android/jar.mn
rename from content/xbl/builtin/android/moz.build
rename to dom/xbl/builtin/android/moz.build
rename from content/xbl/builtin/android/platformHTMLBindings.xml
rename to dom/xbl/builtin/android/platformHTMLBindings.xml
rename from content/xbl/builtin/browser-base.inc
rename to dom/xbl/builtin/browser-base.inc
rename from content/xbl/builtin/editor-base.inc
rename to dom/xbl/builtin/editor-base.inc
rename from content/xbl/builtin/emacs/jar.mn
rename to dom/xbl/builtin/emacs/jar.mn
rename from content/xbl/builtin/emacs/moz.build
rename to dom/xbl/builtin/emacs/moz.build
rename from content/xbl/builtin/emacs/platformHTMLBindings.xml
rename to dom/xbl/builtin/emacs/platformHTMLBindings.xml
rename from content/xbl/builtin/input-fields-base.inc
rename to dom/xbl/builtin/input-fields-base.inc
rename from content/xbl/builtin/mac/jar.mn
rename to dom/xbl/builtin/mac/jar.mn
rename from content/xbl/builtin/mac/moz.build
rename to dom/xbl/builtin/mac/moz.build
rename from content/xbl/builtin/mac/platformHTMLBindings.xml
rename to dom/xbl/builtin/mac/platformHTMLBindings.xml
rename from content/xbl/builtin/moz.build
rename to dom/xbl/builtin/moz.build
rename from content/xbl/builtin/textareas-base.inc
rename to dom/xbl/builtin/textareas-base.inc
rename from content/xbl/builtin/unix/jar.mn
rename to dom/xbl/builtin/unix/jar.mn
rename from content/xbl/builtin/unix/moz.build
rename to dom/xbl/builtin/unix/moz.build
rename from content/xbl/builtin/unix/platformHTMLBindings.xml
rename to dom/xbl/builtin/unix/platformHTMLBindings.xml
rename from content/xbl/builtin/win/jar.mn
rename to dom/xbl/builtin/win/jar.mn
rename from content/xbl/builtin/win/moz.build
rename to dom/xbl/builtin/win/moz.build
rename from content/xbl/builtin/win/platformHTMLBindings.xml
rename to dom/xbl/builtin/win/platformHTMLBindings.xml
rename from content/xbl/crashtests/205735-1.xhtml
rename to dom/xbl/crashtests/205735-1.xhtml
rename from content/xbl/crashtests/223799-1.xul
rename to dom/xbl/crashtests/223799-1.xul
rename from content/xbl/crashtests/226744-1.xhtml
rename to dom/xbl/crashtests/226744-1.xhtml
rename from content/xbl/crashtests/232095-1.xul
rename to dom/xbl/crashtests/232095-1.xul
rename from content/xbl/crashtests/277523-1.xhtml
rename to dom/xbl/crashtests/277523-1.xhtml
rename from content/xbl/crashtests/277950-1.xhtml
rename to dom/xbl/crashtests/277950-1.xhtml
rename from content/xbl/crashtests/336744-1-inner.html
rename to dom/xbl/crashtests/336744-1-inner.html
rename from content/xbl/crashtests/336744-1.html
rename to dom/xbl/crashtests/336744-1.html
rename from content/xbl/crashtests/336960-1-inner.xhtml
rename to dom/xbl/crashtests/336960-1-inner.xhtml
rename from content/xbl/crashtests/336960-1.html
rename to dom/xbl/crashtests/336960-1.html
rename from content/xbl/crashtests/342954-1.xhtml
rename to dom/xbl/crashtests/342954-1.xhtml
rename from content/xbl/crashtests/342954-2-xbl.xml
rename to dom/xbl/crashtests/342954-2-xbl.xml
rename from content/xbl/crashtests/342954-2.xhtml
rename to dom/xbl/crashtests/342954-2.xhtml
rename from content/xbl/crashtests/368276-1.xhtml
rename to dom/xbl/crashtests/368276-1.xhtml
rename from content/xbl/crashtests/368641-1.xhtml
rename to dom/xbl/crashtests/368641-1.xhtml
rename from content/xbl/crashtests/378521-1.xhtml
rename to dom/xbl/crashtests/378521-1.xhtml
rename from content/xbl/crashtests/382376-1.xhtml
rename to dom/xbl/crashtests/382376-1.xhtml
rename from content/xbl/crashtests/382376-2.xhtml
rename to dom/xbl/crashtests/382376-2.xhtml
rename from content/xbl/crashtests/397596-1.xhtml
rename to dom/xbl/crashtests/397596-1.xhtml
rename from content/xbl/crashtests/404125-1.xhtml
rename to dom/xbl/crashtests/404125-1.xhtml
rename from content/xbl/crashtests/406900-1.xul
rename to dom/xbl/crashtests/406900-1.xul
rename from content/xbl/crashtests/406904-1.xhtml
rename to dom/xbl/crashtests/406904-1.xhtml
rename from content/xbl/crashtests/406904-2.xhtml
rename to dom/xbl/crashtests/406904-2.xhtml
rename from content/xbl/crashtests/415192-1.xul
rename to dom/xbl/crashtests/415192-1.xul
rename from content/xbl/crashtests/415301-1.xul
rename to dom/xbl/crashtests/415301-1.xul
rename from content/xbl/crashtests/418133-1.xhtml
rename to dom/xbl/crashtests/418133-1.xhtml
rename from content/xbl/crashtests/420233-1.xhtml
rename to dom/xbl/crashtests/420233-1.xhtml
rename from content/xbl/crashtests/421997-1.xhtml
rename to dom/xbl/crashtests/421997-1.xhtml
rename from content/xbl/crashtests/432813-1-xbl.xml
rename to dom/xbl/crashtests/432813-1-xbl.xml
rename from content/xbl/crashtests/432813-1.xhtml
rename to dom/xbl/crashtests/432813-1.xhtml
rename from content/xbl/crashtests/454820-1.html
rename to dom/xbl/crashtests/454820-1.html
rename from content/xbl/crashtests/460665-1.xhtml
rename to dom/xbl/crashtests/460665-1.xhtml
rename from content/xbl/crashtests/463511-1.xhtml
rename to dom/xbl/crashtests/463511-1.xhtml
rename from content/xbl/crashtests/464863-1.xhtml
rename to dom/xbl/crashtests/464863-1.xhtml
rename from content/xbl/crashtests/472260-1.xhtml
rename to dom/xbl/crashtests/472260-1.xhtml
rename from content/xbl/crashtests/477878-1.html
rename to dom/xbl/crashtests/477878-1.html
rename from content/xbl/crashtests/492978-1.xul
rename to dom/xbl/crashtests/492978-1.xul
rename from content/xbl/crashtests/493123-1.xhtml
rename to dom/xbl/crashtests/493123-1.xhtml
rename from content/xbl/crashtests/495354-1.xhtml
rename to dom/xbl/crashtests/495354-1.xhtml
rename from content/xbl/crashtests/507628-1.xhtml
rename to dom/xbl/crashtests/507628-1.xhtml
rename from content/xbl/crashtests/507991-1.xhtml
rename to dom/xbl/crashtests/507991-1.xhtml
rename from content/xbl/crashtests/830614-1.xul
rename to dom/xbl/crashtests/830614-1.xul
rename from content/xbl/crashtests/895805-1.xhtml
rename to dom/xbl/crashtests/895805-1.xhtml
rename from content/xbl/crashtests/crashtests.list
rename to dom/xbl/crashtests/crashtests.list
rename from content/xbl/crashtests/set-field-bad-this.xhtml
rename to dom/xbl/crashtests/set-field-bad-this.xhtml
rename from content/xbl/src/moz.build
rename to dom/xbl/moz.build
--- a/content/xbl/src/moz.build
+++ b/dom/xbl/moz.build
@@ -1,14 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+PARALLEL_DIRS += ['builtin']
+TEST_DIRS += ['test']
+
 EXPORTS += [
     'nsBindingManager.h',
     'nsXBLBinding.h',
     'nsXBLService.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'XBLChildrenElement.h',
rename from content/xbl/src/nsBindingManager.cpp
rename to dom/xbl/nsBindingManager.cpp
rename from content/xbl/src/nsBindingManager.h
rename to dom/xbl/nsBindingManager.h
rename from content/xbl/src/nsXBLBinding.cpp
rename to dom/xbl/nsXBLBinding.cpp
rename from content/xbl/src/nsXBLBinding.h
rename to dom/xbl/nsXBLBinding.h
rename from content/xbl/src/nsXBLContentSink.cpp
rename to dom/xbl/nsXBLContentSink.cpp
rename from content/xbl/src/nsXBLContentSink.h
rename to dom/xbl/nsXBLContentSink.h
rename from content/xbl/src/nsXBLDocumentInfo.cpp
rename to dom/xbl/nsXBLDocumentInfo.cpp
rename from content/xbl/src/nsXBLDocumentInfo.h
rename to dom/xbl/nsXBLDocumentInfo.h
rename from content/xbl/src/nsXBLEventHandler.cpp
rename to dom/xbl/nsXBLEventHandler.cpp
rename from content/xbl/src/nsXBLEventHandler.h
rename to dom/xbl/nsXBLEventHandler.h
rename from content/xbl/src/nsXBLMaybeCompiled.h
rename to dom/xbl/nsXBLMaybeCompiled.h
rename from content/xbl/src/nsXBLProtoImpl.cpp
rename to dom/xbl/nsXBLProtoImpl.cpp
rename from content/xbl/src/nsXBLProtoImpl.h
rename to dom/xbl/nsXBLProtoImpl.h
rename from content/xbl/src/nsXBLProtoImplField.cpp
rename to dom/xbl/nsXBLProtoImplField.cpp
rename from content/xbl/src/nsXBLProtoImplField.h
rename to dom/xbl/nsXBLProtoImplField.h
rename from content/xbl/src/nsXBLProtoImplMember.h
rename to dom/xbl/nsXBLProtoImplMember.h
rename from content/xbl/src/nsXBLProtoImplMethod.cpp
rename to dom/xbl/nsXBLProtoImplMethod.cpp
rename from content/xbl/src/nsXBLProtoImplMethod.h
rename to dom/xbl/nsXBLProtoImplMethod.h
rename from content/xbl/src/nsXBLProtoImplProperty.cpp
rename to dom/xbl/nsXBLProtoImplProperty.cpp
rename from content/xbl/src/nsXBLProtoImplProperty.h
rename to dom/xbl/nsXBLProtoImplProperty.h
rename from content/xbl/src/nsXBLPrototypeBinding.cpp
rename to dom/xbl/nsXBLPrototypeBinding.cpp
rename from content/xbl/src/nsXBLPrototypeBinding.h
rename to dom/xbl/nsXBLPrototypeBinding.h
rename from content/xbl/src/nsXBLPrototypeHandler.cpp
rename to dom/xbl/nsXBLPrototypeHandler.cpp
rename from content/xbl/src/nsXBLPrototypeHandler.h
rename to dom/xbl/nsXBLPrototypeHandler.h
rename from content/xbl/src/nsXBLPrototypeResources.cpp
rename to dom/xbl/nsXBLPrototypeResources.cpp
rename from content/xbl/src/nsXBLPrototypeResources.h
rename to dom/xbl/nsXBLPrototypeResources.h
rename from content/xbl/src/nsXBLResourceLoader.cpp
rename to dom/xbl/nsXBLResourceLoader.cpp
rename from content/xbl/src/nsXBLResourceLoader.h
rename to dom/xbl/nsXBLResourceLoader.h
rename from content/xbl/src/nsXBLSerialize.cpp
rename to dom/xbl/nsXBLSerialize.cpp
rename from content/xbl/src/nsXBLSerialize.h
rename to dom/xbl/nsXBLSerialize.h
rename from content/xbl/src/nsXBLService.cpp
rename to dom/xbl/nsXBLService.cpp
rename from content/xbl/src/nsXBLService.h
rename to dom/xbl/nsXBLService.h
rename from content/xbl/src/nsXBLWindowKeyHandler.cpp
rename to dom/xbl/nsXBLWindowKeyHandler.cpp
rename from content/xbl/src/nsXBLWindowKeyHandler.h
rename to dom/xbl/nsXBLWindowKeyHandler.h
rename from content/xbl/test/bug310107-resource.xhtml
rename to dom/xbl/test/bug310107-resource.xhtml
rename from content/xbl/test/chrome.ini
rename to dom/xbl/test/chrome.ini
rename from content/xbl/test/file_bug372769.xhtml
rename to dom/xbl/test/file_bug372769.xhtml
rename from content/xbl/test/file_bug379959_cross.html
rename to dom/xbl/test/file_bug379959_cross.html
--- a/content/xbl/test/file_bug379959_cross.html
+++ b/dom/xbl/test/file_bug379959_cross.html
@@ -3,17 +3,17 @@
 <head>
 <style>
 #div1 {
   color: green;
   -moz-binding: url(file_bug379959_xbl.xml#xbltest);
 }
 #div2 {
   color: green;
-  -moz-binding: url(http://example.com/tests/content/xbl/test/file_bug379959_xbl.xml#xbltest);
+  -moz-binding: url(http://example.com/tests/dom/xbl/test/file_bug379959_xbl.xml#xbltest);
 }
 </style>
 <body>
 <div id="div1"></div>
 <div id="div2"></div>
 <script>
 onload = function() {
   nodes = SpecialPowers.wrap(document).getAnonymousNodes(document.getElementById('div1'));
rename from content/xbl/test/file_bug379959_data.html
rename to dom/xbl/test/file_bug379959_data.html
rename from content/xbl/test/file_bug379959_xbl.xml
rename to dom/xbl/test/file_bug379959_xbl.xml
rename from content/xbl/test/file_bug397934.xhtml
rename to dom/xbl/test/file_bug397934.xhtml
rename from content/xbl/test/file_bug481558.xbl
rename to dom/xbl/test/file_bug481558.xbl
rename from content/xbl/test/file_bug481558css.sjs
rename to dom/xbl/test/file_bug481558css.sjs
--- a/content/xbl/test/file_bug481558css.sjs
+++ b/dom/xbl/test/file_bug481558css.sjs
@@ -4,14 +4,14 @@ function handleRequest(request, response
   request.queryString.split('&').forEach(function (val) {
     [name, value] = val.split('=');
     query[name] = unescape(value);
   });
 
   response.setHeader("Content-Type", "text/css", false);
   css = "#" + query.id + " { -moz-binding: url(\"";
   if (query.server) {
-    css += "http://" + query.server + "/tests/content/xbl/test/";
+    css += "http://" + query.server + "/tests/dom/xbl/test/";
   }
   css += "file_bug481558.xbl#test\"); }";
 
   response.write(css);
 }
rename from content/xbl/test/file_bug591198_inner.html
rename to dom/xbl/test/file_bug591198_inner.html
rename from content/xbl/test/file_bug591198_xbl.xml
rename to dom/xbl/test/file_bug591198_xbl.xml
rename from content/xbl/test/file_bug821850.xhtml
rename to dom/xbl/test/file_bug821850.xhtml
rename from content/xbl/test/file_bug844783.xhtml
rename to dom/xbl/test/file_bug844783.xhtml
rename from content/xbl/test/file_bug944407.html
rename to dom/xbl/test/file_bug944407.html
--- a/content/xbl/test/file_bug944407.html
+++ b/dom/xbl/test/file_bug944407.html
@@ -1,8 +1,8 @@
 <!DOCTYPE html>
 <html>
 <body>
 <div id="deny" style="-moz-binding: url(file_bug944407.xml#testAllowScript)"></div>
-<div id="allow" style="-moz-binding: url(chrome://mochitests/content/chrome/content/xbl/test/file_bug944407.xml#testAllowScript)"</div>
+<div id="allow" style="-moz-binding: url(chrome://mochitests/content/chrome/dom/xbl/test/file_bug944407.xml#testAllowScript)"</div>
 <script>/* Flush layout with a script tab - see bug 944407 comment 37. */</script>
 </body>
 </html>
rename from content/xbl/test/file_bug944407.xml
rename to dom/xbl/test/file_bug944407.xml
rename from content/xbl/test/file_bug950909.html
rename to dom/xbl/test/file_bug950909.html
--- a/content/xbl/test/file_bug950909.html
+++ b/dom/xbl/test/file_bug950909.html
@@ -1,8 +1,8 @@
 <!DOCTYPE html>
 <html>
 <head>
 </head>
 <body>
-<div style="-moz-binding: url(chrome://mochitests/content/chrome/content/xbl/test/file_bug950909.xml#testBinding"></div>
+<div style="-moz-binding: url(chrome://mochitests/content/chrome/dom/xbl/test/file_bug950909.xml#testBinding"></div>
 </body>
 </html>
rename from content/xbl/test/file_bug950909.xml
rename to dom/xbl/test/file_bug950909.xml
rename from content/xbl/test/mochitest.ini
rename to dom/xbl/test/mochitest.ini
rename from content/xbl/test/moz.build
rename to dom/xbl/test/moz.build
rename from content/xbl/test/test_bug310107.html
rename to dom/xbl/test/test_bug310107.html
rename from content/xbl/test/test_bug366770.html
rename to dom/xbl/test/test_bug366770.html
rename from content/xbl/test/test_bug371724.xhtml
rename to dom/xbl/test/test_bug371724.xhtml
rename from content/xbl/test/test_bug372769.html
rename to dom/xbl/test/test_bug372769.html
rename from content/xbl/test/test_bug378518.xul
rename to dom/xbl/test/test_bug378518.xul
rename from content/xbl/test/test_bug378866.xhtml
rename to dom/xbl/test/test_bug378866.xhtml
rename from content/xbl/test/test_bug379959.html
rename to dom/xbl/test/test_bug379959.html
rename from content/xbl/test/test_bug389322.xhtml
rename to dom/xbl/test/test_bug389322.xhtml
rename from content/xbl/test/test_bug397934.html
rename to dom/xbl/test/test_bug397934.html
rename from content/xbl/test/test_bug398135.xul
rename to dom/xbl/test/test_bug398135.xul
rename from content/xbl/test/test_bug398492.xul
rename to dom/xbl/test/test_bug398492.xul
rename from content/xbl/test/test_bug400705.xhtml
rename to dom/xbl/test/test_bug400705.xhtml
rename from content/xbl/test/test_bug401907.xhtml
rename to dom/xbl/test/test_bug401907.xhtml
rename from content/xbl/test/test_bug403162.xhtml
rename to dom/xbl/test/test_bug403162.xhtml
rename from content/xbl/test/test_bug468210.xhtml
rename to dom/xbl/test/test_bug468210.xhtml
rename from content/xbl/test/test_bug481558.html
rename to dom/xbl/test/test_bug481558.html
--- a/content/xbl/test/test_bug481558.html
+++ b/dom/xbl/test/test_bug481558.html
@@ -6,18 +6,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <head>
   <title>Test for Bug 481558</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
   <link rel="stylesheet" type="text/css"
         href="file_bug481558css.sjs?id=id1">
   <link rel="stylesheet" type="text/css"
         href="file_bug481558css.sjs?id=id2&server=example.com">
-  <link rel="stylesheet" type="text/css" href="http://example.com/tests/content/xbl/test/file_bug481558css.sjs?id=id3">
-  <link rel="stylesheet" type="text/css" href="http://example.com/tests/content/xbl/test/file_bug481558css.sjs?id=id4&server=localhost:8888">
+  <link rel="stylesheet" type="text/css" href="http://example.com/tests/dom/xbl/test/file_bug481558css.sjs?id=id3">
+  <link rel="stylesheet" type="text/css" href="http://example.com/tests/dom/xbl/test/file_bug481558css.sjs?id=id4&server=localhost:8888">
 </head>
 <body onload="runTest();">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=481558">Mozilla Bug 481558</a>
 <p id="id1"></p>
 <p id="id2"></p>
 <p id="id3"></p>
 <p id="id4"></p>
 <pre id="test">
rename from content/xbl/test/test_bug526178.xhtml
rename to dom/xbl/test/test_bug526178.xhtml
rename from content/xbl/test/test_bug542406.xhtml
rename to dom/xbl/test/test_bug542406.xhtml
rename from content/xbl/test/test_bug591198.html
rename to dom/xbl/test/test_bug591198.html
--- a/content/xbl/test/test_bug591198.html
+++ b/dom/xbl/test/test_bug591198.html
@@ -25,17 +25,17 @@ function runTest() {
   }, false);
   
   iframe.src = "file_bug591198_inner.html";
   let res = (yield);
   is(res.widths[0], res.widths[2], "binding was rendered");
   isnot(res.widths[0], res.widths[1], "binding was rendered");
   is(res.anonChildCount, 2, "correct number of anon children");
 
-  iframe.src = "http://noxul.example.com/tests/content/xbl/test/file_bug591198_inner.html";
+  iframe.src = "http://noxul.example.com/tests/dom/xbl/test/file_bug591198_inner.html";
   let res = (yield);
   is(res.widths[0], res.widths[1], "binding was not rendered");
   isnot(res.widths[0], res.widths[2], "binding was not rendered");
   is("anonChildCount" in res, false, "no anon children");
 
   SimpleTest.finish();
   yield undefined;
 }
rename from content/xbl/test/test_bug639338.xhtml
rename to dom/xbl/test/test_bug639338.xhtml
rename from content/xbl/test/test_bug721452.xul
rename to dom/xbl/test/test_bug721452.xul
rename from content/xbl/test/test_bug723676.xul
rename to dom/xbl/test/test_bug723676.xul
rename from content/xbl/test/test_bug772966.xul
rename to dom/xbl/test/test_bug772966.xul
rename from content/xbl/test/test_bug790265.xhtml
rename to dom/xbl/test/test_bug790265.xhtml
rename from content/xbl/test/test_bug821850.html
rename to dom/xbl/test/test_bug821850.html
rename from content/xbl/test/test_bug844783.html
rename to dom/xbl/test/test_bug844783.html
rename from content/xbl/test/test_bug944407.xul
rename to dom/xbl/test/test_bug944407.xul
--- a/content/xbl/test/test_bug944407.xul
+++ b/dom/xbl/test/test_bug944407.xul
@@ -23,17 +23,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   const Cu = Components.utils;
   Cu.import('resource://gre/modules/Services.jsm');
 
   function go() {
 
     // Disable javascript, and load the frame.
     function loadFrame() {
       ok(!Services.prefs.getBoolPref('javascript.enabled'), "Javascript should be disabled");
-      $('ifr').setAttribute('src', 'http://mochi.test:8888/tests/content/xbl/test/file_bug944407.html');
+      $('ifr').setAttribute('src', 'http://mochi.test:8888/tests/dom/xbl/test/file_bug944407.html');
     }
     SpecialPowers.pushPrefEnv({ set: [['javascript.enabled', false]] }, loadFrame);
   }
 
   function finish() {
     SimpleTest.finish();
   }
 
rename from content/xbl/test/test_bug950909.xul
rename to dom/xbl/test/test_bug950909.xul
--- a/content/xbl/test/test_bug950909.xul
+++ b/dom/xbl/test/test_bug950909.xul
@@ -27,10 +27,10 @@ https://bugzilla.mozilla.org/show_bug.cg
    */
 
   // Just wait. When the iframe loads, it'll apply the binding, which will
   // trigger the constructor for the binding.
   SimpleTest.waitForExplicitFinish();
 
   ]]>
   </script>
-  <iframe src="http://example.com/tests/content/xbl/test/file_bug950909.html"/>
+  <iframe src="http://example.com/tests/dom/xbl/test/file_bug950909.html"/>
 </window>
--- a/embedding/browser/webBrowser/nsWebBrowser.cpp
+++ b/embedding/browser/webBrowser/nsWebBrowser.cpp
@@ -131,17 +131,16 @@ NS_IMPL_RELEASE(nsWebBrowser)
 NS_INTERFACE_MAP_BEGIN(nsWebBrowser)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowser)
     NS_INTERFACE_MAP_ENTRY(nsIWebBrowser)
     NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)
     NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
     NS_INTERFACE_MAP_ENTRY(nsIScrollable)
     NS_INTERFACE_MAP_ENTRY(nsITextScroll)
     NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)
-    NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeNode)
     NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
     NS_INTERFACE_MAP_ENTRY(nsIWebBrowserSetup)
     NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPersist)
     NS_INTERFACE_MAP_ENTRY(nsICancelable)
     NS_INTERFACE_MAP_ENTRY(nsIWebBrowserFocus)
     NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
     NS_INTERFACE_MAP_ENTRY(nsIWebBrowserStream)
     NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
--- a/embedding/browser/webBrowser/nsWebBrowser.h
+++ b/embedding/browser/webBrowser/nsWebBrowser.h
@@ -13,17 +13,16 @@
 // Core Includes
 #include "nsCOMPtr.h"
 
 // Interfaces needed
 #include "nsCWebBrowser.h"
 #include "nsIBaseWindow.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
-#include "nsIDocShellTreeNode.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIScrollable.h"
 #include "nsISHistory.h"
 #include "nsITextScroll.h"
 #include "nsIWidget.h"
 #include "nsIWebProgress.h"
 #include "nsISecureBrowserUI.h"
@@ -91,17 +90,16 @@ class nsWebBrowser : public nsIWebBrowse
 friend class nsDocShellTreeOwner;
 public:
     nsWebBrowser();
 
     NS_DECL_ISUPPORTS
 
     NS_DECL_NSIBASEWINDOW
     NS_DECL_NSIDOCSHELLTREEITEM
-    NS_DECL_NSIDOCSHELLTREENODE
     NS_DECL_NSIINTERFACEREQUESTOR
     NS_DECL_NSISCROLLABLE   
     NS_DECL_NSITEXTSCROLL
     NS_DECL_NSIWEBBROWSER
     NS_DECL_NSIWEBNAVIGATION
     NS_DECL_NSIWEBBROWSERSETUP
     NS_DECL_NSIWEBBROWSERPERSIST
     NS_DECL_NSICANCELABLE
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -73,26 +73,26 @@ struct NativeFont {
  * mAlpha         - Alpha value by which the mask generated by this operation is
  *                  multiplied.
  * mCompositionOp - The operator that indicates how the source and destination
  *                  patterns are blended.
  * mAntiAliasMode - The AntiAlias mode used for this drawing operation.
  */
 struct DrawOptions {
   DrawOptions(Float aAlpha = 1.0f,
-              CompositionOp aCompositionOp = OP_OVER,
-              AntialiasMode aAntialiasMode = AA_DEFAULT)
+              CompositionOp aCompositionOp = CompositionOp::OP_OVER,
+              AntialiasMode aAntialiasMode = AntialiasMode::DEFAULT)
     : mAlpha(aAlpha)
     , mCompositionOp(aCompositionOp)
     , mAntialiasMode(aAntialiasMode)
   {}
 
   Float mAlpha;
-  CompositionOp mCompositionOp : 8;
-  AntialiasMode mAntialiasMode : 3;
+  CompositionOp mCompositionOp;
+  AntialiasMode mAntialiasMode;
 };
 
 /*
  * This structure is used to send stroke options that are used in stroking
  * operations. It consists of the following:
  *
  * mLineWidth    - Width of the stroke in userspace.
  * mLineJoin     - Join style used for joining lines.
@@ -103,18 +103,18 @@ struct DrawOptions {
  *                 this StrokeOptions.
  *                 mDashPattern != null <=> mDashLength > 0.
  * mDashLength   - Number of on/off lengths in mDashPattern.
  * mDashOffset   - Userspace offset within mDashPattern at which stroking
  *                 begins.
  */
 struct StrokeOptions {
   StrokeOptions(Float aLineWidth = 1.0f,
-                JoinStyle aLineJoin = JOIN_MITER_OR_BEVEL,
-                CapStyle aLineCap = CAP_BUTT,
+                JoinStyle aLineJoin = JoinStyle::MITER_OR_BEVEL,
+                CapStyle aLineCap = CapStyle::BUTT,
                 Float aMiterLimit = 10.0f,
                 size_t aDashLength = 0,
                 const Float* aDashPattern = 0,
                 Float aDashOffset = 0.f)
     : mLineWidth(aLineWidth)
     , mMiterLimit(aMiterLimit)
     , mDashPattern(aDashLength > 0 ? aDashPattern : 0)
     , mDashLength(aDashLength)
@@ -125,38 +125,38 @@ struct StrokeOptions {
     MOZ_ASSERT(aDashLength == 0 || aDashPattern);
   }
 
   Float mLineWidth;
   Float mMiterLimit;
   const Float* mDashPattern;
   size_t mDashLength;
   Float mDashOffset;
-  JoinStyle mLineJoin : 4;
-  CapStyle mLineCap : 3;
+  JoinStyle mLineJoin;
+  CapStyle mLineCap;
 };
 
 /*
  * This structure supplies additional options for calls to DrawSurface.
  *
  * mFilter - Filter used when resampling source surface region to the
  *           destination region.
  * aSamplingBounds - This indicates whether the implementation is allowed
  *                   to sample pixels outside the source rectangle as
  *                   specified in DrawSurface on the surface.
  */
 struct DrawSurfaceOptions {
-  DrawSurfaceOptions(Filter aFilter = FILTER_LINEAR,
-                     SamplingBounds aSamplingBounds = SAMPLING_UNBOUNDED)
+  DrawSurfaceOptions(Filter aFilter = Filter::LINEAR,
+                     SamplingBounds aSamplingBounds = SamplingBounds::UNBOUNDED)
     : mFilter(aFilter)
     , mSamplingBounds(aSamplingBounds)
   { }
 
-  Filter mFilter : 3;
-  SamplingBounds mSamplingBounds : 1;
+  Filter mFilter;
+  SamplingBounds mSamplingBounds;
 };
 
 /*
  * This class is used to store gradient stops, it can only be used with a
  * matching DrawTarget. Not adhering to this condition will make a draw call
  * fail.
  */
 class GradientStops : public RefCounted<GradientStops>
@@ -189,17 +189,17 @@ protected:
 
 class ColorPattern : public Pattern
 {
 public:
   ColorPattern(const Color &aColor)
     : mColor(aColor)
   {}
 
-  virtual PatternType GetType() const { return PATTERN_COLOR; }
+  virtual PatternType GetType() const { return PatternType::COLOR; }
 
   Color mColor;
 };
 
 /*
  * This class is used for Linear Gradient Patterns, the gradient stops are
  * stored in a separate object and are backend dependent. This class itself
  * may be used on the stack.
@@ -221,17 +221,17 @@ public:
                         const Matrix &aMatrix = Matrix())
     : mBegin(aBegin)
     , mEnd(aEnd)
     , mStops(aStops)
     , mMatrix(aMatrix)
   {
   }
 
-  virtual PatternType GetType() const { return PATTERN_LINEAR_GRADIENT; }
+  virtual PatternType GetType() const { return PatternType::LINEAR_GRADIENT; }
 
   Point mBegin;
   Point mEnd;
   RefPtr<GradientStops> mStops;
   Matrix mMatrix;
 };
 
 /*
@@ -261,17 +261,17 @@ public:
     , mCenter2(aCenter2)
     , mRadius1(aRadius1)
     , mRadius2(aRadius2)
     , mStops(aStops)
     , mMatrix(aMatrix)
   {
   }
 
-  virtual PatternType GetType() const { return PATTERN_RADIAL_GRADIENT; }
+  virtual PatternType GetType() const { return PatternType::RADIAL_GRADIENT; }
 
   Point mCenter1;
   Point mCenter2;
   Float mRadius1;
   Float mRadius2;
   RefPtr<GradientStops> mStops;
   Matrix mMatrix;
 };
@@ -286,24 +286,24 @@ public:
   /*
    * aSourceSurface Surface to use for drawing
    * aExtendMode This determines how the image is extended outside the bounds
    *             of the image.
    * aMatrix A matrix that transforms the pattern into user space
    * aFilter Resampling filter used for resampling the image.
    */
   SurfacePattern(SourceSurface *aSourceSurface, ExtendMode aExtendMode,
-                 const Matrix &aMatrix = Matrix(), Filter aFilter = FILTER_GOOD)
+                 const Matrix &aMatrix = Matrix(), Filter aFilter = Filter::GOOD)
     : mSurface(aSourceSurface)
     , mExtendMode(aExtendMode)
     , mFilter(aFilter)
     , mMatrix(aMatrix)
   {}
 
-  virtual PatternType GetType() const { return PATTERN_SURFACE; }
+  virtual PatternType GetType() const { return PatternType::SURFACE; }
 
   RefPtr<SourceSurface> mSurface;
   ExtendMode mExtendMode;
   Filter mFilter;
   Matrix mMatrix;
 };
 
 /*
@@ -332,17 +332,17 @@ public:
    * DataSourceSurface's data can be accessed directly.
    */
   virtual TemporaryRef<DataSourceSurface> GetDataSurface() = 0;
 };
 
 class DataSourceSurface : public SourceSurface
 {
 public:
-  virtual SurfaceType GetType() const { return SURFACE_DATA; }
+  virtual SurfaceType GetType() const { return SurfaceType::DATA; }
   /*
    * Get the raw bitmap data of the surface.
    * Can return null if there was OOM allocating surface data.
    */
   virtual uint8_t *GetData() = 0;
 
   /*
    * Stride of the surface, distance in bytes between the start of the image
@@ -354,17 +354,17 @@ public:
   /*
    * This function is called after modifying the data on the source surface
    * directly through the data pointer.
    */
   virtual void MarkDirty() {}
 
   /*
    * Returns a DataSourceSurface with the same data as this one, but
-   * guaranteed to have surface->GetType() == SURFACE_DATA.
+   * guaranteed to have surface->GetType() == SurfaceType::DATA.
    */
   virtual TemporaryRef<DataSourceSurface> GetDataSurface();
 };
 
 /* This is an abstract object that accepts path segments. */
 class PathSink : public RefCounted<PathSink>
 {
 public:
@@ -408,19 +408,19 @@ class Path : public RefCounted<Path>
 public:
   virtual ~Path();
   
   virtual BackendType GetBackendType() const = 0;
 
   /* This returns a PathBuilder object that contains a copy of the contents of
    * this path and is still writable.
    */
-  virtual TemporaryRef<PathBuilder> CopyToBuilder(FillRule aFillRule = FILL_WINDING) const = 0;
+  virtual TemporaryRef<PathBuilder> CopyToBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const = 0;
   virtual TemporaryRef<PathBuilder> TransformedCopyToBuilder(const Matrix &aTransform,
-                                                             FillRule aFillRule = FILL_WINDING) const = 0;
+                                                             FillRule aFillRule = FillRule::FILL_WINDING) const = 0;
 
   /* This function checks if a point lies within a path. It allows passing a
    * transform that will transform the path to the coordinate space in which
    * aPoint is given.
    */
   virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const = 0;
 
 
@@ -858,32 +858,32 @@ public:
 
   /*
    * Create a path builder with the specified fillmode.
    *
    * We need the fill mode up front because of Direct2D.
    * ID2D1SimplifiedGeometrySink requires the fill mode
    * to be set before calling BeginFigure().
    */
-  virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FILL_WINDING) const = 0;
+  virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const = 0;
 
   /*
    * Create a GradientStops object that holds information about a set of
    * gradient stops, this object is required for linear or radial gradient
    * patterns to represent the color stops in the gradient.
    *
    * aStops An array of gradient stops
    * aNumStops Number of stops in the array aStops
    * aExtendNone This describes how to extend the stop color outside of the
    *             gradient area.
    */
   virtual TemporaryRef<GradientStops>
     CreateGradientStops(GradientStop *aStops,
                         uint32_t aNumStops,
-                        ExtendMode aExtendMode = EXTEND_CLAMP) const = 0;
+                        ExtendMode aExtendMode = ExtendMode::CLAMP) const = 0;
 
   /*
    * Create a FilterNode object that can be used to apply a filter to various
    * inputs.
    *
    * aType Type of filter node to be created.
    */
   virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType) = 0;
--- a/gfx/2d/BaseMargin.h
+++ b/gfx/2d/BaseMargin.h
@@ -33,21 +33,21 @@ struct BaseMargin {
     top = aTop; right = aRight; bottom = aBottom; left = aLeft;
   }
 
   T LeftRight() const { return left + right; }
   T TopBottom() const { return top + bottom; }
 
   T& Side(SideT aSide) {
     // This is ugly!
-    return *(&top + aSide);
+    return *(&top + T(aSide));
   }
   T Side(SideT aSide) const {
     // This is ugly!
-    return *(&top + aSide);
+    return *(&top + T(aSide));
   }
 
   // Overloaded operators. Note that '=' isn't defined so we'll get the
   // compiler generated default assignment operator
   bool operator==(const Sub& aMargin) const {
     return top == aMargin.top && right == aMargin.right &&
            bottom == aMargin.bottom && left == aMargin.left;
   }
--- a/gfx/2d/DataSourceSurface.cpp
+++ b/gfx/2d/DataSourceSurface.cpp
@@ -8,17 +8,17 @@
 
 namespace mozilla {
 namespace gfx {
 
 TemporaryRef<DataSourceSurface>
 DataSourceSurface::GetDataSurface()
 {
   RefPtr<DataSourceSurface> temp;
-  if (GetType() == SURFACE_DATA) {
+  if (GetType() == SurfaceType::DATA) {
     temp = this;
   } else {
     temp = new DataSourceSurfaceWrapper(this);
   }
   return temp;
 }
 
 }
--- a/gfx/2d/DataSourceSurfaceWrapper.h
+++ b/gfx/2d/DataSourceSurfaceWrapper.h
@@ -7,25 +7,25 @@
 #define MOZILLA_GFX_DATASOURCESURFACEWRAPPER_H_
 
 #include "2D.h"
 
 namespace mozilla {
 namespace gfx {
 
 // Wraps a DataSourceSurface and forwards all methods except for GetType(),
-// from which it always returns SURFACE_DATA.
+// from which it always returns SurfaceType::DATA.
 class DataSourceSurfaceWrapper : public DataSourceSurface
 {
 public:
   DataSourceSurfaceWrapper(DataSourceSurface *aSurface)
    : mSurface(aSurface)
   {}
 
-  virtual SurfaceType GetType() const MOZ_OVERRIDE { return SURFACE_DATA; }
+  virtual SurfaceType GetType() const MOZ_OVERRIDE { return SurfaceType::DATA; }
 
   virtual uint8_t *GetData() MOZ_OVERRIDE { return mSurface->GetData(); }
   virtual int32_t Stride() MOZ_OVERRIDE { return mSurface->Stride(); }
   virtual IntSize GetSize() const MOZ_OVERRIDE { return mSurface->GetSize(); }
   virtual SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mSurface->GetFormat(); }
   virtual bool IsValid() const MOZ_OVERRIDE { return mSurface->IsValid(); }
   virtual void MarkDirty() { mSurface->MarkDirty(); }
 
--- a/gfx/2d/DataSurfaceHelpers.h
+++ b/gfx/2d/DataSurfaceHelpers.h
@@ -35,17 +35,17 @@ inline uint8_t *
 SurfaceToPackedBGRA(SourceSurface *aSurface)
 {
   RefPtr<DataSourceSurface> data = aSurface->GetDataSurface();
   if (!data) {
     return nullptr;
   }
 
   SurfaceFormat format = data->GetFormat();
-  if (format != FORMAT_B8G8R8A8 && format != FORMAT_B8G8R8X8) {
+  if (format != SurfaceFormat::B8G8R8A8 && format != SurfaceFormat::B8G8R8X8) {
     return nullptr;
   }
 
   IntSize size = data->GetSize();
 
   uint8_t* imageBuffer = new (std::nothrow) uint8_t[size.width * size.height * sizeof(uint32_t)];
   if (!imageBuffer) {
     return nullptr;
@@ -63,17 +63,17 @@ SurfaceToPackedBGRA(SourceSurface *aSurf
     for (int row = 0; row < size.height; ++row) {
       for (int column = 0; column < size.width; ++column) {
         *dst++ = src[column];
       }
       src += (stride/4);
     }
   }
 
-  if (format == FORMAT_B8G8R8X8) {
+  if (format == SurfaceFormat::B8G8R8X8) {
     // Convert BGRX to BGRA by setting a to 255.
     ConvertBGRXToBGRA(reinterpret_cast<uint8_t *>(imageBuffer), size, size.width * sizeof(uint32_t));
   }
 
   return imageBuffer;
 }
 
 }
--- a/gfx/2d/DrawTargetCG.cpp
+++ b/gfx/2d/DrawTargetCG.cpp
@@ -32,92 +32,92 @@ static CGRect IntRectToCGRect(IntRect r)
 {
   return CGRectMake(r.x, r.y, r.width, r.height);
 }
 
 CGBlendMode ToBlendMode(CompositionOp op)
 {
   CGBlendMode mode;
   switch (op) {
-    case OP_OVER:
+    case CompositionOp::OP_OVER:
       mode = kCGBlendModeNormal;
       break;
-    case OP_ADD:
+    case CompositionOp::OP_ADD:
       mode = kCGBlendModePlusLighter;
       break;
-    case OP_ATOP:
+    case CompositionOp::OP_ATOP:
       mode = kCGBlendModeSourceAtop;
       break;
-    case OP_OUT:
+    case CompositionOp::OP_OUT:
       mode = kCGBlendModeSourceOut;
       break;
-    case OP_IN:
+    case CompositionOp::OP_IN:
       mode = kCGBlendModeSourceIn;
       break;
-    case OP_SOURCE:
+    case CompositionOp::OP_SOURCE:
       mode = kCGBlendModeCopy;
       break;
-    case OP_DEST_IN:
+    case CompositionOp::OP_DEST_IN:
       mode = kCGBlendModeDestinationIn;
       break;
-    case OP_DEST_OUT:
+    case CompositionOp::OP_DEST_OUT:
       mode = kCGBlendModeDestinationOut;
       break;
-    case OP_DEST_OVER:
+    case CompositionOp::OP_DEST_OVER:
       mode = kCGBlendModeDestinationOver;
       break;
-    case OP_DEST_ATOP:
+    case CompositionOp::OP_DEST_ATOP:
       mode = kCGBlendModeDestinationAtop;
       break;
-    case OP_XOR:
+    case CompositionOp::OP_XOR:
       mode = kCGBlendModeXOR;
       break;
-    case OP_MULTIPLY:
+    case CompositionOp::OP_MULTIPLY:
       mode = kCGBlendModeMultiply;
       break;
-    case OP_SCREEN:
+    case CompositionOp::OP_SCREEN:
       mode = kCGBlendModeScreen;
       break;
-    case OP_OVERLAY:
+    case CompositionOp::OP_OVERLAY:
       mode = kCGBlendModeOverlay;
       break;
-    case OP_DARKEN:
+    case CompositionOp::OP_DARKEN:
       mode = kCGBlendModeDarken;
       break;
-    case OP_LIGHTEN:
+    case CompositionOp::OP_LIGHTEN:
       mode = kCGBlendModeLighten;
       break;
-    case OP_COLOR_DODGE:
+    case CompositionOp::OP_COLOR_DODGE:
       mode = kCGBlendModeColorDodge;
       break;
-    case OP_COLOR_BURN:
+    case CompositionOp::OP_COLOR_BURN:
       mode = kCGBlendModeColorBurn;
       break;
-    case OP_HARD_LIGHT:
+    case CompositionOp::OP_HARD_LIGHT:
       mode = kCGBlendModeHardLight;
       break;
-    case OP_SOFT_LIGHT:
+    case CompositionOp::OP_SOFT_LIGHT:
       mode = kCGBlendModeSoftLight;
       break;
-    case OP_DIFFERENCE:
+    case CompositionOp::OP_DIFFERENCE:
       mode = kCGBlendModeDifference;
       break;
-    case OP_EXCLUSION:
+    case CompositionOp::OP_EXCLUSION:
       mode = kCGBlendModeExclusion;
       break;
-    case OP_HUE:
+    case CompositionOp::OP_HUE:
       mode = kCGBlendModeHue;
       break;
-    case OP_SATURATION:
+    case CompositionOp::OP_SATURATION:
       mode = kCGBlendModeSaturation;
       break;
-    case OP_COLOR:
+    case CompositionOp::OP_COLOR:
       mode = kCGBlendModeColor;
       break;
-    case OP_LUMINOSITY:
+    case CompositionOp::OP_LUMINOSITY:
       mode = kCGBlendModeLuminosity;
       break;
       /*
     case OP_CLEAR:
       mode = kCGBlendModeClear;
       break;*/
     default:
       mode = kCGBlendModeNormal;
@@ -125,21 +125,21 @@ CGBlendMode ToBlendMode(CompositionOp op
   return mode;
 }
 
 static CGInterpolationQuality
 InterpolationQualityFromFilter(Filter aFilter)
 {
   switch (aFilter) {
     default:
-    case FILTER_LINEAR:
+    case Filter::LINEAR:
       return kCGInterpolationLow;
-    case FILTER_POINT:
+    case Filter::POINT:
       return kCGInterpolationNone;
-    case FILTER_GOOD:
+    case Filter::GOOD:
       return kCGInterpolationDefault;
   }
 }
 
 
 DrawTargetCG::DrawTargetCG() : mCg(nullptr), mSnapshot(nullptr)
 {
 }
@@ -156,19 +156,19 @@ DrawTargetCG::~DrawTargetCG()
 }
 
 BackendType
 DrawTargetCG::GetType() const
 {
   // It may be worth spliting Bitmap and IOSurface DrawTarget
   // into seperate classes.
   if (GetContextType(mCg) == CG_CONTEXT_TYPE_IOSURFACE) {
-    return BACKEND_COREGRAPHICS_ACCELERATED;
+    return BackendType::COREGRAPHICS_ACCELERATED;
   } else {
-    return BACKEND_COREGRAPHICS;
+    return BackendType::COREGRAPHICS;
   }
 }
 
 TemporaryRef<SourceSurface>
 DrawTargetCG::Snapshot()
 {
   if (!mSnapshot) {
     if (GetContextType(mCg) == CG_CONTEXT_TYPE_IOSURFACE) {
@@ -210,22 +210,22 @@ DrawTargetCG::CreateSourceSurfaceFromDat
 }
 
 // This function returns a retained CGImage that needs to be released after
 // use. The reason for this is that we want to either reuse an existing CGImage
 // or create a new one.
 static CGImageRef
 GetRetainedImageFromSourceSurface(SourceSurface *aSurface)
 {
-  if (aSurface->GetType() == SURFACE_COREGRAPHICS_IMAGE)
+  if (aSurface->GetType() == SurfaceType::COREGRAPHICS_IMAGE)
     return CGImageRetain(static_cast<SourceSurfaceCG*>(aSurface)->GetImage());
-  else if (aSurface->GetType() == SURFACE_COREGRAPHICS_CGCONTEXT)
+  else if (aSurface->GetType() == SurfaceType::COREGRAPHICS_CGCONTEXT)
     return CGImageRetain(static_cast<SourceSurfaceCGContext*>(aSurface)->GetImage());
 
-  if (aSurface->GetType() == SURFACE_DATA) {
+  if (aSurface->GetType() == SurfaceType::DATA) {
     DataSourceSurface* dataSource = static_cast<DataSourceSurface*>(aSurface);
     return CreateCGImage(nullptr, dataSource->GetData(), dataSource->GetSize(),
                          dataSource->Stride(), dataSource->GetFormat());
   }
 
   MOZ_CRASH("unsupported source surface");
 }
 
@@ -292,17 +292,17 @@ DrawTargetCG::DrawSurface(SourceSurface 
   MarkChanged();
 
   CGContextSaveGState(mCg);
 
   CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp));
   UnboundnessFixer fixer;
   CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp);
   CGContextSetAlpha(cg, aDrawOptions.mAlpha);
-  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AA_NONE);
+  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AntialiasMode::NONE);
 
   CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform));
   CGImageRef image = GetRetainedImageFromSourceSurface(aSurface);
 
   /* we have two options here:
    *  - create a subimage -- this is slower
    *  - fancy things with clip and different dest rects */
   CGImageRef subimage = CGImageCreateWithImageInRect(image, RectToCGRect(aSource));
@@ -348,17 +348,17 @@ static CGColorRef ColorToCGColor(CGColor
 
 class GradientStopsCG : public GradientStops
 {
   public:
   //XXX: The skia backend uses a vector and passes in aNumStops. It should do better
   GradientStopsCG(GradientStop* aStops, uint32_t aNumStops, ExtendMode aExtendMode)
   {
     mExtend = aExtendMode;
-    if (aExtendMode == EXTEND_CLAMP) {
+    if (aExtendMode == ExtendMode::CLAMP) {
       //XXX: do the stops need to be in any particular order?
       // what should we do about the color space here? we certainly shouldn't be
       // recreating it all the time
       std::vector<CGFloat> colors;
       std::vector<CGFloat> offsets;
       colors.reserve(aNumStops*4);
       offsets.reserve(aNumStops);
 
@@ -385,19 +385,19 @@ class GradientStopsCG : public GradientS
       }
     }
 
   }
   virtual ~GradientStopsCG() {
     if (mGradient)
         CGGradientRelease(mGradient);
   }
-  // Will always report BACKEND_COREGRAPHICS, but it is compatible
-  // with BACKEND_COREGRAPHICS_ACCELERATED
-  BackendType GetBackendType() const { return BACKEND_COREGRAPHICS; }
+  // Will always report BackendType::COREGRAPHICS, but it is compatible
+  // with BackendType::COREGRAPHICS_ACCELERATED
+  BackendType GetBackendType() const { return BackendType::COREGRAPHICS; }
   // XXX this should be a union
   CGGradientRef mGradient;
   std::vector<GradientStop> mStops;
   ExtendMode mExtend;
 };
 
 TemporaryRef<GradientStops>
 DrawTargetCG::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops,
@@ -600,51 +600,51 @@ DrawRadialRepeatingGradient(CGContextRef
   CGContextDrawRadialGradient(cg, gradient, startCenter, startRadius, endCenter, endRadius,
                               kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
   CGGradientRelease(gradient);
 }
 
 static void
 DrawGradient(CGContextRef cg, const Pattern &aPattern, const CGRect &aExtents)
 {
-  if (aPattern.GetType() == PATTERN_LINEAR_GRADIENT) {
+  if (aPattern.GetType() == PatternType::LINEAR_GRADIENT) {
     const LinearGradientPattern& pat = static_cast<const LinearGradientPattern&>(aPattern);
     GradientStopsCG *stops = static_cast<GradientStopsCG*>(pat.mStops.get());
     CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(pat.mMatrix));
-    if (stops->mExtend == EXTEND_CLAMP) {
+    if (stops->mExtend == ExtendMode::CLAMP) {
 
       // XXX: we should take the m out of the properties of LinearGradientPatterns
       CGPoint startPoint = { pat.mBegin.x, pat.mBegin.y };
       CGPoint endPoint   = { pat.mEnd.x,   pat.mEnd.y };
 
       // Canvas spec states that we should avoid drawing degenerate gradients (XXX: should this be in common code?)
       //if (startPoint.x == endPoint.x && startPoint.y == endPoint.y)
       //  return;
 
       CGContextDrawLinearGradient(cg, stops->mGradient, startPoint, endPoint,
                                   kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
-    } else if (stops->mExtend == EXTEND_REPEAT) {
+    } else if (stops->mExtend == ExtendMode::REPEAT) {
       DrawLinearRepeatingGradient(cg, pat, aExtents);
     }
-  } else if (aPattern.GetType() == PATTERN_RADIAL_GRADIENT) {
+  } else if (aPattern.GetType() == PatternType::RADIAL_GRADIENT) {
     const RadialGradientPattern& pat = static_cast<const RadialGradientPattern&>(aPattern);
     CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(pat.mMatrix));
     GradientStopsCG *stops = static_cast<GradientStopsCG*>(pat.mStops.get());
-    if (stops->mExtend == EXTEND_CLAMP) {
+    if (stops->mExtend == ExtendMode::CLAMP) {
 
       // XXX: we should take the m out of the properties of RadialGradientPatterns
       CGPoint startCenter = { pat.mCenter1.x, pat.mCenter1.y };
       CGFloat startRadius = pat.mRadius1;
       CGPoint endCenter   = { pat.mCenter2.x, pat.mCenter2.y };
       CGFloat endRadius   = pat.mRadius2;
 
       //XXX: are there degenerate radial gradients that we should avoid drawing?
       CGContextDrawRadialGradient(cg, stops->mGradient, startCenter, startRadius, endCenter, endRadius,
                                   kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
-    } else if (stops->mExtend == EXTEND_REPEAT) {
+    } else if (stops->mExtend == ExtendMode::REPEAT) {
       DrawRadialRepeatingGradient(cg, pat, aExtents);
     }
   } else {
     assert(0);
   }
 
 }
 
@@ -669,37 +669,37 @@ CGPatternCallbacks patternCallbacks = {
   0,
   drawPattern,
   releaseInfo
 };
 
 static bool
 isGradient(const Pattern &aPattern)
 {
-  return aPattern.GetType() == PATTERN_LINEAR_GRADIENT || aPattern.GetType() == PATTERN_RADIAL_GRADIENT;
+  return aPattern.GetType() == PatternType::LINEAR_GRADIENT || aPattern.GetType() == PatternType::RADIAL_GRADIENT;
 }
 
 /* CoreGraphics patterns ignore the userspace transform so
  * we need to multiply it in */
 static CGPatternRef
 CreateCGPattern(const Pattern &aPattern, CGAffineTransform aUserSpace)
 {
   const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
   // XXX: is .get correct here?
   CGImageRef image = GetRetainedImageFromSourceSurface(pat.mSurface.get());
   CGFloat xStep, yStep;
   switch (pat.mExtendMode) {
-    case EXTEND_CLAMP:
+    case ExtendMode::CLAMP:
       // The 1 << 22 comes from Webkit see Pattern::createPlatformPattern() in PatternCG.cpp for more info
       xStep = static_cast<CGFloat>(1 << 22);
       yStep = static_cast<CGFloat>(1 << 22);
       break;
-    case EXTEND_REFLECT:
+    case ExtendMode::REFLECT:
       assert(0);
-    case EXTEND_REPEAT:
+    case ExtendMode::REPEAT:
       xStep = static_cast<CGFloat>(CGImageGetWidth(image));
       yStep = static_cast<CGFloat>(CGImageGetHeight(image));
       // webkit uses wkCGPatternCreateWithImageAndTransform a wrapper around CGPatternCreateWithImage2
       // this is done to avoid pixel-cracking along pattern boundaries
       // (see https://bugs.webkit.org/show_bug.cgi?id=53055)
       // typedef enum {
       //    wkPatternTilingNoDistortion,
       //    wkPatternTilingConstantSpacingMinimalDistortion,
@@ -724,24 +724,24 @@ CreateCGPattern(const Pattern &aPattern,
   return CGPatternCreate(image, bounds, transform, xStep, yStep, kCGPatternTilingConstantSpacing,
                          true, &patternCallbacks);
 }
 
 static void
 SetFillFromPattern(CGContextRef cg, CGColorSpaceRef aColorSpace, const Pattern &aPattern)
 {
   assert(!isGradient(aPattern));
-  if (aPattern.GetType() == PATTERN_COLOR) {
+  if (aPattern.GetType() == PatternType::COLOR) {
 
     const Color& color = static_cast<const ColorPattern&>(aPattern).mColor;
     //XXX: we should cache colors
     CGColorRef cgcolor = ColorToCGColor(aColorSpace, color);
     CGContextSetFillColorWithColor(cg, cgcolor);
     CGColorRelease(cgcolor);
-  } else if (aPattern.GetType() == PATTERN_SURFACE) {
+  } else if (aPattern.GetType() == PatternType::SURFACE) {
 
     CGColorSpaceRef patternSpace;
     patternSpace = CGColorSpaceCreatePattern (nullptr);
     CGContextSetFillColorSpace(cg, patternSpace);
     CGColorSpaceRelease(patternSpace);
 
     CGPatternRef pattern = CreateCGPattern(aPattern, CGContextGetCTM(cg));
     const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
@@ -751,23 +751,23 @@ SetFillFromPattern(CGContextRef cg, CGCo
     CGPatternRelease(pattern);
   }
 }
 
 static void
 SetStrokeFromPattern(CGContextRef cg, CGColorSpaceRef aColorSpace, const Pattern &aPattern)
 {
   assert(!isGradient(aPattern));
-  if (aPattern.GetType() == PATTERN_COLOR) {
+  if (aPattern.GetType() == PatternType::COLOR) {
     const Color& color = static_cast<const ColorPattern&>(aPattern).mColor;
     //XXX: we should cache colors
     CGColorRef cgcolor = ColorToCGColor(aColorSpace, color);
     CGContextSetStrokeColorWithColor(cg, cgcolor);
     CGColorRelease(cgcolor);
-  } else if (aPattern.GetType() == PATTERN_SURFACE) {
+  } else if (aPattern.GetType() == PatternType::SURFACE) {
     CGColorSpaceRef patternSpace;
     patternSpace = CGColorSpaceCreatePattern (nullptr);
     CGContextSetStrokeColorSpace(cg, patternSpace);
     CGColorSpaceRelease(patternSpace);
 
     CGPatternRef pattern = CreateCGPattern(aPattern, CGContextGetCTM(cg));
     const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
     CGContextSetInterpolationQuality(cg, InterpolationQualityFromFilter(pat.mFilter));
@@ -787,17 +787,17 @@ DrawTargetCG::MaskSurface(const Pattern 
   MarkChanged();
 
   CGContextSaveGState(mCg);
 
   CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp));
   UnboundnessFixer fixer;
   CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp);
   CGContextSetAlpha(cg, aDrawOptions.mAlpha);
-  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AA_NONE);
+  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AntialiasMode::NONE);
 
   CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform));
   CGImageRef image = GetRetainedImageFromSourceSurface(aMask);
 
   // use a negative-y so that the mask image draws right ways up
   CGContextScaleCTM(cg, 1, -1);
 
   IntSize size = aMask->GetSize();
@@ -830,26 +830,26 @@ DrawTargetCG::FillRect(const Rect &aRect
 {
   MarkChanged();
 
   CGContextSaveGState(mCg);
 
   UnboundnessFixer fixer;
   CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp);
   CGContextSetAlpha(mCg, aDrawOptions.mAlpha);
-  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AA_NONE);
+  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AntialiasMode::NONE);
   CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp));
 
   CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform));
 
   if (isGradient(aPattern)) {
     CGContextClipToRect(cg, RectToCGRect(aRect));
     DrawGradient(cg, aPattern, RectToCGRect(aRect));
   } else {
-    if (aPattern.GetType() == PATTERN_SURFACE && static_cast<const SurfacePattern&>(aPattern).mExtendMode != EXTEND_REPEAT) {
+    if (aPattern.GetType() == PatternType::SURFACE && static_cast<const SurfacePattern&>(aPattern).mExtendMode != ExtendMode::REPEAT) {
       // SetFillFromPattern can handle this case but using CGContextDrawImage
       // should give us better performance, better output, smaller PDF and
       // matches what cairo does.
       const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
       CGImageRef image = GetRetainedImageFromSourceSurface(pat.mSurface.get());
       CGContextClipToRect(cg, RectToCGRect(aRect));
       CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(pat.mMatrix));
       CGContextTranslateCTM(cg, 0, CGImageGetHeight(image));
@@ -883,17 +883,17 @@ DrawTargetCG::StrokeLine(const Point &p1
 
   MarkChanged();
 
   CGContextSaveGState(mCg);
 
   UnboundnessFixer fixer;
   CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp);
   CGContextSetAlpha(mCg, aDrawOptions.mAlpha);
-  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AA_NONE);
+  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AntialiasMode::NONE);
   CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp));
 
   CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform));
 
   CGContextBeginPath(cg);
   CGContextMoveToPoint(cg, p1.x, p1.y);
   CGContextAddLineToPoint(cg, p2.x, p2.y);
 
@@ -926,17 +926,17 @@ DrawTargetCG::StrokeRect(const Rect &aRe
 
   MarkChanged();
 
   CGContextSaveGState(mCg);
 
   UnboundnessFixer fixer;
   CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp);
   CGContextSetAlpha(mCg, aDrawOptions.mAlpha);
-  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AA_NONE);
+  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AntialiasMode::NONE);
   CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp));
 
   CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform));
 
   SetStrokeOptions(cg, aStrokeOptions);
 
   if (isGradient(aPattern)) {
     // There's no CGContextClipStrokeRect so we do it by hand
@@ -979,25 +979,25 @@ DrawTargetCG::Stroke(const Path *aPath, 
 
   MarkChanged();
 
   CGContextSaveGState(mCg);
 
   UnboundnessFixer fixer;
   CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp);
   CGContextSetAlpha(mCg, aDrawOptions.mAlpha);
-  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AA_NONE);
+  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AntialiasMode::NONE);
   CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp));
 
   CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform));
 
 
   CGContextBeginPath(cg);
 
-  assert(aPath->GetBackendType() == BACKEND_COREGRAPHICS);
+  assert(aPath->GetBackendType() == BackendType::COREGRAPHICS);
   const PathCG *cgPath = static_cast<const PathCG*>(aPath);
   CGContextAddPath(cg, cgPath->GetPath());
 
   SetStrokeOptions(cg, aStrokeOptions);
 
   if (isGradient(aPattern)) {
     CGContextReplacePathWithStrokedPath(cg);
     CGRect extents = CGContextGetPathBoundingBox(cg);
@@ -1015,25 +1015,25 @@ DrawTargetCG::Stroke(const Path *aPath, 
   CGContextRestoreGState(mCg);
 }
 
 void
 DrawTargetCG::Fill(const Path *aPath, const Pattern &aPattern, const DrawOptions &aDrawOptions)
 {
   MarkChanged();
 
-  assert(aPath->GetBackendType() == BACKEND_COREGRAPHICS);
+  assert(aPath->GetBackendType() == BackendType::COREGRAPHICS);
 
   CGContextSaveGState(mCg);
 
   CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp));
   UnboundnessFixer fixer;
   CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp);
   CGContextSetAlpha(cg, aDrawOptions.mAlpha);
-  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AA_NONE);
+  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AntialiasMode::NONE);
 
   CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform));
 
   CGContextBeginPath(cg);
   // XXX: we could put fill mode into the path fill rule if we wanted
   const PathCG *cgPath = static_cast<const PathCG*>(aPath);
 
   if (isGradient(aPattern)) {
@@ -1042,29 +1042,29 @@ DrawTargetCG::Fill(const Path *aPath, co
     if (CGPathIsEmpty(cgPath->GetPath())) {
       // Adding an empty path will cause us not to clip
       // so clip everything explicitly
       CGContextClipToRect(mCg, CGRectZero);
       extents = CGRectZero;
     } else {
       CGContextAddPath(cg, cgPath->GetPath());
       extents = CGContextGetPathBoundingBox(cg);
-      if (cgPath->GetFillRule() == FILL_EVEN_ODD)
+      if (cgPath->GetFillRule() == FillRule::FILL_EVEN_ODD)
         CGContextEOClip(mCg);
       else
         CGContextClip(mCg);
     }
 
     DrawGradient(cg, aPattern, extents);
   } else {
     CGContextAddPath(cg, cgPath->GetPath());
 
     SetFillFromPattern(cg, mColorSpace, aPattern);
 
-    if (cgPath->GetFillRule() == FILL_EVEN_ODD)
+    if (cgPath->GetFillRule() == FillRule::FILL_EVEN_ODD)
       CGContextEOFillPath(cg);
     else
       CGContextFillPath(cg);
   }
 
   fixer.Fix(mCg);
   CGContextRestoreGState(mCg);
 }
@@ -1101,19 +1101,19 @@ DrawTargetCG::FillGlyphs(ScaledFont *aFo
 
   assert(aBuffer.mNumGlyphs);
   CGContextSaveGState(mCg);
 
   CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp));
   UnboundnessFixer fixer;
   CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp);
   CGContextSetAlpha(cg, aDrawOptions.mAlpha);
-  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AA_NONE);
-  if (aDrawOptions.mAntialiasMode != AA_DEFAULT) {
-    CGContextSetShouldSmoothFonts(cg, aDrawOptions.mAntialiasMode == AA_SUBPIXEL);
+  CGContextSetShouldAntialias(cg, aDrawOptions.mAntialiasMode != AntialiasMode::NONE);
+  if (aDrawOptions.mAntialiasMode != AntialiasMode::DEFAULT) {
+    CGContextSetShouldSmoothFonts(cg, aDrawOptions.mAntialiasMode == AntialiasMode::SUBPIXEL);
   }
 
   CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform));
 
   ScaledFontMac* macFont = static_cast<ScaledFontMac*>(aFont);
 
   //XXX: we should use a stack vector here when we have a class like that
   std::vector<CGGlyph> glyphs;
@@ -1188,18 +1188,18 @@ CGContextResetClip(CGContextRef);
 
 void
 DrawTargetCG::CopySurface(SourceSurface *aSurface,
                           const IntRect& aSourceRect,
                           const IntPoint &aDestination)
 {
   MarkChanged();
 
-  if (aSurface->GetType() == SURFACE_COREGRAPHICS_IMAGE ||
-      aSurface->GetType() == SURFACE_COREGRAPHICS_CGCONTEXT) {
+  if (aSurface->GetType() == SurfaceType::COREGRAPHICS_IMAGE ||
+      aSurface->GetType() == SurfaceType::COREGRAPHICS_CGCONTEXT) {
     CGImageRef image = GetRetainedImageFromSourceSurface(aSurface);
 
     /* we have two options here:
      *  - create a subimage -- this is slower
      *  - fancy things with clip and different dest rects */
     CGImageRef subimage = CGImageCreateWithImageInRect(image, IntRectToCGRect(aSourceRect));
     CGImageRelease(image);
     // XXX: it might be more efficient for us to do the copy directly if we have access to the bits
@@ -1212,17 +1212,17 @@ DrawTargetCG::CopySurface(SourceSurface 
 
     CGContextScaleCTM(mCg, 1, -1);
 
     CGRect flippedRect = CGRectMake(aDestination.x, -(aDestination.y + aSourceRect.height),
                                     aSourceRect.width, aSourceRect.height);
 
     // Quartz seems to copy A8 surfaces incorrectly if we don't initialize them
     // to transparent first.
-    if (mFormat == FORMAT_A8) {
+    if (mFormat == SurfaceFormat::A8) {
       CGContextClearRect(mCg, flippedRect);
     }
     CGContextDrawImage(mCg, flippedRect, subimage);
 
     CGContextRestoreGState(mCg);
 
     CGImageRelease(subimage);
   }
@@ -1276,47 +1276,47 @@ DrawTargetCG::Init(BackendType aType,
     return false;
   }
 
   //XXX: handle SurfaceFormat
 
   //XXX: we'd be better off reusing the Colorspace across draw targets
   mColorSpace = CGColorSpaceCreateDeviceRGB();
 
-  if (aData == nullptr && aType != BACKEND_COREGRAPHICS_ACCELERATED) {
+  if (aData == nullptr && aType != BackendType::COREGRAPHICS_ACCELERATED) {
     // XXX: Currently, Init implicitly clears, that can often be a waste of time
     mData.Realloc(aStride * aSize.height);
     aData = static_cast<unsigned char*>(mData);
     memset(aData, 0, aStride * aSize.height);
   }
 
   mSize = aSize;
 
-  if (aType == BACKEND_COREGRAPHICS_ACCELERATED) {
+  if (aType == BackendType::COREGRAPHICS_ACCELERATED) {
     RefPtr<MacIOSurface> ioSurface = MacIOSurface::CreateIOSurface(aSize.width, aSize.height);
     mCg = ioSurface->CreateIOSurfaceContext();
     // If we don't have the symbol for 'CreateIOSurfaceContext' mCg will be null
     // and we will fallback to software below
   }
 
-  mFormat = FORMAT_B8G8R8A8;
+  mFormat = SurfaceFormat::B8G8R8A8;
 
-  if (!mCg || aType == BACKEND_COREGRAPHICS) {
+  if (!mCg || aType == BackendType::COREGRAPHICS) {
     int bitsPerComponent = 8;
 
     CGBitmapInfo bitinfo;
-    if (aFormat == FORMAT_A8) {
+    if (aFormat == SurfaceFormat::A8) {
       if (mColorSpace)
         CGColorSpaceRelease(mColorSpace);
       mColorSpace = nullptr;
       bitinfo = kCGImageAlphaOnly;
-      mFormat = FORMAT_A8;
+      mFormat = SurfaceFormat::A8;
     } else {
       bitinfo = kCGBitmapByteOrder32Host;
-      if (aFormat == FORMAT_B8G8R8X8) {
+      if (aFormat == SurfaceFormat::B8G8R8X8) {
         bitinfo |= kCGImageAlphaNoneSkipFirst;
         mFormat = aFormat;
       } else {
         bitinfo |= kCGImageAlphaPremultipliedFirst;
       }
     }
     // XXX: what should we do if this fails?
     mCg = CGBitmapContextCreate (aData,
@@ -1339,17 +1339,17 @@ DrawTargetCG::Init(BackendType aType,
   // to have competitive performance with other canvas
   // implementation.
   // XXX: Create input parameter to control interpolation and
   //      use the default for content.
   CGContextSetInterpolationQuality(mCg, kCGInterpolationLow);
   CGContextSetShouldSmoothFonts(mCg, GetPermitSubpixelAA());
 
 
-  if (aType == BACKEND_COREGRAPHICS_ACCELERATED) {
+  if (aType == BackendType::COREGRAPHICS_ACCELERATED) {
     // The bitmap backend uses callac to clear, we can't do that without
     // reading back the surface. This should trigger something equivilent
     // to glClear.
     ClearRect(Rect(0, 0, mSize.width, mSize.height));
   }
 
   return true;
 }
@@ -1389,25 +1389,25 @@ DrawTargetCG::Init(CGContextRef cgContex
   // CGContext's default to have the origin at the bottom left.
   // However, currently the only use of this function is to construct a
   // DrawTargetCG around a CGContextRef from a cairo quartz surface which
   // already has it's origin adjusted.
   //
   // CGContextTranslateCTM(mCg, 0, mSize.height);
   // CGContextScaleCTM(mCg, 1, -1);
 
-  mFormat = FORMAT_B8G8R8A8;
+  mFormat = SurfaceFormat::B8G8R8A8;
   if (GetContextType(mCg) == CG_CONTEXT_TYPE_BITMAP) {
     CGColorSpaceRef colorspace;
     CGBitmapInfo bitinfo = CGBitmapContextGetBitmapInfo(mCg);
     colorspace = CGBitmapContextGetColorSpace (mCg);
     if (CGColorSpaceGetNumberOfComponents(colorspace) == 1) {
-      mFormat = FORMAT_A8;
+      mFormat = SurfaceFormat::A8;
     } else if ((bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaNoneSkipFirst) {
-      mFormat = FORMAT_B8G8R8X8;
+      mFormat = SurfaceFormat::B8G8R8X8;
     }
   }
 
   return true;
 }
 
 bool
 DrawTargetCG::Init(BackendType aType, const IntSize &aSize, SurfaceFormat &aFormat)
@@ -1423,18 +1423,18 @@ DrawTargetCG::CreatePathBuilder(FillRule
 {
   RefPtr<PathBuilderCG> pb = new PathBuilderCG(aFillRule);
   return pb;
 }
 
 void*
 DrawTargetCG::GetNativeSurface(NativeSurfaceType aType)
 {
-  if ((aType == NATIVE_SURFACE_CGCONTEXT && GetContextType(mCg) == CG_CONTEXT_TYPE_BITMAP) ||
-      (aType == NATIVE_SURFACE_CGCONTEXT_ACCELERATED && GetContextType(mCg) == CG_CONTEXT_TYPE_IOSURFACE)) {
+  if ((aType == NativeSurfaceType::CGCONTEXT && GetContextType(mCg) == CG_CONTEXT_TYPE_BITMAP) ||
+      (aType == NativeSurfaceType::CGCONTEXT_ACCELERATED && GetContextType(mCg) == CG_CONTEXT_TYPE_IOSURFACE)) {
     return mCg;
   } else {
     return nullptr;
   }
 }
 
 void
 DrawTargetCG::Mask(const Pattern &aSource,
@@ -1443,25 +1443,25 @@ DrawTargetCG::Mask(const Pattern &aSourc
 {
   MarkChanged();
 
   CGContextSaveGState(mCg);
 
   if (isGradient(aMask)) {
     assert(0);
   } else {
-    if (aMask.GetType() == PATTERN_COLOR) {
+    if (aMask.GetType() == PatternType::COLOR) {
       DrawOptions drawOptions(aDrawOptions);
       const Color& color = static_cast<const ColorPattern&>(aMask).mColor;
       drawOptions.mAlpha *= color.a;
       assert(0);
       // XXX: we need to get a rect that when transformed covers the entire surface
       //Rect
       //FillRect(rect, aSource, drawOptions);
-    } else if (aMask.GetType() == PATTERN_SURFACE) {
+    } else if (aMask.GetType() == PatternType::SURFACE) {
       const SurfacePattern& pat = static_cast<const SurfacePattern&>(aMask);
       CGImageRef mask = GetRetainedImageFromSourceSurface(pat.mSurface.get());
       Rect rect(0,0, CGImageGetWidth(mask), CGImageGetHeight(mask));
       // XXX: probably we need to do some flipping of the image or something
       CGContextClipToMask(mCg, RectToCGRect(rect), mask);
       FillRect(rect, aSource, aDrawOptions);
       CGImageRelease(mask);
     }
@@ -1485,17 +1485,17 @@ DrawTargetCG::PushClipRect(const Rect &a
 
 
 void
 DrawTargetCG::PushClip(const Path *aPath)
 {
   CGContextSaveGState(mCg);
 
   CGContextBeginPath(mCg);
-  assert(aPath->GetBackendType() == BACKEND_COREGRAPHICS);
+  assert(aPath->GetBackendType() == BackendType::COREGRAPHICS);
 
   const PathCG *cgPath = static_cast<const PathCG*>(aPath);
 
   // Weirdly, CoreGraphics clips empty paths as all shown
   // but emtpy rects as all clipped.  We detect this situation and
   // workaround it appropriately
   if (CGPathIsEmpty(cgPath->GetPath())) {
     // XXX: should we return here?
@@ -1506,17 +1506,17 @@ DrawTargetCG::PushClip(const Path *aPath
   /* We go through a bit of trouble to temporarilly set the transform
    * while we add the path. XXX: this could be improved if we keep
    * the CTM as resident state on the DrawTarget. */
   CGContextSaveGState(mCg);
   CGContextConcatCTM(mCg, GfxMatrixToCGAffineTransform(mTransform));
   CGContextAddPath(mCg, cgPath->GetPath());
   CGContextRestoreGState(mCg);
 
-  if (cgPath->GetFillRule() == FILL_EVEN_ODD)
+  if (cgPath->GetFillRule() == FillRule::FILL_EVEN_ODD)
     CGContextEOClip(mCg);
   else
     CGContextClip(mCg);
 }
 
 void
 DrawTargetCG::PopClip()
 {
@@ -1539,17 +1539,17 @@ void
 DrawTargetCG::SetPermitSubpixelAA(bool aPermitSubpixelAA) {
   DrawTarget::SetPermitSubpixelAA(aPermitSubpixelAA);
   CGContextSetShouldSmoothFonts(mCg, aPermitSubpixelAA);
 }
 
 CGContextRef
 BorrowedCGContext::BorrowCGContextFromDrawTarget(DrawTarget *aDT)
 {
-  if (aDT->GetType() == BACKEND_COREGRAPHICS || aDT->GetType() == BACKEND_COREGRAPHICS_ACCELERATED) {
+  if (aDT->GetType() == BackendType::COREGRAPHICS || aDT->GetType() == BackendType::COREGRAPHICS_ACCELERATED) {
     DrawTargetCG* cgDT = static_cast<DrawTargetCG*>(aDT);
     cgDT->MarkChanged();
 
     // swap out the context
     CGContextRef cg = cgDT->mCg;
     cgDT->mCg = nullptr;
 
     // save the state to make it easier for callers to avoid mucking with things
--- a/gfx/2d/DrawTargetCG.h
+++ b/gfx/2d/DrawTargetCG.h
@@ -46,37 +46,37 @@ CGPointToPoint(CGPoint point)
   return Point(point.x, point.y);
 }
 
 static inline void
 SetStrokeOptions(CGContextRef cg, const StrokeOptions &aStrokeOptions)
 {
   switch (aStrokeOptions.mLineCap)
   {
-    case CAP_BUTT:
+    case CapStyle::BUTT:
       CGContextSetLineCap(cg, kCGLineCapButt);
       break;
-    case CAP_ROUND:
+    case CapStyle::ROUND:
       CGContextSetLineCap(cg, kCGLineCapRound);
       break;
-    case CAP_SQUARE:
+    case CapStyle::SQUARE:
       CGContextSetLineCap(cg, kCGLineCapSquare);
       break;
   }
 
   switch (aStrokeOptions.mLineJoin)
   {
-    case JOIN_BEVEL:
+    case JoinStyle::BEVEL:
       CGContextSetLineJoin(cg, kCGLineJoinBevel);
       break;
-    case JOIN_ROUND:
+    case JoinStyle::ROUND:
       CGContextSetLineJoin(cg, kCGLineJoinRound);
       break;
-    case JOIN_MITER:
-    case JOIN_MITER_OR_BEVEL:
+    case JoinStyle::MITER:
+    case JoinStyle::MITER_OR_BEVEL:
       CGContextSetLineJoin(cg, kCGLineJoinMiter);
       break;
   }
 
   CGContextSetLineWidth(cg, aStrokeOptions.mLineWidth);
   CGContextSetMiterLimit(cg, aStrokeOptions.mMiterLimit);
 
   // XXX: rename mDashLength to dashLength
@@ -142,17 +142,17 @@ public:
                     const DrawOptions &aOptions = DrawOptions());
   virtual void PushClip(const Path *);
   virtual void PushClipRect(const Rect &aRect);
   virtual void PopClip();
   virtual TemporaryRef<SourceSurface> CreateSourceSurfaceFromNativeSurface(const NativeSurface&) const { return nullptr;}
   virtual TemporaryRef<DrawTarget> CreateSimilarDrawTarget(const IntSize &, SurfaceFormat) const;
   virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule) const;
   virtual TemporaryRef<GradientStops> CreateGradientStops(GradientStop *, uint32_t,
-                                                          ExtendMode aExtendMode = EXTEND_CLAMP) const;
+                                                          ExtendMode aExtendMode = ExtendMode::CLAMP) const;
   virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType);
 
   virtual void *GetNativeSurface(NativeSurfaceType);
 
   virtual IntSize GetSize() { return mSize; }
 
   virtual void SetPermitSubpixelAA(bool aPermitSubpixelAA) MOZ_OVERRIDE;
 
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -164,25 +164,25 @@ SupportsSelfCopy(cairo_surface_t* surfac
   }
 }
 
 static bool
 PatternIsCompatible(const Pattern& aPattern)
 {
   switch (aPattern.GetType())
   {
-    case PATTERN_LINEAR_GRADIENT:
+    case PatternType::LINEAR_GRADIENT:
     {
       const LinearGradientPattern& pattern = static_cast<const LinearGradientPattern&>(aPattern);
-      return pattern.mStops->GetBackendType() == BACKEND_CAIRO;
+      return pattern.mStops->GetBackendType() == BackendType::CAIRO;
     }
-    case PATTERN_RADIAL_GRADIENT:
+    case PatternType::RADIAL_GRADIENT:
     {
       const RadialGradientPattern& pattern = static_cast<const RadialGradientPattern&>(aPattern);
-      return pattern.mStops->GetBackendType() == BACKEND_CAIRO;
+      return pattern.mStops->GetBackendType() == BackendType::CAIRO;
     }
     default:
       return true;
   }
 }
 
 static cairo_user_data_key_t surfaceDataKey;
 
@@ -197,23 +197,23 @@ ReleaseData(void* aData)
  * If possible, it will use the cairo_surface associated with aSurface,
  * otherwise, it will create a new cairo_surface.
  * In either case, the caller must call cairo_surface_destroy on the
  * result when it is done with it.
  */
 cairo_surface_t*
 GetCairoSurfaceForSourceSurface(SourceSurface *aSurface, bool aExistingOnly = false)
 {
-  if (aSurface->GetType() == SURFACE_CAIRO) {
+  if (aSurface->GetType() == SurfaceType::CAIRO) {
     cairo_surface_t* surf = static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface();
     cairo_surface_reference(surf);
     return surf;
   }
 
-  if (aSurface->GetType() == SURFACE_CAIRO_IMAGE) {
+  if (aSurface->GetType() == SurfaceType::CAIRO_IMAGE) {
     cairo_surface_t* surf =
       static_cast<const DataSourceSurfaceCairo*>(aSurface)->GetSurface();
     cairo_surface_reference(surf);
     return surf;
   }
 
   if (aExistingOnly) {
     return nullptr;
@@ -256,17 +256,17 @@ public:
     : mSurface(nullptr)
   {
     Init(aSurface);
   }
 
   AutoClearDeviceOffset(const Pattern& aPattern)
     : mSurface(nullptr)
   {
-    if (aPattern.GetType() == PATTERN_SURFACE) {
+    if (aPattern.GetType() == PatternType::SURFACE) {
       const SurfacePattern& pattern = static_cast<const SurfacePattern&>(aPattern);
       Init(pattern.mSurface);
     }
   }
 
   ~AutoClearDeviceOffset()
   {
     if (mSurface) {
@@ -306,70 +306,70 @@ private:
 static cairo_pattern_t*
 GfxPatternToCairoPattern(const Pattern& aPattern, Float aAlpha)
 {
   cairo_pattern_t* pat;
   const Matrix* matrix = nullptr;
 
   switch (aPattern.GetType())
   {
-    case PATTERN_COLOR:
+    case PatternType::COLOR:
     {
       Color color = static_cast<const ColorPattern&>(aPattern).mColor;
       pat = cairo_pattern_create_rgba(color.r, color.g, color.b, color.a * aAlpha);
       break;
     }
 
-    case PATTERN_SURFACE:
+    case PatternType::SURFACE:
     {
       const SurfacePattern& pattern = static_cast<const SurfacePattern&>(aPattern);
       cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(pattern.mSurface);
 
       pat = cairo_pattern_create_for_surface(surf);
 
       matrix = &pattern.mMatrix;
 
       cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(pattern.mFilter));
       cairo_pattern_set_extend(pat, GfxExtendToCairoExtend(pattern.mExtendMode));
 
       cairo_surface_destroy(surf);
 
       break;
     }
-    case PATTERN_LINEAR_GRADIENT:
+    case PatternType::LINEAR_GRADIENT:
     {
       const LinearGradientPattern& pattern = static_cast<const LinearGradientPattern&>(aPattern);
 
       pat = cairo_pattern_create_linear(pattern.mBegin.x, pattern.mBegin.y,
                                         pattern.mEnd.x, pattern.mEnd.y);
 
-      MOZ_ASSERT(pattern.mStops->GetBackendType() == BACKEND_CAIRO);
+      MOZ_ASSERT(pattern.mStops->GetBackendType() == BackendType::CAIRO);
       GradientStopsCairo* cairoStops = static_cast<GradientStopsCairo*>(pattern.mStops.get());
       cairo_pattern_set_extend(pat, GfxExtendToCairoExtend(cairoStops->GetExtendMode()));
 
       matrix = &pattern.mMatrix;
 
       const std::vector<GradientStop>& stops = cairoStops->GetStops();
       for (size_t i = 0; i < stops.size(); ++i) {
         const GradientStop& stop = stops[i];
         cairo_pattern_add_color_stop_rgba(pat, stop.offset, stop.color.r,
                                           stop.color.g, stop.color.b,
                                           stop.color.a);
       }
 
       break;
     }
-    case PATTERN_RADIAL_GRADIENT:
+    case PatternType::RADIAL_GRADIENT:
     {
       const RadialGradientPattern& pattern = static_cast<const RadialGradientPattern&>(aPattern);
 
       pat = cairo_pattern_create_radial(pattern.mCenter1.x, pattern.mCenter1.y, pattern.mRadius1,
                                         pattern.mCenter2.x, pattern.mCenter2.y, pattern.mRadius2);
 
-      MOZ_ASSERT(pattern.mStops->GetBackendType() == BACKEND_CAIRO);
+      MOZ_ASSERT(pattern.mStops->GetBackendType() == BackendType::CAIRO);
       GradientStopsCairo* cairoStops = static_cast<GradientStopsCairo*>(pattern.mStops.get());
       cairo_pattern_set_extend(pat, GfxExtendToCairoExtend(cairoStops->GetExtendMode()));
 
       matrix = &pattern.mMatrix;
 
       const std::vector<GradientStop>& stops = cairoStops->GetStops();
       for (size_t i = 0; i < stops.size(); ++i) {
         const GradientStop& stop = stops[i];
@@ -400,17 +400,17 @@ GfxPatternToCairoPattern(const Pattern& 
   return pat;
 }
 
 static bool
 NeedIntermediateSurface(const Pattern& aPattern, const DrawOptions& aOptions)
 {
   // We pre-multiply colours' alpha by the global alpha, so we don't need to
   // use an intermediate surface for them.
-  if (aPattern.GetType() == PATTERN_COLOR)
+  if (aPattern.GetType() == PatternType::COLOR)
     return false;
 
   if (aOptions.mAlpha == 1.0)
     return false;
 
   return true;
 }
 
@@ -570,17 +570,17 @@ DrawTargetCairo::DrawFilter(FilterNode *
 void
 DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface,
                                        const Point &aDest,
                                        const Color &aColor,
                                        const Point &aOffset,
                                        Float aSigma,
                                        CompositionOp aOperator)
 {
-  if (aSurface->GetType() != SURFACE_CAIRO) {
+  if (aSurface->GetType() != SurfaceType::CAIRO) {
     return;
   }
   
   AutoClearDeviceOffset clear(aSurface);
 
   Float width = Float(aSurface->GetSize().width);
   Float height = Float(aSurface->GetSize().height);
 
@@ -829,33 +829,33 @@ DrawTargetCairo::StrokeLine(const Point 
 void
 DrawTargetCairo::Stroke(const Path *aPath,
                         const Pattern &aPattern,
                         const StrokeOptions &aStrokeOptions /* = StrokeOptions() */,
                         const DrawOptions &aOptions /* = DrawOptions() */)
 {
   AutoPrepareForDrawing prep(this, mContext, aPath);
 
-  if (aPath->GetBackendType() != BACKEND_CAIRO)
+  if (aPath->GetBackendType() != BackendType::CAIRO)
     return;
 
   PathCairo* path = const_cast<PathCairo*>(static_cast<const PathCairo*>(aPath));
   path->SetPathOnContext(mContext);
 
   DrawPattern(aPattern, aStrokeOptions, aOptions, DRAW_STROKE);
 }
 
 void
 DrawTargetCairo::Fill(const Path *aPath,
                       const Pattern &aPattern,
                       const DrawOptions &aOptions /* = DrawOptions() */)
 {
   AutoPrepareForDrawing prep(this, mContext, aPath);
 
-  if (aPath->GetBackendType() != BACKEND_CAIRO)
+  if (aPath->GetBackendType() != BackendType::CAIRO)
     return;
 
   PathCairo* path = const_cast<PathCairo*>(static_cast<const PathCairo*>(aPath));
   path->SetPathOnContext(mContext);
 
   DrawPattern(aPattern, StrokeOptions(), aOptions, DRAW_FILL);
 }
 
@@ -963,17 +963,17 @@ DrawTargetCairo::MaskSurface(const Patte
   cairo_surface_destroy(surf);
   cairo_pattern_destroy(mask);
   cairo_pattern_destroy(pat);
 }
 
 void
 DrawTargetCairo::PushClip(const Path *aPath)
 {
-  if (aPath->GetBackendType() != BACKEND_CAIRO) {
+  if (aPath->GetBackendType() != BackendType::CAIRO) {
     return;
   }
 
   WillChange(aPath);
   cairo_save(mContext);
 
   PathCairo* path = const_cast<PathCairo*>(static_cast<const PathCairo*>(aPath));
   path->SetPathOnContext(mContext);
@@ -1005,27 +1005,27 @@ DrawTargetCairo::PopClip()
 
   cairo_set_matrix(mContext, &mat);
 
   MOZ_ASSERT(GetTransform() == Matrix(mat.xx, mat.yx, mat.xy, mat.yy, mat.x0, mat.y0),
              "Transforms are out of sync");
 }
 
 TemporaryRef<PathBuilder>
-DrawTargetCairo::CreatePathBuilder(FillRule aFillRule /* = FILL_WINDING */) const
+DrawTargetCairo::CreatePathBuilder(FillRule aFillRule /* = FillRule::FILL_WINDING */) const
 {
   RefPtr<PathBuilderCairo> builder = new PathBuilderCairo(aFillRule);
 
   return builder;
 }
 
 void
 DrawTargetCairo::ClearSurfaceForUnboundedSource(const CompositionOp &aOperator)
 {
-  if (aOperator != OP_SOURCE)
+  if (aOperator != CompositionOp::OP_SOURCE)
     return;
   cairo_set_operator(mContext, CAIRO_OPERATOR_CLEAR);
   // It doesn't really matter what the source is here, since Paint
   // isn't bounded by the source and the mask covers the entire clip
   // region.
   cairo_paint(mContext);
 }
 
@@ -1102,17 +1102,17 @@ TemporaryRef<SourceSurface>
 DrawTargetCairo::OptimizeSourceSurface(SourceSurface *aSurface) const
 {
   return aSurface;
 }
 
 TemporaryRef<SourceSurface>
 DrawTargetCairo::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
 {
-  if (aSurface.mType == NATIVE_SURFACE_CAIRO_SURFACE) {
+  if (aSurface.mType == NativeSurfaceType::CAIRO_SURFACE) {
     IntSize size;
     cairo_surface_t* surf = static_cast<cairo_surface_t*>(aSurface.mSurface);
     if (GetCairoSurfaceSize(surf, size)) {
       RefPtr<SourceSurfaceCairo> source =
         new SourceSurfaceCairo(surf, size, aSurface.mFormat);
       return source;
     }
   }
@@ -1153,18 +1153,18 @@ DrawTargetCairo::CreateSimilarDrawTarget
 bool
 DrawTargetCairo::InitAlreadyReferenced(cairo_surface_t* aSurface, const IntSize& aSize)
 {
   mContext = cairo_create(aSurface);
   mSurface = aSurface;
   mSize = aSize;
   mFormat = CairoContentToGfxFormat(cairo_surface_get_content(aSurface));
 
-  if (mFormat == FORMAT_B8G8R8A8 ||
-      mFormat == FORMAT_R8G8B8A8) {
+  if (mFormat == SurfaceFormat::B8G8R8A8 ||
+      mFormat == SurfaceFormat::R8G8B8A8) {
     SetPermitSubpixelAA(false);
   } else {
     SetPermitSubpixelAA(true);
   }
 
   return true;
 }
 
@@ -1235,20 +1235,20 @@ DrawTargetCairo::Init(unsigned char* aDa
                                         aSize.height,
                                         aStride);
   return InitAlreadyReferenced(surf, aSize);
 }
 
 void *
 DrawTargetCairo::GetNativeSurface(NativeSurfaceType aType)
 {
-  if (aType == NATIVE_SURFACE_CAIRO_SURFACE) {
+  if (aType == NativeSurfaceType::CAIRO_SURFACE) {
     return cairo_get_target(mContext);
   }
-  if (aType == NATIVE_SURFACE_CAIRO_CONTEXT) {
+  if (aType == NativeSurfaceType::CAIRO_CONTEXT) {
     return mContext;
   }
 
   return nullptr;
 }
 
 void
 DrawTargetCairo::MarkSnapshotIndependent()
@@ -1285,17 +1285,17 @@ DrawTargetCairo::GetUserSpaceClip()
   double clipX1, clipY1, clipX2, clipY2;
   cairo_clip_extents(mContext, &clipX1, &clipY1, &clipX2, &clipY2);
   return Rect(clipX1, clipY1, clipX2 - clipX1, clipY2 - clipY1); // Narrowing of doubles to floats
 }
 
 cairo_t*
 BorrowedCairoContext::BorrowCairoContextFromDrawTarget(DrawTarget* aDT)
 {
-  if (aDT->GetType() != BACKEND_CAIRO || aDT->IsDualDrawTarget()) {
+  if (aDT->GetType() != BackendType::CAIRO || aDT->IsDualDrawTarget()) {
     return nullptr;
   }
   DrawTargetCairo* cairoDT = static_cast<DrawTargetCairo*>(aDT);
 
   cairoDT->WillChange();
 
   // save the state to make it easier for callers to avoid mucking with things
   cairo_save(cairoDT->mContext);
@@ -1306,17 +1306,17 @@ BorrowedCairoContext::BorrowCairoContext
 
   return cairo;
 }
 
 void
 BorrowedCairoContext::ReturnCairoContextToDrawTarget(DrawTarget* aDT,
                                                      cairo_t* aCairo)
 {
-  if (aDT->GetType() != BACKEND_CAIRO || aDT->IsDualDrawTarget()) {
+  if (aDT->GetType() != BackendType::CAIRO || aDT->IsDualDrawTarget()) {
     return;
   }
   DrawTargetCairo* cairoDT = static_cast<DrawTargetCairo*>(aDT);
 
   cairo_restore(aCairo);
   cairoDT->mContext = aCairo;
 }
 
--- a/gfx/2d/DrawTargetCairo.h
+++ b/gfx/2d/DrawTargetCairo.h
@@ -36,32 +36,32 @@ class GradientStopsCairo : public Gradie
       return mStops;
     }
 
     ExtendMode GetExtendMode() const
     {
       return mExtendMode;
     }
 
-    virtual BackendType GetBackendType() const { return BACKEND_CAIRO; }
+    virtual BackendType GetBackendType() const { return BackendType::CAIRO; }
 
   private:
     std::vector<GradientStop> mStops;
     ExtendMode mExtendMode;
 };
 
 class DrawTargetCairo : public DrawTarget
 {
 public:
   friend class BorrowedCairoContext;
 
   DrawTargetCairo();
   virtual ~DrawTargetCairo();
 
-  virtual BackendType GetType() const { return BACKEND_CAIRO; }
+  virtual BackendType GetType() const { return BackendType::CAIRO; }
   virtual TemporaryRef<SourceSurface> Snapshot();
   virtual IntSize GetSize();
 
   virtual void SetPermitSubpixelAA(bool aPermitSubpixelAA);
 
   virtual bool LockBits(uint8_t** aData, IntSize* aSize,
                         int32_t* aStride, SurfaceFormat* aFormat);
   virtual void ReleaseBits(uint8_t* aData);
@@ -125,17 +125,17 @@ public:
                            SourceSurface *aMask,
                            Point aOffset,
                            const DrawOptions &aOptions = DrawOptions());
 
   virtual void PushClip(const Path *aPath);
   virtual void PushClipRect(const Rect &aRect);
   virtual void PopClip();
 
-  virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FILL_WINDING) const;
+  virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const;
 
   virtual TemporaryRef<SourceSurface> CreateSourceSurfaceFromData(unsigned char *aData,
                                                             const IntSize &aSize,
                                                             int32_t aStride,
                                                             SurfaceFormat aFormat) const;
   virtual TemporaryRef<SourceSurface> OptimizeSourceSurface(SourceSurface *aSurface) const;
   virtual TemporaryRef<SourceSurface>
     CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const;
@@ -143,17 +143,17 @@ public:
     CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const;
   virtual TemporaryRef<DrawTarget>
     CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat,
                            float aSigma) const;
 
   virtual TemporaryRef<GradientStops>
     CreateGradientStops(GradientStop *aStops,
                         uint32_t aNumStops,
-                        ExtendMode aExtendMode = EXTEND_CLAMP) const;
+                        ExtendMode aExtendMode = ExtendMode::CLAMP) const;
 
   virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType);
 
   virtual void *GetNativeSurface(NativeSurfaceType aType);
 
   bool Init(cairo_surface_t* aSurface, const IntSize& aSize);
   bool Init(const IntSize& aSize, SurfaceFormat aFormat);
   bool Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);
--- a/gfx/2d/DrawTargetD2D.cpp
+++ b/gfx/2d/DrawTargetD2D.cpp
@@ -268,23 +268,23 @@ DrawTargetD2D::AddDependencyOnSource(Sou
 TemporaryRef<ID2D1Bitmap>
 DrawTargetD2D::GetBitmapForSurface(SourceSurface *aSurface,
                                    Rect &aSource)
 {
   RefPtr<ID2D1Bitmap> bitmap;
 
   switch (aSurface->GetType()) {
 
-  case SURFACE_D2D1_BITMAP:
+  case SurfaceType::D2D1_BITMAP:
     {
       SourceSurfaceD2D *srcSurf = static_cast<SourceSurfaceD2D*>(aSurface);
       bitmap = srcSurf->GetBitmap();
     }
     break;
-  case SURFACE_D2D1_DRAWTARGET:
+  case SurfaceType::D2D1_DRAWTARGET:
     {
       SourceSurfaceD2DTarget *srcSurf = static_cast<SourceSurfaceD2DTarget*>(aSurface);
       bitmap = srcSurf->GetBitmap(mRT);
       AddDependencyOnSource(srcSurf);
     }
     break;
   default:
     {
@@ -422,17 +422,17 @@ void
 DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface,
                                      const Point &aDest,
                                      const Color &aColor,
                                      const Point &aOffset,
                                      Float aSigma,
                                      CompositionOp aOperator)
 {
   RefPtr<ID3D10ShaderResourceView> srView = nullptr;
-  if (aSurface->GetType() != SURFACE_D2D1_DRAWTARGET) {
+  if (aSurface->GetType() != SurfaceType::D2D1_DRAWTARGET) {
     return;
   }
 
   SetScissorToRect(nullptr);
 
   // XXX - This function is way too long, it should be split up soon to make
   // it more graspable!
 
@@ -576,17 +576,17 @@ DrawTargetD2D::DrawSurfaceWithShadow(Sou
     viewport.TopLeftX = 0;
     viewport.TopLeftY = 0;
 
     mDevice->RSSetViewports(1, &viewport);
     mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(srView);
     mPrivateData->mEffect->GetTechniqueByName("SampleTexture")->
       GetPassByIndex(0)->Apply(0);
 
-    mDevice->OMSetBlendState(GetBlendStateForOperator(OP_OVER), nullptr, 0xffffffff);
+    mDevice->OMSetBlendState(GetBlendStateForOperator(CompositionOp::OP_OVER), nullptr, 0xffffffff);
 
     mDevice->Draw(4, 0);
     
     srcSurfSize = dsSize;
 
     srView = dsSRView;
   } else {
     // In this case generate a kernel to draw the blur directly to the temp
@@ -816,17 +816,17 @@ DrawTargetD2D::CopySurface(SourceSurface
   mRT->Clear(D2D1::ColorF(0, 0.0f));
   mRT->PopAxisAlignedClip();
 
   RefPtr<ID2D1Bitmap> bitmap = GetBitmapForSurface(aSurface, srcRect);
   if (!bitmap) {
     return;
   }
 
-  if (aSurface->GetFormat() == FORMAT_A8) {
+  if (aSurface->GetFormat() == SurfaceFormat::A8) {
     RefPtr<ID2D1SolidColorBrush> brush;
     mRT->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White),
                                D2D1::BrushProperties(), byRef(brush));
     mRT->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
     mRT->FillOpacityMask(bitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS);
   } else {
     mRT->DrawBitmap(bitmap, D2DRect(dstRect), 1.0f,
             D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
@@ -902,17 +902,17 @@ DrawTargetD2D::StrokeLine(const Point &a
 }
 
 void
 DrawTargetD2D::Stroke(const Path *aPath,
                       const Pattern &aPattern,
                       const StrokeOptions &aStrokeOptions,
                       const DrawOptions &aOptions)
 {
-  if (aPath->GetBackendType() != BACKEND_DIRECT2D) {
+  if (aPath->GetBackendType() != BackendType::DIRECT2D) {
     gfxDebug() << *this << ": Ignoring drawing call for incompatible path.";
     return;
   }
 
   const PathD2D *d2dPath = static_cast<const PathD2D*>(aPath);
 
   ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
 
@@ -931,17 +931,17 @@ DrawTargetD2D::Stroke(const Path *aPath,
   FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, Rect(0, 0, Float(mSize.width), Float(mSize.height)));
 }
 
 void
 DrawTargetD2D::Fill(const Path *aPath,
                     const Pattern &aPattern,
                     const DrawOptions &aOptions)
 {
-  if (aPath->GetBackendType() != BACKEND_DIRECT2D) {
+  if (aPath->GetBackendType() != BackendType::DIRECT2D) {
     gfxDebug() << *this << ": Ignoring drawing call for incompatible path.";
     return;
   }
 
   const PathD2D *d2dPath = static_cast<const PathD2D*>(aPath);
 
   ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
 
@@ -951,87 +951,87 @@ DrawTargetD2D::Fill(const Path *aPath,
 
   RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
 
   if (brush) {
     rt->FillGeometry(d2dPath->mGeometry, brush);
   }
 
   Rect bounds;
-  if (aOptions.mCompositionOp != OP_OVER) {
+  if (aOptions.mCompositionOp != CompositionOp::OP_OVER) {
     D2D1_RECT_F d2dbounds;
     d2dPath->mGeometry->GetBounds(D2D1::IdentityMatrix(), &d2dbounds);
     bounds = ToRect(d2dbounds);
   }
   FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, bounds);
 }
 
 void
 DrawTargetD2D::FillGlyphs(ScaledFont *aFont,
                           const GlyphBuffer &aBuffer,
                           const Pattern &aPattern,
                           const DrawOptions &aOptions,
                           const GlyphRenderingOptions* aRenderOptions)
 {
-  if (aFont->GetType() != FONT_DWRITE) {
+  if (aFont->GetType() != FontType::DWRITE) {
     gfxDebug() << *this << ": Ignoring drawing call for incompatible font.";
     return;
   }
 
   ScaledFontDWrite *font = static_cast<ScaledFontDWrite*>(aFont);
 
   IDWriteRenderingParams *params = nullptr;
   if (aRenderOptions) {
-    if (aRenderOptions->GetType() != FONT_DWRITE) {
+    if (aRenderOptions->GetType() != FontType::DWRITE) {
       gfxDebug() << *this << ": Ignoring incompatible GlyphRenderingOptions.";
       // This should never happen.
       MOZ_ASSERT(false);
     } else {
       params = static_cast<const GlyphRenderingOptionsDWrite*>(aRenderOptions)->mParams;
     }
   }
 
   AntialiasMode aaMode = font->GetDefaultAAMode();
 
-  if (aOptions.mAntialiasMode != AA_DEFAULT) {
+  if (aOptions.mAntialiasMode != AntialiasMode::DEFAULT) {
     aaMode = aOptions.mAntialiasMode;
   }
 
-  if (mFormat == FORMAT_B8G8R8A8 && mPermitSubpixelAA &&
-      aOptions.mCompositionOp == OP_OVER && aPattern.GetType() == PATTERN_COLOR &&
-      aaMode == AA_SUBPIXEL) {
+  if (mFormat == SurfaceFormat::B8G8R8A8 && mPermitSubpixelAA &&
+      aOptions.mCompositionOp == CompositionOp::OP_OVER && aPattern.GetType() == PatternType::COLOR &&
+      aaMode == AntialiasMode::SUBPIXEL) {
     if (FillGlyphsManual(font, aBuffer,
                          static_cast<const ColorPattern*>(&aPattern)->mColor,
                          params, aOptions)) {
       return;
     }
   }
 
   ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
 
   PrepareForDrawing(rt);
 
   D2D1_TEXT_ANTIALIAS_MODE d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
 
   switch (aaMode) {
-  case AA_NONE:
+  case AntialiasMode::NONE:
     d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
     break;
-  case AA_GRAY:
+  case AntialiasMode::GRAY:
     d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
     break;
-  case AA_SUBPIXEL:
+  case AntialiasMode::SUBPIXEL:
     d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
     break;
   default:
     d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
   }
 
   if (d2dAAMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE &&
-      mFormat != FORMAT_B8G8R8X8) {
+      mFormat != SurfaceFormat::B8G8R8X8) {
     d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
   }
 
   rt->SetTextAntialiasMode(d2dAAMode);
 
   if (rt != mRT || params != mTextRenderingParams) {
     rt->SetTextRenderingParams(params);
     if (rt == mRT) {
@@ -1081,17 +1081,17 @@ DrawTargetD2D::Mask(const Pattern &aSour
   PopCachedLayer(rt);
 
   FinalizeRTForOperation(aOptions.mCompositionOp, aSource, Rect(0, 0, (Float)mSize.width, (Float)mSize.height));
 }
 
 void
 DrawTargetD2D::PushClip(const Path *aPath)
 {
-  if (aPath->GetBackendType() != BACKEND_DIRECT2D) {
+  if (aPath->GetBackendType() != BackendType::DIRECT2D) {
     gfxDebug() << *this << ": Ignoring clipping call for incompatible path.";
     return;
   }
 
   mCurrentClipMaskTexture = nullptr;
   mCurrentClippedGeometry = nullptr;
 
   RefPtr<PathD2D> pathD2D = static_cast<PathD2D*>(const_cast<Path*>(aPath));
@@ -1189,17 +1189,17 @@ DrawTargetD2D::OptimizeSourceSurface(Sou
 {
   // Unsupported!
   return nullptr;
 }
 
 TemporaryRef<SourceSurface>
 DrawTargetD2D::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
 {
-  if (aSurface.mType != NATIVE_SURFACE_D3D10_TEXTURE) {
+  if (aSurface.mType != NativeSurfaceType::D3D10_TEXTURE) {
     gfxDebug() << *this << ": Failure to create source surface from non-D3D10 texture native surface.";
     return nullptr;
   }
   RefPtr<SourceSurfaceD2D> newSurf = new SourceSurfaceD2D();
 
   if (!newSurf->InitFromTexture(static_cast<ID3D10Texture2D*>(aSurface.mSurface),
                                 aSurface.mFormat,
                                 mRT))
@@ -1238,17 +1238,17 @@ DrawTargetD2D::CreatePathBuilder(FillRul
 
   RefPtr<ID2D1GeometrySink> sink;
   hr = path->Open(byRef(sink));
   if (FAILED(hr)) {
     gfxWarning() << "Failed to access Direct2D Path Geometry. Code: " << hr;
     return nullptr;
   }
 
-  if (aFillRule == FILL_WINDING) {
+  if (aFillRule == FillRule::FILL_WINDING) {
     sink->SetFillMode(D2D1_FILL_MODE_WINDING);
   }
 
   return new PathBuilderD2D(sink, path, aFillRule);
 }
 
 TemporaryRef<GradientStops>
 DrawTargetD2D::CreateGradientStops(GradientStop *rawStops, uint32_t aNumStops, ExtendMode aExtendMode) const
@@ -1288,17 +1288,17 @@ DrawTargetD2D::CreateFilter(FilterType a
   }
 #endif
   return FilterNodeSoftware::Create(aType);
 }
 
 void*
 DrawTargetD2D::GetNativeSurface(NativeSurfaceType aType)
 {
-  if (aType != NATIVE_SURFACE_D3D10_TEXTURE) {
+  if (aType != NativeSurfaceType::D3D10_TEXTURE) {
     return nullptr;
   }
 
   return mTexture;
 }
 
 /*
  * Public functions
@@ -1482,17 +1482,17 @@ DrawTargetD2D::InitD2DRenderTarget()
   mRT = CreateRTForTexture(mTexture, mFormat);
 
   if (!mRT) {
     return false;
   }
 
   mRT->BeginDraw();
 
-  if (mFormat == FORMAT_B8G8R8X8) {
+  if (mFormat == SurfaceFormat::B8G8R8X8) {
     mRT->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
   }
 
   mVRAMUsageDT += GetByteSize();
 
   return InitD3D10Data();
 }
 
@@ -1542,109 +1542,110 @@ DrawTargetD2D::MarkChanged()
     // The Flush() should have broken all dependencies on this target.
     MOZ_ASSERT(!mDependentTargets.size());
   }
 }
 
 ID3D10BlendState*
 DrawTargetD2D::GetBlendStateForOperator(CompositionOp aOperator)
 {
-  if (mPrivateData->mBlendStates[aOperator]) {
-    return mPrivateData->mBlendStates[aOperator];
+  size_t operatorIndex = static_cast<size_t>(aOperator);
+  if (mPrivateData->mBlendStates[operatorIndex]) {
+    return mPrivateData->mBlendStates[operatorIndex];
   }
 
   D3D10_BLEND_DESC desc;
 
   memset(&desc, 0, sizeof(D3D10_BLEND_DESC));
 
   desc.AlphaToCoverageEnable = FALSE;
   desc.BlendEnable[0] = TRUE;
   desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
   desc.BlendOp = desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
 
   switch (aOperator) {
-  case OP_ADD:
+  case CompositionOp::OP_ADD:
     desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ONE;
     desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ONE;
     break;
-  case OP_IN:
+  case CompositionOp::OP_IN:
     desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_DEST_ALPHA;
     desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ZERO;
     break;
-  case OP_OUT:
+  case CompositionOp::OP_OUT:
     desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA;
     desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ZERO;
     break;
-  case OP_ATOP:
+  case CompositionOp::OP_ATOP:
     desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_DEST_ALPHA;
     desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
     break;
-  case OP_DEST_IN:
+  case CompositionOp::OP_DEST_IN:
     desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
     desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_SRC_ALPHA;
     break;
-  case OP_DEST_OUT:
+  case CompositionOp::OP_DEST_OUT:
     desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
     desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
     break;
-  case OP_DEST_ATOP:
+  case CompositionOp::OP_DEST_ATOP:
     desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA;
     desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_SRC_ALPHA;
     break;
-  case OP_DEST_OVER:
+  case CompositionOp::OP_DEST_OVER:
     desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA;
     desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ONE;
     break;
-  case OP_XOR:
+  case CompositionOp::OP_XOR:
     desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA;
     desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
     break;
-  case OP_SOURCE:
+  case CompositionOp::OP_SOURCE:
     desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ONE;
     desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ZERO;
     break;
   default:
     desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ONE;
     desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
   }
   
-  mDevice->CreateBlendState(&desc, byRef(mPrivateData->mBlendStates[aOperator]));
-
-  return mPrivateData->mBlendStates[aOperator];
+  mDevice->CreateBlendState(&desc, byRef(mPrivateData->mBlendStates[operatorIndex]));
+
+  return mPrivateData->mBlendStates[operatorIndex];
 }
 
 /* This function prepares the temporary RT for drawing and returns it when a
  * drawing operation other than OVER is required.
  */
 ID2D1RenderTarget*
 DrawTargetD2D::GetRTForOperation(CompositionOp aOperator, const Pattern &aPattern)
 {
-  if (aOperator == OP_OVER && IsPatternSupportedByD2D(aPattern)) {
+  if (aOperator == CompositionOp::OP_OVER && IsPatternSupportedByD2D(aPattern)) {
     return mRT;
   }
 
   PopAllClips();
 
-  if (aOperator > OP_XOR) {
+  if (aOperator > CompositionOp::OP_XOR) {
     mRT->Flush();
   }
 
   if (mTempRT) {
     mTempRT->Clear(D2D1::ColorF(0, 0));
     return mTempRT;
   }
 
   EnsureViews();
 
   if (!mRTView || !mSRView) {
-    gfxDebug() << *this << ": Failed to get required views. Defaulting to OP_OVER.";
+    gfxDebug() << *this << ": Failed to get required views. Defaulting to CompositionOp::OP_OVER.";
     return mRT;
   }
 
-  mTempRT = CreateRTForTexture(mTempTexture, FORMAT_B8G8R8A8);
+  mTempRT = CreateRTForTexture(mTempTexture, SurfaceFormat::B8G8R8A8);
 
   if (!mTempRT) {
     return mRT;
   }
 
   mVRAMUsageDT += GetByteSize();
 
   mTempRT->BeginDraw();
@@ -1659,17 +1660,17 @@ DrawTargetD2D::GetRTForOperation(Composi
  * contents) to the rendertarget using the requested composition operation.
  * In order to respect clip for operations which are unbound by their mask,
  * the old content of the surface outside the clipped area may be blended back
  * to the surface.
  */
 void
 DrawTargetD2D::FinalizeRTForOperation(CompositionOp aOperator, const Pattern &aPattern, const Rect &aBounds)
 {
-  if (aOperator == OP_OVER && IsPatternSupportedByD2D(aPattern)) {
+  if (aOperator == CompositionOp::OP_OVER && IsPatternSupportedByD2D(aPattern)) {
     return;
   }
 
   if (!mTempRT) {
     return;
   }
 
   PopClipsFromRT(mTempRT);
@@ -1713,17 +1714,17 @@ DrawTargetD2D::FinalizeRTForOperation(Co
     SetFloatVector(ShaderConstantRectD3D10(-1.0f, 1.0f, 2.0f, -2.0f));
 
   if (IsPatternSupportedByD2D(aPattern)) {
     mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()->
       SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
     mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(mSRView);
 
     // Handle the case where we blend with the backdrop
-    if (aOperator > OP_XOR) {
+    if (aOperator > CompositionOp::OP_XOR) {
       IntSize size = mSize;
       SurfaceFormat format = mFormat;
 
       CD3D10_TEXTURE2D_DESC desc(DXGIFormat(format), size.width, size.height, 1, 1);
       desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
 
       HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, byRef(tmpTexture));
       if (FAILED(hr)) {
@@ -1741,35 +1742,35 @@ DrawTargetD2D::FinalizeRTForOperation(Co
 
       hr = mDevice->CreateShaderResourceView(tmpTexture, nullptr, byRef(mBckSRView));
 
       if (FAILED(hr)) {
         gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hr;
         return;
       }
 
-      unsigned int compop = (unsigned int)aOperator - (unsigned int)OP_XOR;
+      unsigned int compop = (unsigned int)aOperator - (unsigned int)CompositionOp::OP_XOR;
       mPrivateData->mEffect->GetVariableByName("bcktex")->AsShaderResource()->SetResource(mBckSRView);
       mPrivateData->mEffect->GetVariableByName("blendop")->AsScalar()->SetInt(compop);
 
-      if (aOperator > OP_EXCLUSION)
+      if (aOperator > CompositionOp::OP_EXCLUSION)
         mPrivateData->mEffect->GetTechniqueByName("SampleTextureForNonSeparableBlending")->
           GetPassByIndex(0)->Apply(0);
-      else if (aOperator > OP_COLOR_DODGE)
+      else if (aOperator > CompositionOp::OP_COLOR_DODGE)
         mPrivateData->mEffect->GetTechniqueByName("SampleTextureForSeparableBlending_2")->
           GetPassByIndex(0)->Apply(0);
       else
         mPrivateData->mEffect->GetTechniqueByName("SampleTextureForSeparableBlending_1")->
           GetPassByIndex(0)->Apply(0);
     }
     else {
       mPrivateData->mEffect->GetTechniqueByName("SampleTexture")->GetPassByIndex(0)->Apply(0);
     }
 
-  } else if (aPattern.GetType() == PATTERN_RADIAL_GRADIENT) {
+  } else if (aPattern.GetType() == PatternType::RADIAL_GRADIENT) {
     const RadialGradientPattern *pat = static_cast<const RadialGradientPattern*>(&aPattern);
 
     if (pat->mCenter1 == pat->mCenter2 && pat->mRadius1 == pat->mRadius2) {
       // Draw nothing!
       return;
     }
 
     mPrivateData->mEffect->GetVariableByName("mask")->AsShaderResource()->SetResource(mSRView);
@@ -1927,17 +1928,17 @@ DrawTargetD2D::CreateRTForTexture(ID3D10
     return nullptr;
   }
 
   D3D10_TEXTURE2D_DESC desc;
   aTexture->GetDesc(&desc);
 
   D2D1_ALPHA_MODE alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
 
-  if (aFormat == FORMAT_B8G8R8X8 && aTexture == mTexture) {
+  if (aFormat == SurfaceFormat::B8G8R8X8 && aTexture == mTexture) {
     alphaMode = D2D1_ALPHA_MODE_IGNORE;
   }
 
   D2D1_RENDER_TARGET_PROPERTIES props =
     D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(desc.Format, alphaMode));
   hr = factory()->CreateDxgiSurfaceRenderTarget(surface, props, byRef(rt));
 
   if (FAILED(hr)) {
@@ -2038,17 +2039,17 @@ DrawTargetD2D::EnsureClipMaskTexture(Int
 
   HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, byRef(mCurrentClipMaskTexture));
 
   if (FAILED(hr)) {
     gfxWarning() << "Failed to create texture for ClipMask!";
     return;
   }
 
-  RefPtr<ID2D1RenderTarget> rt = CreateRTForTexture(mCurrentClipMaskTexture, FORMAT_A8);
+  RefPtr<ID2D1RenderTarget> rt = CreateRTForTexture(mCurrentClipMaskTexture, SurfaceFormat::A8);
 
   if (!rt) {
     gfxWarning() << "Failed to create RT for ClipMask!";
     return;
   }
   
   RefPtr<ID2D1SolidColorBrush> brush;
   rt->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), byRef(brush));
@@ -2243,25 +2244,25 @@ TemporaryRef<ID2D1Brush>
 DrawTargetD2D::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
 {
   if (!IsPatternSupportedByD2D(aPattern)) {
     RefPtr<ID2D1SolidColorBrush> colBrush;
     mRT->CreateSolidColorBrush(D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f), byRef(colBrush));
     return colBrush;
   }
 
-  if (aPattern.GetType() == PATTERN_COLOR) {
+  if (aPattern.GetType() == PatternType::COLOR) {
     RefPtr<ID2D1SolidColorBrush> colBrush;
     Color color = static_cast<const ColorPattern*>(&aPattern)->mColor;
     mRT->CreateSolidColorBrush(D2D1::ColorF(color.r, color.g,
                                             color.b, color.a),
                                D2D1::BrushProperties(aAlpha),
                                byRef(colBrush));
     return colBrush;
-  } else if (aPattern.GetType() == PATTERN_LINEAR_GRADIENT) {
+  } else if (aPattern.GetType() == PatternType::LINEAR_GRADIENT) {
     RefPtr<ID2D1LinearGradientBrush> gradBrush;
     const LinearGradientPattern *pat =
       static_cast<const LinearGradientPattern*>(&aPattern);
 
     GradientStopsD2D *stops = static_cast<GradientStopsD2D*>(pat->mStops.get());
 
     if (!stops) {
       gfxDebug() << "No stops specified for gradient pattern.";
@@ -2280,17 +2281,17 @@ DrawTargetD2D::CreateBrushForPattern(con
     }
 
     mRT->CreateLinearGradientBrush(D2D1::LinearGradientBrushProperties(D2DPoint(pat->mBegin),
                                                                        D2DPoint(pat->mEnd)),
                                    D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)),
                                    stops->mStopCollection,
                                    byRef(gradBrush));
     return gradBrush;
-  } else if (aPattern.GetType() == PATTERN_RADIAL_GRADIENT) {
+  } else if (aPattern.GetType() == PatternType::RADIAL_GRADIENT) {
     RefPtr<ID2D1RadialGradientBrush> gradBrush;
     const RadialGradientPattern *pat =
       static_cast<const RadialGradientPattern*>(&aPattern);
 
     GradientStopsD2D *stops = static_cast<GradientStopsD2D*>(pat->mStops.get());
 
     if (!stops) {
       gfxDebug() << "No stops specified for gradient pattern.";
@@ -2302,43 +2303,43 @@ DrawTargetD2D::CreateBrushForPattern(con
       D2D1::RadialGradientBrushProperties(D2DPoint(pat->mCenter2),
                                           D2DPoint(pat->mCenter1 - pat->mCenter2),
                                           pat->mRadius2, pat->mRadius2),
       D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)),
       stops->mStopCollection,
       byRef(gradBrush));
 
     return gradBrush;
-  } else if (aPattern.GetType() == PATTERN_SURFACE) {
+  } else if (aPattern.GetType() == PatternType::SURFACE) {
     RefPtr<ID2D1BitmapBrush> bmBrush;
     const SurfacePattern *pat =
       static_cast<const SurfacePattern*>(&aPattern);
 
     if (!pat->mSurface) {
       gfxDebug() << "No source surface specified for surface pattern";
       return nullptr;
     }
 
     RefPtr<ID2D1Bitmap> bitmap;
 
     Matrix mat = pat->mMatrix;
     
     switch (pat->mSurface->GetType()) {
-    case SURFACE_D2D1_BITMAP:
+    case SurfaceType::D2D1_BITMAP:
       {
         SourceSurfaceD2D *surf = static_cast<SourceSurfaceD2D*>(pat->mSurface.get());
 
         bitmap = surf->mBitmap;
 
         if (!bitmap) {
           return nullptr;
         }
       }
       break;
-    case SURFACE_D2D1_DRAWTARGET:
+    case SurfaceType::D2D1_DRAWTARGET:
       {
         SourceSurfaceD2DTarget *surf =
           static_cast<SourceSurfaceD2DTarget*>(pat->mSurface.get());
         bitmap = surf->GetBitmap(mRT);
         AddDependencyOnSource(surf);
       }
       break;
     default:
--- a/gfx/2d/DrawTargetD2D.h
+++ b/gfx/2d/DrawTargetD2D.h
@@ -32,26 +32,26 @@ class ScaledFontDWrite;
 
 const int32_t kLayerCacheSize = 5;
 
 struct PrivateD3D10DataD2D
 {
   RefPtr<ID3D10Effect> mEffect;
   RefPtr<ID3D10InputLayout> mInputLayout;
   RefPtr<ID3D10Buffer> mVB;
-  RefPtr<ID3D10BlendState> mBlendStates[OP_COUNT];
+  RefPtr<ID3D10BlendState> mBlendStates[CompositionOp::OP_COUNT];
 };
 
 class DrawTargetD2D : public DrawTarget
 {
 public:
   DrawTargetD2D();
   virtual ~DrawTargetD2D();
 
-  virtual BackendType GetType() const { return BACKEND_DIRECT2D; }
+  virtual BackendType GetType() const { return BackendType::DIRECT2D; }
   virtual TemporaryRef<SourceSurface> Snapshot();
   virtual IntSize GetSize() { return mSize; }
 
   virtual void Flush();
   virtual void DrawSurface(SourceSurface *aSurface,
                            const Rect &aDest,
                            const Rect &aSource,
                            const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(),
@@ -115,22 +115,22 @@ public:
   virtual TemporaryRef<SourceSurface> OptimizeSourceSurface(SourceSurface *aSurface) const;
 
   virtual TemporaryRef<SourceSurface>
     CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const;
   
   virtual TemporaryRef<DrawTarget>
     CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const;
 
-  virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FILL_WINDING) const;
+  virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const;
 
   virtual TemporaryRef<GradientStops>
     CreateGradientStops(GradientStop *aStops,
                         uint32_t aNumStops,
-                        ExtendMode aExtendMode = EXTEND_CLAMP) const;
+                        ExtendMode aExtendMode = ExtendMode::CLAMP) const;
 
   virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType);
 
   virtual void *GetNativeSurface(NativeSurfaceType aType);
 
   bool Init(const IntSize &aSize, SurfaceFormat aFormat);
   bool Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
   bool InitD3D10Data();
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -64,28 +64,28 @@ DrawTargetD2D1::Flush()
 
 void
 DrawTargetD2D1::DrawSurface(SourceSurface *aSurface,
                             const Rect &aDest,
                             const Rect &aSource,
                             const DrawSurfaceOptions &aSurfOptions,
                             const DrawOptions &aOptions)
 {
-  RefPtr<ID2D1Image> image = GetImageForSurface(aSurface, EXTEND_CLAMP);
+  RefPtr<ID2D1Image> image = GetImageForSurface(aSurface, ExtendMode::CLAMP);
 
   if (!image) {
     gfxWarning() << *this << ": Unable to get D2D image for surface.";
     return;
   }
 
   PrepareForDrawing(aOptions.mCompositionOp, ColorPattern(Color()));
 
   D2D1_RECT_F samplingBounds;
 
-  if (aSurfOptions.mSamplingBounds == SAMPLING_BOUNDED) {
+  if (aSurfOptions.mSamplingBounds == SamplingBounds::BOUNDED) {
     samplingBounds = D2DRect(aSource);
   } else {
     samplingBounds = D2D1::RectF(0, 0, Float(aSurface->GetSize().width), Float(aSurface->GetSize().height));
   }
 
   Float xScale = aDest.width / aSource.width;
   Float yScale = aDest.height / aSource.height;
 
@@ -129,17 +129,17 @@ DrawTargetD2D1::DrawSurfaceWithShadow(So
                                       Float aSigma,
                                       CompositionOp aOperator)
 {
   MarkChanged();
   mDC->SetTransform(D2D1::IdentityMatrix());
   mTransformDirty = true;
 
   Matrix mat;
-  RefPtr<ID2D1Image> image = GetImageForSurface(aSurface, mat, EXTEND_CLAMP);
+  RefPtr<ID2D1Image> image = GetImageForSurface(aSurface, mat, ExtendMode::CLAMP);
 
   if (!mat.IsIdentity()) {
     gfxDebug() << *this << ": At this point complex partial uploads are not supported for Shadow surfaces.";
     return;
   }
 
   // Step 1, create the shadow effect.
   RefPtr<ID2D1Effect> shadowEffect;
@@ -180,17 +180,17 @@ DrawTargetD2D1::ClearRect(const Rect &aR
 void
 DrawTargetD2D1::MaskSurface(const Pattern &aSource,
                             SourceSurface *aMask,
                             Point aOffset,
                             const DrawOptions &aOptions)
 {
   RefPtr<ID2D1Bitmap> bitmap;
 
-  RefPtr<ID2D1Image> image = GetImageForSurface(aMask, EXTEND_CLAMP);
+  RefPtr<ID2D1Image> image = GetImageForSurface(aMask, ExtendMode::CLAMP);
 
   PrepareForDrawing(aOptions.mCompositionOp, aSource);
 
   // FillOpacityMask only works if the antialias mode is MODE_ALIASED
   mDC->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
 
   IntSize size = aMask->GetSize();
   Rect maskRect = Rect(0.f, 0.f, Float(size.width), Float(size.height));
@@ -215,17 +215,17 @@ DrawTargetD2D1::CopySurface(SourceSurfac
                             const IntPoint &aDestination)
 {
   MarkChanged();
 
   mDC->SetTransform(D2D1::IdentityMatrix());
   mTransformDirty = true;
 
   Matrix mat;
-  RefPtr<ID2D1Image> image = GetImageForSurface(aSurface, mat, EXTEND_CLAMP);
+  RefPtr<ID2D1Image> image = GetImageForSurface(aSurface, mat, ExtendMode::CLAMP);
 
   if (!mat.IsIdentity()) {
     gfxDebug() << *this << ": At this point complex partial uploads are not supported for CopySurface.";
     return;
   }
 
   mDC->DrawImage(image, D2D1::Point2F(Float(aDestination.x), Float(aDestination.y)),
                  D2D1::RectF(Float(aSourceRect.x), Float(aSourceRect.y), 
@@ -280,17 +280,17 @@ DrawTargetD2D1::StrokeLine(const Point &
 }
 
 void
 DrawTargetD2D1::Stroke(const Path *aPath,
                        const Pattern &aPattern,
                        const StrokeOptions &aStrokeOptions,
                        const DrawOptions &aOptions)
 {
-  if (aPath->GetBackendType() != BACKEND_DIRECT2D) {
+  if (aPath->GetBackendType() != BackendType::DIRECT2D) {
     gfxDebug() << *this << ": Ignoring drawing call for incompatible path.";
     return;
   }
   const PathD2D *d2dPath = static_cast<const PathD2D*>(aPath);
 
   PrepareForDrawing(aOptions.mCompositionOp, aPattern);
 
   RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
@@ -301,17 +301,17 @@ DrawTargetD2D1::Stroke(const Path *aPath
   FinalizeDrawing(aOptions.mCompositionOp, aPattern);
 }
 
 void
 DrawTargetD2D1::Fill(const Path *aPath,
                      const Pattern &aPattern,
                      const DrawOptions &aOptions)
 {
-  if (aPath->GetBackendType() != BACKEND_DIRECT2D) {
+  if (aPath->GetBackendType() != BackendType::DIRECT2D) {
     gfxDebug() << *this << ": Ignoring drawing call for incompatible path.";
     return;
   }
   const PathD2D *d2dPath = static_cast<const PathD2D*>(aPath);
 
   PrepareForDrawing(aOptions.mCompositionOp, aPattern);
 
   RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
@@ -323,67 +323,67 @@ DrawTargetD2D1::Fill(const Path *aPath,
 
 void
 DrawTargetD2D1::FillGlyphs(ScaledFont *aFont,
                            const GlyphBuffer &aBuffer,
                            const Pattern &aPattern,
                            const DrawOptions &aOptions,
                            const GlyphRenderingOptions *aRenderingOptions)
 {
-  if (aFont->GetType() != FONT_DWRITE) {
+  if (aFont->GetType() != FontType::DWRITE) {
     gfxDebug() << *this << ": Ignoring drawing call for incompatible font.";
     return;
   }
 
   ScaledFontDWrite *font = static_cast<ScaledFontDWrite*>(aFont);
 
   IDWriteRenderingParams *params = nullptr;
   if (aRenderingOptions) {
-    if (aRenderingOptions->GetType() != FONT_DWRITE) {
+    if (aRenderingOptions->GetType() != FontType::DWRITE) {
       gfxDebug() << *this << ": Ignoring incompatible GlyphRenderingOptions.";
       // This should never happen.
       MOZ_ASSERT(false);
     } else {
       params = static_cast<const GlyphRenderingOptionsDWrite*>(aRenderingOptions)->mParams;
     }
   }
 
   AntialiasMode aaMode = font->GetDefaultAAMode();
 
-  if (aOptions.mAntialiasMode != AA_DEFAULT) {
+  if (aOptions.mAntialiasMode != AntialiasMode::DEFAULT) {
     aaMode = aOptions.mAntialiasMode;
   }
 
   PrepareForDrawing(aOptions.mCompositionOp, aPattern);
 
   bool forceClearType = false;
-  if (mFormat == FORMAT_B8G8R8A8 && mPermitSubpixelAA &&
-      aOptions.mCompositionOp == OP_OVER && aaMode == AA_SUBPIXEL) {
+  if (mFormat == SurfaceFormat::B8G8R8A8 && mPermitSubpixelAA &&
+      aOptions.mCompositionOp == CompositionOp::OP_OVER && aaMode == AntialiasMode::SUBPIXEL) {
     forceClearType = true;    
   }
 
 
   D2D1_TEXT_ANTIALIAS_MODE d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
 
   switch (aaMode) {
-  case AA_NONE:
+  case AntialiasMode::NONE:
     d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
     break;
-  case AA_GRAY:
+  case AntialiasMode::GRAY:
     d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
     break;
-  case AA_SUBPIXEL:
+  case AntialiasMode::SUBPIXEL:
     d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
     break;
   default:
     d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
   }
 
   if (d2dAAMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE &&
-      mFormat != FORMAT_B8G8R8X8 && !forceClearType) {
+      mFormat != SurfaceFormat::B8G8R8X8 && !forceClearType) {
     d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
   }
 
   mDC->SetTextAntialiasMode(d2dAAMode);
 
   if (params != mTextRenderingParams) {
     mDC->SetTextRenderingParams(params);
     mTextRenderingParams = params;
@@ -425,17 +425,17 @@ DrawTargetD2D1::Mask(const Pattern &aSou
   mDC->PopLayer();
 
   FinalizeDrawing(aOptions.mCompositionOp, aSource);
 }
 
 void
 DrawTargetD2D1::PushClip(const Path *aPath)
 {
-  if (aPath->GetBackendType() != BACKEND_DIRECT2D) {
+  if (aPath->GetBackendType() != BackendType::DIRECT2D) {
     gfxDebug() << *this << ": Ignoring clipping call for incompatible path.";
     return;
   }
 
   RefPtr<PathD2D> pathD2D = static_cast<PathD2D*>(const_cast<Path*>(aPath));
 
   PushedClip clip;
   clip.mTransform = D2DMatrix(mTransform);
@@ -548,17 +548,17 @@ DrawTargetD2D1::CreatePathBuilder(FillRu
 
   RefPtr<ID2D1GeometrySink> sink;
   hr = path->Open(byRef(sink));
   if (FAILED(hr)) {
     gfxWarning() << *this << ": Failed to access Direct2D Path Geometry. Code: " << hr;
     return nullptr;
   }
 
-  if (aFillRule == FILL_WINDING) {
+  if (aFillRule == FillRule::FILL_WINDING) {
     sink->SetFillMode(D2D1_FILL_MODE_WINDING);
   }
 
   return new PathBuilderD2D(sink, path, aFillRule);
 }
 
 TemporaryRef<GradientStops>
 DrawTargetD2D1::CreateGradientStops(GradientStop *rawStops, uint32_t aNumStops, ExtendMode aExtendMode) const
@@ -690,30 +690,30 @@ DrawTargetD2D1::PrepareForDrawing(Compos
   // the transform to become dirty.
   if (!mClipsArePushed) {
     mClipsArePushed = true;
     PushClipsToDC(mDC);
   }
 
   FlushTransformToDC();
 
-  if (aOp == OP_OVER && IsPatternSupportedByD2D(aPattern)) {
+  if (aOp == CompositionOp::OP_OVER && IsPatternSupportedByD2D(aPattern)) {
     return;
   }
 
   mDC->SetTarget(mTempBitmap);
   mDC->Clear(D2D1::ColorF(0, 0));
 }
 
 void
 DrawTargetD2D1::FinalizeDrawing(CompositionOp aOp, const Pattern &aPattern)
 {
   bool patternSupported = IsPatternSupportedByD2D(aPattern);
 
-  if (aOp == OP_OVER && patternSupported) {
+  if (aOp == CompositionOp::OP_OVER && patternSupported) {
     return;
   }
 
   RefPtr<ID2D1Image> image;
   mDC->GetTarget(byRef(image));
 
   mDC->SetTarget(mBitmap);
 
@@ -794,25 +794,25 @@ TemporaryRef<ID2D1Brush>
 DrawTargetD2D1::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
 {
   if (!IsPatternSupportedByD2D(aPattern)) {
     RefPtr<ID2D1SolidColorBrush> colBrush;
     mDC->CreateSolidColorBrush(D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f), byRef(colBrush));
     return colBrush;
   }
 
-  if (aPattern.GetType() == PATTERN_COLOR) {
+  if (aPattern.GetType() == PatternType::COLOR) {
     RefPtr<ID2D1SolidColorBrush> colBrush;
     Color color = static_cast<const ColorPattern*>(&aPattern)->mColor;
     mDC->CreateSolidColorBrush(D2D1::ColorF(color.r, color.g,
                                             color.b, color.a),
                                D2D1::BrushProperties(aAlpha),
                                byRef(colBrush));
     return colBrush;
-  } else if (aPattern.GetType() == PATTERN_LINEAR_GRADIENT) {
+  } else if (aPattern.GetType() == PatternType::LINEAR_GRADIENT) {
     RefPtr<ID2D1LinearGradientBrush> gradBrush;
     const LinearGradientPattern *pat =
       static_cast<const LinearGradientPattern*>(&aPattern);
 
     GradientStopsD2D *stops = static_cast<GradientStopsD2D*>(pat->mStops.get());
 
     if (!stops) {
       gfxDebug() << "No stops specified for gradient pattern.";
@@ -831,17 +831,17 @@ DrawTargetD2D1::CreateBrushForPattern(co
     }
 
     mDC->CreateLinearGradientBrush(D2D1::LinearGradientBrushProperties(D2DPoint(pat->mBegin),
                                                                        D2DPoint(pat->mEnd)),
                                    D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)),
                                    stops->mStopCollection,
                                    byRef(gradBrush));
     return gradBrush;
-  } else if (aPattern.GetType() == PATTERN_RADIAL_GRADIENT) {
+  } else if (aPattern.GetType() == PatternType::RADIAL_GRADIENT) {
     RefPtr<ID2D1RadialGradientBrush> gradBrush;
     const RadialGradientPattern *pat =
       static_cast<const RadialGradientPattern*>(&aPattern);
 
     GradientStopsD2D *stops = static_cast<GradientStopsD2D*>(pat->mStops.get());
 
     if (!stops) {
       gfxDebug() << "No stops specified for gradient pattern.";
@@ -853,17 +853,17 @@ DrawTargetD2D1::CreateBrushForPattern(co
       D2D1::RadialGradientBrushProperties(D2DPoint(pat->mCenter2),
                                           D2DPoint(pat->mCenter1 - pat->mCenter2),
                                           pat->mRadius2, pat->mRadius2),
       D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)),
       stops->mStopCollection,
       byRef(gradBrush));
 
     return gradBrush;
-  } else if (aPattern.GetType() == PATTERN_SURFACE) {
+  } else if (aPattern.GetType() == PatternType::SURFACE) {
     const SurfacePattern *pat =
       static_cast<const SurfacePattern*>(&aPattern);
 
     if (!pat->mSurface) {
       gfxDebug() << "No source surface specified for surface pattern";
       return nullptr;
     }
 
@@ -889,17 +889,17 @@ DrawTargetD2D1::CreateBrushForPattern(co
 
 TemporaryRef<ID2D1Image>
 DrawTargetD2D1::GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTransform,
                                    ExtendMode aExtendMode)
 {
   RefPtr<ID2D1Image> image;
 
   switch (aSurface->GetType()) {
-  case SURFACE_D2D1_1_IMAGE:
+  case SurfaceType::D2D1_1_IMAGE:
     {
       SourceSurfaceD2D1 *surf = static_cast<SourceSurfaceD2D1*>(aSurface);
       image = surf->GetImage();
       AddDependencyOnSource(surf);
     }
     break;
   default:
     {
--- a/gfx/2d/DrawTargetD2D1.h
+++ b/gfx/2d/DrawTargetD2D1.h
@@ -33,17 +33,17 @@ class ScaledFontDWrite;
 const int32_t kLayerCacheSize1 = 5;
 
 class DrawTargetD2D1 : public DrawTarget
 {
 public:
   DrawTargetD2D1();
   virtual ~DrawTargetD2D1();
 
-  virtual BackendType GetType() const { return BACKEND_DIRECT2D1_1; }
+  virtual BackendType GetType() const { return BackendType::DIRECT2D1_1; }
   virtual TemporaryRef<SourceSurface> Snapshot();
   virtual IntSize GetSize() { return mSize; }
 
   virtual void Flush();
   virtual void DrawSurface(SourceSurface *aSurface,
                            const Rect &aDest,
                            const Rect &aSource,
                            const DrawSurfaceOptions &aSurfOptions,
@@ -106,22 +106,22 @@ public:
   virtual TemporaryRef<SourceSurface> OptimizeSourceSurface(SourceSurface *aSurface) const { return nullptr; }
 
   virtual TemporaryRef<SourceSurface>
     CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const { return nullptr; }
   
   virtual TemporaryRef<DrawTarget>
     CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const;
 
-  virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FILL_WINDING) const;
+  virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const;
 
   virtual TemporaryRef<GradientStops>
     CreateGradientStops(GradientStop *aStops,
                         uint32_t aNumStops,
-                        ExtendMode aExtendMode = EXTEND_CLAMP) const;
+                        ExtendMode aExtendMode = ExtendMode::CLAMP) const;
 
   virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType);
 
   virtual void *GetNativeSurface(NativeSurfaceType aType) { return nullptr; }
 
   bool Init(const IntSize &aSize, SurfaceFormat aFormat);
   uint32_t GetByteSize() const;
 
--- a/gfx/2d/DrawTargetDual.cpp
+++ b/gfx/2d/DrawTargetDual.cpp
@@ -9,17 +9,17 @@
 namespace mozilla {
 namespace gfx {
 
 class DualSurface
 {
 public:
   inline DualSurface(SourceSurface *aSurface)
   {
-    if (aSurface->GetType() != SURFACE_DUAL_DT) {
+    if (aSurface->GetType() != SurfaceType::DUAL_DT) {
       mA = mB = aSurface;
       return;
     }
 
     SourceSurfaceDual *ssDual =
       static_cast<SourceSurfaceDual*>(aSurface);
     mA = ssDual->mA;
     mB = ssDual->mB;
@@ -34,25 +34,25 @@ public:
  * we need to pass separate patterns into our destination DrawTargets.
  */
 class DualPattern
 {
 public:
   inline DualPattern(const Pattern &aPattern)
     : mPatternsInitialized(false)
   {
-    if (aPattern.GetType() != PATTERN_SURFACE) {
+    if (aPattern.GetType() != PatternType::SURFACE) {
       mA = mB = &aPattern;
       return;
     }
 
     const SurfacePattern *surfPat =
       static_cast<const SurfacePattern*>(&aPattern);
 
-    if (surfPat->mSurface->GetType() != SURFACE_DUAL_DT) {
+    if (surfPat->mSurface->GetType() != SurfaceType::DUAL_DT) {
       mA = mB = &aPattern;
       return;
     }
 
     const SourceSurfaceDual *ssDual =
       static_cast<const SourceSurfaceDual*>(surfPat->mSurface.get());
     mA = new (mSurfPatA.addr()) SurfacePattern(ssDual->mA, surfPat->mExtendMode,
                                                surfPat->mMatrix, surfPat->mFilter);
--- a/gfx/2d/DrawTargetDual.h
+++ b/gfx/2d/DrawTargetDual.h
@@ -119,25 +119,25 @@ public:
     CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
   {
     return mA->CreateSourceSurfaceFromNativeSurface(aSurface);
   }
      
   virtual TemporaryRef<DrawTarget>
     CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const;
      
-  virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FILL_WINDING) const
+  virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const
   {
     return mA->CreatePathBuilder(aFillRule);
   }
      
   virtual TemporaryRef<GradientStops>
     CreateGradientStops(GradientStop *aStops,
                         uint32_t aNumStops,
-                        ExtendMode aExtendMode = EXTEND_CLAMP) const
+                        ExtendMode aExtendMode = ExtendMode::CLAMP) const
   {
     return mA->CreateGradientStops(aStops, aNumStops, aExtendMode);
   }
 
   virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType)
   {
     return mA->CreateFilter(aType);
   }
--- a/gfx/2d/DrawTargetRecording.cpp
+++ b/gfx/2d/DrawTargetRecording.cpp
@@ -22,17 +22,17 @@ public:
   {
   }
 
   ~SourceSurfaceRecording()
   {
     mRecorder->RecordEvent(RecordedSourceSurfaceDestruction(this));
   }
 
-  virtual SurfaceType GetType() const { return SURFACE_RECORDING; }
+  virtual SurfaceType GetType() const { return SurfaceType::RECORDING; }
   virtual IntSize GetSize() const { return mFinalSurface->GetSize(); }
   virtual SurfaceFormat GetFormat() const { return mFinalSurface->GetFormat(); }
   virtual TemporaryRef<DataSourceSurface> GetDataSurface() { return mFinalSurface->GetDataSurface(); }
 
   RefPtr<SourceSurface> mFinalSurface;
   RefPtr<DrawEventRecorderPrivate> mRecorder;
 };
 
@@ -44,36 +44,36 @@ public:
   {
   }
 
   ~GradientStopsRecording()
   {
     mRecorder->RecordEvent(RecordedGradientStopsDestruction(this));
   }
 
-  virtual BackendType GetBackendType() const { return BACKEND_RECORDING; }
+  virtual BackendType GetBackendType() const { return BackendType::RECORDING; }
 
   RefPtr<GradientStops> mFinalGradientStops;
   RefPtr<DrawEventRecorderPrivate> mRecorder;
 };
 
 static SourceSurface *
 GetSourceSurface(SourceSurface *aSurface)
 {
-  if (aSurface->GetType() != SURFACE_RECORDING) {
+  if (aSurface->GetType() != SurfaceType::RECORDING) {
     return aSurface;
   }
 
   return static_cast<SourceSurfaceRecording*>(aSurface)->mFinalSurface;
 }
 
 static GradientStops *
 GetGradientStops(GradientStops *aStops)
 {
-  if (aStops->GetBackendType() != BACKEND_RECORDING) {
+  if (aStops->GetBackendType() != BackendType::RECORDING) {
     return aStops;
   }
 
   return static_cast<GradientStopsRecording*>(aStops)->mFinalGradientStops;
 }
 
 class FilterNodeRecording : public FilterNode
 {
@@ -164,37 +164,37 @@ struct AdjustedPattern
     if (mPattern) {
       mPattern->~Pattern();
     }
   }
 
   operator Pattern*()
   {
     switch(mOrigPattern->GetType()) {
-    case PATTERN_COLOR:
+    case PatternType::COLOR:
       return mOrigPattern;
-    case PATTERN_SURFACE:
+    case PatternType::SURFACE:
       {
         SurfacePattern *surfPat = static_cast<SurfacePattern*>(mOrigPattern);
         mPattern =
           new (mSurfPat) SurfacePattern(GetSourceSurface(surfPat->mSurface),
                                         surfPat->mExtendMode, surfPat->mMatrix,
                                         surfPat->mFilter);
         return mPattern;
       }
-    case PATTERN_LINEAR_GRADIENT:
+    case PatternType::LINEAR_GRADIENT:
       {
         LinearGradientPattern *linGradPat = static_cast<LinearGradientPattern*>(mOrigPattern);
         mPattern =
           new (mLinGradPat) LinearGradientPattern(linGradPat->mBegin, linGradPat->mEnd,
                                                   GetGradientStops(linGradPat->mStops),
                                                   linGradPat->mMatrix);
         return mPattern;
       }
-    case PATTERN_RADIAL_GRADIENT:
+    case PatternType::RADIAL_GRADIENT:
       {
         RadialGradientPattern *radGradPat = static_cast<RadialGradientPattern*>(mOrigPattern);
         mPattern =
           new (mRadGradPat) RadialGradientPattern(radGradPat->mCenter1, radGradPat->mCenter2,
                                                   radGradPat->mRadius1, radGradPat->mRadius2,
                                                   GetGradientStops(radGradPat->mStops),
                                                   radGradPat->mMatrix);
         return mPattern;
@@ -260,17 +260,17 @@ DrawTargetRecording::StrokeLine(const Po
 {
   mRecorder->RecordEvent(RecordedStrokeLine(this, aBegin, aEnd, aPattern, aStrokeOptions, aOptions));
   mFinalDT->StrokeLine(aBegin, aEnd, *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
 }
 
 Path*
 DrawTargetRecording::GetPathForPathRecording(const Path *aPath) const
 {
-  if (aPath->GetBackendType() != BACKEND_RECORDING) {
+  if (aPath->GetBackendType() != BackendType::RECORDING) {
     return nullptr;
   }
 
   return static_cast<const PathRecording*>(aPath)->mPath;
 }
 
 void
 DrawTargetRecording::Fill(const Path *aPath,
@@ -569,17 +569,17 @@ DrawTargetRecording::SetTransform(const 
   DrawTarget::SetTransform(aTransform);
   mFinalDT->SetTransform(aTransform);
 }
 
 void
 DrawTargetRecording::EnsureStored(const Path *aPath)
 {
   if (!mRecorder->HasStoredPath(aPath)) {
-    if (aPath->GetBackendType() != BACKEND_RECORDING) {
+    if (aPath->GetBackendType() != BackendType::RECORDING) {
       gfxWarning() << "Cannot record this fill path properly!";
     } else {
       PathRecording *recPath = const_cast<PathRecording*>(static_cast<const PathRecording*>(aPath));
       mRecorder->RecordEvent(RecordedPathCreation(recPath));
       mRecorder->AddStoredPath(aPath);
       recPath->mStoredRecorders.push_back(mRecorder);
     }
   }
--- a/gfx/2d/DrawTargetRecording.h
+++ b/gfx/2d/DrawTargetRecording.h
@@ -236,32 +236,32 @@ public:
 
   /*
    * Create a path builder with the specified fillmode.
    *
    * We need the fill mode up front because of Direct2D.
    * ID2D1SimplifiedGeometrySink requires the fill mode
    * to be set before calling BeginFigure().
    */
-  virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FILL_WINDING) const;
+  virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const;
 
   /*
    * Create a GradientStops object that holds information about a set of
    * gradient stops, this object is required for linear or radial gradient
    * patterns to represent the color stops in the gradient.
    *
    * aStops An array of gradient stops
    * aNumStops Number of stops in the array aStops
    * aExtendNone This describes how to extend the stop color outside of the
    *             gradient area.
    */
   virtual TemporaryRef<GradientStops>
     CreateGradientStops(GradientStop *aStops,
                         uint32_t aNumStops,
-                        ExtendMode aExtendMode = EXTEND_CLAMP) const;
+                        ExtendMode aExtendMode = ExtendMode::CLAMP) const;
 
   virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType);
 
   /*
    * Set a transform on the surface, this transform is applied at drawing time
    * to both the mask and source of the operation.
    */
   virtual void SetTransform(const Matrix &aTransform);
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -64,17 +64,17 @@ public:
       mPositions[i + shift] = SkFloatToScalar(aStops[i].offset);
     }
     if (aStops[aNumStops-1].offset != 1) {
       mColors[mCount-1] = ColorToSkColor(aStops[aNumStops-1].color, 1.0);
       mPositions[mCount-1] = SK_Scalar1;
     }
   }
 
-  BackendType GetBackendType() const { return BACKEND_SKIA; }
+  BackendType GetBackendType() const { return BackendType::SKIA; }
 
   std::vector<SkColor> mColors;
   std::vector<SkScalar> mPositions;
   int mCount;
   ExtendMode mExtendMode;
 };
 
 #ifdef USE_SKIA_GPU
@@ -146,34 +146,49 @@ DrawTargetSkia::PurgeAllCaches()
   uint32_t targetCount = targets.size();
   for (uint32_t i = 0; i < targetCount; i++) {
     targets[i]->PurgeCaches();
   }
 }
 
 #endif
 
-static SkBitmap
-GetBitmapForSurface(SourceSurface *aSurface)
+/**
+ * When constructing a temporary SkBitmap via GetBitmapForSurface, we may also
+ * have to construct a temporary DataSourceSurface, which must live as long as
+ * the SkBitmap. So we return a pair of the SkBitmap and the (optional)
+ * temporary surface.
+ */
+struct TempBitmap
 {
-  switch (aSurface->GetType()) {
-  case SURFACE_SKIA:
-    return static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
-  case SURFACE_DATA:
-    {
-      DataSourceSurface* surf = static_cast<DataSourceSurface*>(aSurface);
-      SkBitmap tmp;
-      tmp.setConfig(GfxFormatToSkiaConfig(surf->GetFormat()),
-                    surf->GetSize().width, surf->GetSize().height, surf->Stride());
-      tmp.setPixels(surf->GetData());
-      return tmp;
-    }
-  default:
+  SkBitmap mBitmap;
+  RefPtr<SourceSurface> mTmpSurface;
+};
+
+static TempBitmap
+GetBitmapForSurface(SourceSurface* aSurface)
+{
+  TempBitmap result;
+
+  if (aSurface->GetType() == SurfaceType::SKIA) {
+    result.mBitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
+    return result;
+  }
+
+  RefPtr<DataSourceSurface> surf = aSurface->GetDataSurface();
+  if (!surf) {
     MOZ_CRASH("Non-skia SourceSurfaces need to be DataSourceSurfaces");
   }
+
+  result.mBitmap.setConfig(GfxFormatToSkiaConfig(surf->GetFormat()),
+                                 surf->GetSize().width, surf->GetSize().height,
+                                 surf->Stride());
+  result.mBitmap.setPixels(surf->GetData());
+  result.mTmpSurface = surf.forget();
+  return result;
 }
 
 DrawTargetSkia::DrawTargetSkia()
   : mSnapshot(nullptr)
 {
 }
 
 DrawTargetSkia::~DrawTargetSkia()
@@ -192,25 +207,27 @@ DrawTargetSkia::Snapshot()
     mSnapshot = snapshot;
     if (!snapshot->InitFromCanvas(mCanvas.get(), mFormat, this))
       return nullptr;
   }
 
   return snapshot;
 }
 
-void SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, Float aAlpha = 1.0)
+static void
+SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, TempBitmap& aTmpBitmap,
+                Float aAlpha = 1.0)
 {
   switch (aPattern.GetType()) {
-    case PATTERN_COLOR: {
+    case PatternType::COLOR: {
       Color color = static_cast<const ColorPattern&>(aPattern).mColor;
       aPaint.setColor(ColorToSkColor(color, aAlpha));
       break;
     }
-    case PATTERN_LINEAR_GRADIENT: {
+    case PatternType::LINEAR_GRADIENT: {
       const LinearGradientPattern& pat = static_cast<const LinearGradientPattern&>(aPattern);
       GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
       SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode);
 
       if (stops->mCount >= 2) {
         SkPoint points[2];
         points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x), SkFloatToScalar(pat.mBegin.y));
         points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x), SkFloatToScalar(pat.mEnd.y));
@@ -228,17 +245,17 @@ void SetPaintPattern(SkPaint& aPaint, co
             SkSafeUnref(aPaint.setShader(shader));
         }
 
       } else {
         aPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
       }
       break;
     }
-    case PATTERN_RADIAL_GRADIENT: {
+    case PatternType::RADIAL_GRADIENT: {
       const RadialGradientPattern& pat = static_cast<const RadialGradientPattern&>(aPattern);
       GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
       SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode);
 
       if (stops->mCount >= 2) {
         SkPoint points[2];
         points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x), SkFloatToScalar(pat.mCenter1.y));
         points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x), SkFloatToScalar(pat.mCenter2.y));
@@ -258,40 +275,41 @@ void SetPaintPattern(SkPaint& aPaint, co
             SkSafeUnref(aPaint.setShader(shader));
         }
 
       } else {
         aPaint.setColor(SkColorSetARGB(0, 0, 0, 0));
       }
       break;
     }
-    case PATTERN_SURFACE: {
+    case PatternType::SURFACE: {
       const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
-      const SkBitmap& bitmap = GetBitmapForSurface(pat.mSurface);
+      aTmpBitmap = GetBitmapForSurface(pat.mSurface);
+      const SkBitmap& bitmap = aTmpBitmap.mBitmap;
 
       SkShader::TileMode mode = ExtendModeToTileMode(pat.mExtendMode);
       SkShader* shader = SkShader::CreateBitmapShader(bitmap, mode, mode);
       SkMatrix mat;
       GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
       shader->setLocalMatrix(mat);
       SkSafeUnref(aPaint.set