Merge inbound to m-c. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 30 Jul 2014 17:13:20 -0400
changeset 219789 005424a764da20705e205aeb0083b2ae7f4b559d
parent 219735 e71c55ff7219584f5920698244ffe2ed709692dd (current diff)
parent 219788 44d47b88f3c2219cbec714af8bc6d2dd39ab3dce (diff)
child 219798 60eeadfddc0e9bd15fc899ae7a1a9b2b1483e279
child 219853 81f81a4777f1b7c0db87b03b4bb9383aa101e128
child 219919 b4771f70160177c1ea7566b64213b80c7f390f28
push id583
push userbhearsum@mozilla.com
push dateMon, 24 Nov 2014 19:04:58 +0000
treeherdermozilla-release@c107e74250f4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone34.0a1
first release with
nightly linux32
005424a764da / 34.0a1 / 20140731030206 / files
nightly linux64
005424a764da / 34.0a1 / 20140731030206 / files
nightly mac
005424a764da / 34.0a1 / 20140731030206 / files
nightly win32
005424a764da / 34.0a1 / 20140731030206 / files
nightly win64
005424a764da / 34.0a1 / 20140731030206 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to m-c. a=merge
browser/components/loop/content/libs/sdk-content/css/ot.css
browser/components/loop/content/libs/sdk-content/images/rtc/access-denied-chrome.png
browser/components/loop/content/libs/sdk-content/images/rtc/access-denied-copy-firefox.png
browser/components/loop/content/libs/sdk-content/images/rtc/access-denied-firefox.png
browser/components/loop/content/libs/sdk-content/images/rtc/access-predenied-chrome.png
browser/components/loop/content/libs/sdk-content/images/rtc/access-prompt-chrome.png
browser/components/loop/content/libs/sdk-content/images/rtc/audioonly-publisher.png
browser/components/loop/content/libs/sdk-content/images/rtc/audioonly-subscriber.png
browser/components/loop/content/libs/sdk-content/images/rtc/buttons.png
browser/components/loop/content/libs/sdk-content/images/rtc/loader.gif
browser/components/loop/content/libs/sdk-content/images/rtc/mic-off.png
browser/components/loop/content/libs/sdk-content/images/rtc/mic-on.png
browser/components/loop/content/libs/sdk-content/images/rtc/speaker-off.png
browser/components/loop/content/libs/sdk-content/images/rtc/speaker-on.png
browser/components/loop/content/libs/sdk-content/js/dynamic_config.min.js
browser/components/loop/content/libs/sdk.js
toolkit/devtools/qrcode/moz.build
xpcom/tests/TestRefPtr.cpp
--- a/accessible/jsat/moz.build
+++ b/accessible/jsat/moz.build
@@ -1,17 +1,15 @@
 # -*- 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/.
 
-JS_MODULES_PATH = 'modules/accessibility'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.accessibility += [
     'AccessFu.jsm',
     'Constants.jsm',
     'ContentControl.jsm',
     'EventManager.jsm',
     'Gestures.jsm',
     'OutputGenerator.jsm',
     'PointerAdapter.jsm',
     'Presentation.jsm',
--- a/addon-sdk/moz.build
+++ b/addon-sdk/moz.build
@@ -3,13 +3,11 @@
 # 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/.
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
 DIRS += ["source/modules/system"]
 
-JS_MODULES_PATH = 'modules/sdk'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.sdk += [
     'source/app-extension/bootstrap.js',
 ]
--- a/addon-sdk/source/modules/system/moz.build
+++ b/addon-sdk/source/modules/system/moz.build
@@ -1,11 +1,9 @@
 # -*- 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/.
 
-JS_MODULES_PATH = 'modules/sdk/system'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.sdk.system += [
     'XulApp.js',
 ]
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2531,17 +2531,17 @@ let BrowserOnClick = {
         secHistogram.add(nsISecTel[bucketName + "WHY_BLOCKED"]);
 
         if (isMalware) {
           // Get the stop badware "why is this blocked" report url,
           // append the current url, and go there.
           try {
             let reportURL = formatURL("browser.safebrowsing.malware.reportURL", true);
             reportURL += location;
-            content.location = reportURL;
+            gBrowser.loadURI(reportURL);
           } catch (e) {
             Components.utils.reportError("Couldn't get malware report URL: " + e);
           }
         }
         else { // It's a phishing site, not malware
           openHelpLink("phishing-malware", false, "current");
         }
         break;
@@ -2556,26 +2556,27 @@ let BrowserOnClick = {
   /**
    * This functions prevents navigation from happening directly through the <a>
    * link in about:newtab (which is loaded in the parent and therefore would load
    * the next page also in the parent) and instructs the browser to open the url
    * in the current tab which will make it update the remoteness of the tab.
    */
   onE10sAboutNewTab: function(event, ownerDoc) {
     let isTopFrame = (ownerDoc.defaultView.parent === ownerDoc.defaultView);
-    if (!isTopFrame || event.button != 0) {
+    if (!isTopFrame) {
       return;
     }
 
     let anchorTarget = event.originalTarget.parentNode;
 
     if (anchorTarget instanceof HTMLAnchorElement &&
         anchorTarget.classList.contains("newtab-link")) {
       event.preventDefault();
-      openUILinkIn(anchorTarget.href, "current");
+      let where = whereToOpenLink(event, false, false);
+      openUILinkIn(anchorTarget.href, where);
     }
   },
 
   /**
    * The about:tabcrashed can't do window.reload() because that
    * would reload the page but not use a remote browser.
    */
   onAboutTabCrashed: function(event, ownerDoc) {
@@ -2596,21 +2597,21 @@ let BrowserOnClick = {
       TabCrashReporter.reloadCrashedTabs();
     }
   },
 
   ignoreWarningButton: function (isMalware) {
     // Allow users to override and continue through to the site,
     // but add a notify bar as a reminder, so that they don't lose
     // track after, e.g., tab switching.
-    gBrowser.loadURIWithFlags(content.location.href,
+    gBrowser.loadURIWithFlags(gBrowser.currentURI.spec,
                               nsIWebNavigation.LOAD_FLAGS_BYPASS_CLASSIFIER,
                               null, null, null);
 
-    Services.perms.add(makeURI(content.location.href), "safe-browsing",
+    Services.perms.add(gBrowser.currentURI, "safe-browsing",
                        Ci.nsIPermissionManager.ALLOW_ACTION,
                        Ci.nsIPermissionManager.EXPIRE_SESSION);
 
     let buttons = [{
       label: gNavigatorBundle.getString("safebrowsing.getMeOutOfHereButton.label"),
       accessKey: gNavigatorBundle.getString("safebrowsing.getMeOutOfHereButton.accessKey"),
       callback: function() { getMeOutOfHere(); }
     }];
@@ -2672,17 +2673,17 @@ function getMeOutOfHere() {
     url = prefs.getComplexValue("browser.startup.homepage",
                                 Ci.nsIPrefLocalizedString).data;
     // If url is a pipe-delimited set of pages, just take the first one.
     if (url.contains("|"))
       url = url.split("|")[0];
   } catch(e) {
     Components.utils.reportError("Couldn't get homepage pref: " + e);
   }
-  content.location = url;
+  gBrowser.loadURI(url);
 }
 
 function BrowserFullScreen()
 {
   window.fullScreen = !window.fullScreen;
 }
 
 function _checkDefaultAndSwitchToMetro() {
--- a/browser/components/loop/.gitignore
+++ b/browser/components/loop/.gitignore
@@ -1,2 +1,1 @@
 .module-cache
-standalone/content/config.js
rename from browser/components/loop/content/libs/sdk-content/css/ot.css
rename to browser/components/loop/content/shared/libs/sdk-content/css/ot.css
rename from browser/components/loop/content/libs/sdk-content/images/rtc/access-denied-chrome.png
rename to browser/components/loop/content/shared/libs/sdk-content/images/rtc/access-denied-chrome.png
rename from browser/components/loop/content/libs/sdk-content/images/rtc/access-denied-copy-firefox.png
rename to browser/components/loop/content/shared/libs/sdk-content/images/rtc/access-denied-copy-firefox.png
rename from browser/components/loop/content/libs/sdk-content/images/rtc/access-denied-firefox.png
rename to browser/components/loop/content/shared/libs/sdk-content/images/rtc/access-denied-firefox.png
rename from browser/components/loop/content/libs/sdk-content/images/rtc/access-predenied-chrome.png
rename to browser/components/loop/content/shared/libs/sdk-content/images/rtc/access-predenied-chrome.png
rename from browser/components/loop/content/libs/sdk-content/images/rtc/access-prompt-chrome.png
rename to browser/components/loop/content/shared/libs/sdk-content/images/rtc/access-prompt-chrome.png
rename from browser/components/loop/content/libs/sdk-content/images/rtc/audioonly-publisher.png
rename to browser/components/loop/content/shared/libs/sdk-content/images/rtc/audioonly-publisher.png
rename from browser/components/loop/content/libs/sdk-content/images/rtc/audioonly-subscriber.png
rename to browser/components/loop/content/shared/libs/sdk-content/images/rtc/audioonly-subscriber.png
rename from browser/components/loop/content/libs/sdk-content/images/rtc/buttons.png
rename to browser/components/loop/content/shared/libs/sdk-content/images/rtc/buttons.png
rename from browser/components/loop/content/libs/sdk-content/images/rtc/loader.gif
rename to browser/components/loop/content/shared/libs/sdk-content/images/rtc/loader.gif
rename from browser/components/loop/content/libs/sdk-content/images/rtc/mic-off.png
rename to browser/components/loop/content/shared/libs/sdk-content/images/rtc/mic-off.png
rename from browser/components/loop/content/libs/sdk-content/images/rtc/mic-on.png
rename to browser/components/loop/content/shared/libs/sdk-content/images/rtc/mic-on.png
rename from browser/components/loop/content/libs/sdk-content/images/rtc/speaker-off.png
rename to browser/components/loop/content/shared/libs/sdk-content/images/rtc/speaker-off.png
rename from browser/components/loop/content/libs/sdk-content/images/rtc/speaker-on.png
rename to browser/components/loop/content/shared/libs/sdk-content/images/rtc/speaker-on.png
rename from browser/components/loop/content/libs/sdk-content/js/dynamic_config.min.js
rename to browser/components/loop/content/shared/libs/sdk-content/js/dynamic_config.min.js
rename from browser/components/loop/content/libs/sdk.js
rename to browser/components/loop/content/shared/libs/sdk.js
--- a/browser/components/loop/jar.mn
+++ b/browser/components/loop/jar.mn
@@ -48,24 +48,24 @@ browser.jar:
   content/browser/loop/shared/libs/lodash-2.4.1.js    (content/shared/libs/lodash-2.4.1.js)
   content/browser/loop/shared/libs/jquery-2.1.0.js    (content/shared/libs/jquery-2.1.0.js)
   content/browser/loop/shared/libs/backbone-1.1.2.js  (content/shared/libs/backbone-1.1.2.js)
 
   # Shared sounds
   content/browser/loop/shared/sounds/Firefox-Long.ogg (content/shared/sounds/Firefox-Long.ogg)
 
   # Partner SDK assets
-  content/browser/loop/libs/sdk.js                                                    (content/libs/sdk.js)
-  content/browser/loop/sdk-content/css/ot.css                                 (content/libs/sdk-content/css/ot.css)
-  content/browser/loop/sdk-content/js/dynamic_config.min.js                   (content/libs/sdk-content/js/dynamic_config.min.js)
-  content/browser/loop/sdk-content/images/rtc/access-denied-chrome.png        (content/libs/sdk-content/images/rtc/access-denied-chrome.png)
-  content/browser/loop/sdk-content/images/rtc/access-denied-copy-firefox.png  (content/libs/sdk-content/images/rtc/access-denied-copy-firefox.png)
-  content/browser/loop/sdk-content/images/rtc/access-denied-firefox.png       (content/libs/sdk-content/images/rtc/access-denied-firefox.png)
-  content/browser/loop/sdk-content/images/rtc/access-predenied-chrome.png     (content/libs/sdk-content/images/rtc/access-predenied-chrome.png)
-  content/browser/loop/sdk-content/images/rtc/access-prompt-chrome.png        (content/libs/sdk-content/images/rtc/access-prompt-chrome.png)
-  content/browser/loop/sdk-content/images/rtc/audioonly-publisher.png         (content/libs/sdk-content/images/rtc/audioonly-publisher.png)
-  content/browser/loop/sdk-content/images/rtc/audioonly-subscriber.png        (content/libs/sdk-content/images/rtc/audioonly-subscriber.png)
-  content/browser/loop/sdk-content/images/rtc/buttons.png                     (content/libs/sdk-content/images/rtc/buttons.png)
-  content/browser/loop/sdk-content/images/rtc/loader.gif                      (content/libs/sdk-content/images/rtc/loader.gif)
-  content/browser/loop/sdk-content/images/rtc/mic-off.png                     (content/libs/sdk-content/images/rtc/mic-off.png)
-  content/browser/loop/sdk-content/images/rtc/mic-on.png                      (content/libs/sdk-content/images/rtc/mic-on.png)
-  content/browser/loop/sdk-content/images/rtc/speaker-off.png                 (content/libs/sdk-content/images/rtc/speaker-off.png)
-  content/browser/loop/sdk-content/images/rtc/speaker-on.png                  (content/libs/sdk-content/images/rtc/speaker-on.png)
+  content/browser/loop/libs/sdk.js                                                    (content/shared/libs/sdk.js)
+  content/browser/loop/sdk-content/css/ot.css                                 (content/shared/libs/sdk-content/css/ot.css)
+  content/browser/loop/sdk-content/js/dynamic_config.min.js                   (content/shared/libs/sdk-content/js/dynamic_config.min.js)
+  content/browser/loop/sdk-content/images/rtc/access-denied-chrome.png        (content/shared/libs/sdk-content/images/rtc/access-denied-chrome.png)
+  content/browser/loop/sdk-content/images/rtc/access-denied-copy-firefox.png  (content/shared/libs/sdk-content/images/rtc/access-denied-copy-firefox.png)
+  content/browser/loop/sdk-content/images/rtc/access-denied-firefox.png       (content/shared/libs/sdk-content/images/rtc/access-denied-firefox.png)
+  content/browser/loop/sdk-content/images/rtc/access-predenied-chrome.png     (content/shared/libs/sdk-content/images/rtc/access-predenied-chrome.png)
+  content/browser/loop/sdk-content/images/rtc/access-prompt-chrome.png        (content/shared/libs/sdk-content/images/rtc/access-prompt-chrome.png)
+  content/browser/loop/sdk-content/images/rtc/audioonly-publisher.png         (content/shared/libs/sdk-content/images/rtc/audioonly-publisher.png)
+  content/browser/loop/sdk-content/images/rtc/audioonly-subscriber.png        (content/shared/libs/sdk-content/images/rtc/audioonly-subscriber.png)
+  content/browser/loop/sdk-content/images/rtc/buttons.png                     (content/shared/libs/sdk-content/images/rtc/buttons.png)
+  content/browser/loop/sdk-content/images/rtc/loader.gif                      (content/shared/libs/sdk-content/images/rtc/loader.gif)
+  content/browser/loop/sdk-content/images/rtc/mic-off.png                     (content/shared/libs/sdk-content/images/rtc/mic-off.png)
+  content/browser/loop/sdk-content/images/rtc/mic-on.png                      (content/shared/libs/sdk-content/images/rtc/mic-on.png)
+  content/browser/loop/sdk-content/images/rtc/speaker-off.png                 (content/shared/libs/sdk-content/images/rtc/speaker-off.png)
+  content/browser/loop/sdk-content/images/rtc/speaker-on.png                  (content/shared/libs/sdk-content/images/rtc/speaker-on.png)
--- a/browser/components/loop/moz.build
+++ b/browser/components/loop/moz.build
@@ -1,22 +1,20 @@
 # -*- 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/.
 
 JAR_MANIFESTS += ['jar.mn']
 
-JS_MODULES_PATH = 'modules/loop'
-
 XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
 
 BROWSER_CHROME_MANIFESTS += [
     'test/mochitest/browser.ini',
 ]
 
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.loop += [
     'MozLoopAPI.jsm',
     'MozLoopPushHandler.jsm',
     'MozLoopService.jsm',
     'MozLoopWorker.js',
 ]
--- a/browser/components/loop/standalone/.gitignore
+++ b/browser/components/loop/standalone/.gitignore
@@ -1,2 +1,5 @@
+.module-cache
 node_modules
 *.pyc
+content/config.js
+content/VERSION.txt
--- a/browser/components/loop/standalone/Makefile
+++ b/browser/components/loop/standalone/Makefile
@@ -16,13 +16,28 @@ lint:
 	@$(NODE_LOCAL_BIN)/jshint *.js content test
 
 runserver: config
 	@node server.js
 
 frontend:
 	@echo "Not implemented yet."
 
+# Try hg first, if not fall back to git.
+SOURCE_STAMP := $(shell hg parent --template '{node|short}\n' 2> /dev/null)
+ifndef SOURCE_STAMP
+SOURCE_STAMP := $(shell git describe --always --tag)
+endif
+
+SOURCE_DATE := $(shell hg parent --template '{date|date}\n' 2> /dev/null)
+ifndef SOURCE_DATE
+SOURCE_DATE := $(shell git log -1 --format="%H%n%aD")
+endif
+
+version:
+	@echo $(SOURCE_STAMP) > content/VERSION.txt
+	@echo $(SOURCE_DATE) >> content/VERSION.txt
+
 config:
 	@echo "var loop = loop || {};" > content/config.js
 	@echo "loop.config = loop.config || {};" >> content/config.js
 	@echo "loop.config.serverUrl          = '`echo $(LOOP_SERVER_URL)`';" >> content/config.js
 	@echo "loop.config.pendingCallTimeout = `echo $(LOOP_PENDING_CALL_TIMEOUT)`;" >> content/config.js
--- a/browser/components/loop/standalone/content/index.html
+++ b/browser/components/loop/standalone/content/index.html
@@ -17,17 +17,25 @@
       <h1>Loop</h1>
     </header>
 
     <div id="messages"></div>
 
     <div id="main"></div>
 
     <!-- libs -->
-    <script src="https://static.opentok.com/webrtc/v2.2/js/opentok.min.js"></script>
+    <script>
+      window.OTProperties = {
+        cdnURL: 'shared/libs/',
+      };
+      window.OTProperties.assetURL = window.OTProperties.cdnURL + 'sdk-content/';
+      window.OTProperties.configURL = window.OTProperties.assetURL + 'js/dynamic_config.min.js';
+      window.OTProperties.cssURL = window.OTProperties.assetURL + 'css/ot.css';
+    </script>
+    <script type="text/javascript" src="shared/libs/sdk.js"></script>
     <script type="text/javascript" src="libs/webl10n-20130617.js"></script>
     <script type="text/javascript" src="shared/libs/react-0.10.0.js"></script>
     <script type="text/javascript" src="shared/libs/jquery-2.1.0.js"></script>
     <script type="text/javascript" src="shared/libs/lodash-2.4.1.js"></script>
     <script type="text/javascript" src="shared/libs/backbone-1.1.2.js"></script>
 
     <!-- app scripts -->
     <script type="text/javascript" src="config.js"></script>
--- a/browser/components/sessionstore/moz.build
+++ b/browser/components/sessionstore/moz.build
@@ -17,19 +17,17 @@ XPIDL_SOURCES += [
 XPIDL_MODULE = 'sessionstore'
 
 EXTRA_COMPONENTS += [
     'nsSessionStartup.js',
     'nsSessionStore.js',
     'nsSessionStore.manifest',
 ]
 
-JS_MODULES_PATH = 'modules/sessionstore'
-
-EXTRA_JS_MODULES = [
+EXTRA_JS_MODULES.sessionstore = [
     'ContentRestore.jsm',
     'DocShellCapabilities.jsm',
     'FrameTree.jsm',
     'GlobalState.jsm',
     'PageStyle.jsm',
     'PrivacyFilter.jsm',
     'PrivacyLevel.jsm',
     'RecentlyClosedTabsAndWindowsMenuUtils.jsm',
@@ -41,13 +39,13 @@ EXTRA_JS_MODULES = [
     'SessionWorker.js',
     'SessionWorker.jsm',
     'TabAttributes.jsm',
     'TabState.jsm',
     'TabStateCache.jsm',
     'Utils.jsm',
 ]
 
-EXTRA_PP_JS_MODULES += [
+EXTRA_PP_JS_MODULES.sessionstore += [
     'SessionSaver.jsm',
     'SessionStore.jsm',
 ]
 
--- a/browser/components/tabview/moz.build
+++ b/browser/components/tabview/moz.build
@@ -1,14 +1,12 @@
 # -*- 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/.
 
-EXTRA_JS_MODULES = ['modules/utils.jsm']
-JS_MODULES_PATH  = 'modules/tabview'
-
+EXTRA_JS_MODULES.tabview = ['modules/utils.jsm']
 BROWSER_CHROME_MANIFESTS += [
     'test/browser.ini',
 ]
 
 JAR_MANIFESTS += ['jar.mn']
\ No newline at end of file
--- a/browser/components/translation/moz.build
+++ b/browser/components/translation/moz.build
@@ -1,15 +1,13 @@
 # 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/.
 
-JS_MODULES_PATH = 'modules/translation'
-
-EXTRA_JS_MODULES = [
+EXTRA_JS_MODULES.translation = [
     'BingTranslator.jsm',
     'cld2/cld-worker.js',
     'cld2/cld-worker.js.mem',
     'LanguageDetector.jsm',
     'Translation.jsm',
     'TranslationContentHandler.jsm',
     'TranslationDocument.jsm'
 ]
--- a/browser/devtools/app-manager/moz.build
+++ b/browser/devtools/app-manager/moz.build
@@ -2,19 +2,17 @@
 # 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/.
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
-JS_MODULES_PATH = 'modules/devtools/app-manager'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools["app-manager"] += [
     'app-projects.js',
     'app-validator.js',
     'builtin-adb-store.js',
     'connection-store.js',
     'device-store.js',
     'simulators-store.js',
     'webapps-store.js',
 ]
--- a/browser/devtools/canvasdebugger/moz.build
+++ b/browser/devtools/canvasdebugger/moz.build
@@ -1,12 +1,10 @@
 # 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/.
 
-JS_MODULES_PATH = 'modules/devtools/canvasdebugger'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.canvasdebugger += [
     'panel.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/commandline/moz.build
+++ b/browser/devtools/commandline/moz.build
@@ -1,11 +1,9 @@
 # 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/.
 
-JS_MODULES_PATH = 'modules/devtools/commandline'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.commandline += [
     'commands-index.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/debugger/moz.build
+++ b/browser/devtools/debugger/moz.build
@@ -1,13 +1,11 @@
 # 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/.
 
-JS_MODULES_PATH = 'modules/devtools/debugger'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.debugger += [
     'debugger-commands.js',
     'panel.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/eyedropper/moz.build
+++ b/browser/devtools/eyedropper/moz.build
@@ -1,14 +1,12 @@
 # -*- 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/.
 
-JS_MODULES_PATH = 'modules/devtools/eyedropper'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.eyedropper += [
     'commands.js',
     'eyedropper.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/inspector/moz.build
+++ b/browser/devtools/inspector/moz.build
@@ -1,14 +1,12 @@
 # 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/.
 
-JS_MODULES_PATH = 'modules/devtools/inspector'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.inspector += [
     'breadcrumbs.js',
     'inspector-commands.js',
     'inspector-panel.js',
     'selector-search.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/markupview/moz.build
+++ b/browser/devtools/markupview/moz.build
@@ -1,14 +1,12 @@
 # -*- 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/.
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
-JS_MODULES_PATH = 'modules/devtools/markupview'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.markupview += [
     'html-editor.js',
     'markup-view.js',
 ]
--- a/browser/devtools/moz.build
+++ b/browser/devtools/moz.build
@@ -33,13 +33,11 @@ DIRS += [
 
 EXTRA_COMPONENTS += [
     'devtools-clhandler.js',
     'devtools-clhandler.manifest',
 ]
 
 JAR_MANIFESTS += ['jar.mn']
 
-JS_MODULES_PATH = 'modules/devtools'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools += [
     'main.js',
 ]
--- a/browser/devtools/netmonitor/moz.build
+++ b/browser/devtools/netmonitor/moz.build
@@ -1,12 +1,10 @@
 # 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/.
 
-JS_MODULES_PATH = 'modules/devtools/netmonitor'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.netmonitor += [
     'panel.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/profiler/moz.build
+++ b/browser/devtools/profiler/moz.build
@@ -1,18 +1,16 @@
 # -*- 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/.
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
-JS_MODULES_PATH = 'modules/devtools/profiler'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.profiler += [
     'cleopatra.js',
     'commands.js',
     'consts.js',
     'controller.js',
     'panel.js',
     'sidebar.js',
 ]
--- a/browser/devtools/responsivedesign/moz.build
+++ b/browser/devtools/responsivedesign/moz.build
@@ -1,11 +1,9 @@
 # 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/.
 
-JS_MODULES_PATH = 'modules/devtools'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools += [
     'resize-commands.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/scratchpad/moz.build
+++ b/browser/devtools/scratchpad/moz.build
@@ -1,14 +1,12 @@
 # -*- 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/.
 
-JS_MODULES_PATH = 'modules/devtools/scratchpad'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.scratchpad += [
     'scratchpad-commands.js',
     'scratchpad-panel.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/shadereditor/moz.build
+++ b/browser/devtools/shadereditor/moz.build
@@ -1,12 +1,10 @@
 # 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/.
 
-JS_MODULES_PATH = 'modules/devtools/shadereditor'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.shadereditor += [
     'panel.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/sourceeditor/moz.build
+++ b/browser/devtools/sourceeditor/moz.build
@@ -1,17 +1,15 @@
 # -*- 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/.
 
-JS_MODULES_PATH = 'modules/devtools/sourceeditor'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.sourceeditor += [
     'autocomplete.js',
     'css-autocompleter.js',
     'css-tokenizer.js',
     'debugger.js',
     'editor.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/styleinspector/moz.build
+++ b/browser/devtools/styleinspector/moz.build
@@ -2,17 +2,15 @@
 # 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/.
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/devtools/styleinspector'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.styleinspector += [
     'computed-view.js',
     'css-parsing-utils.js',
     'rule-view.js',
     'style-inspector-overlays.js',
     'style-inspector.js',
 ]
--- a/browser/devtools/tilt/moz.build
+++ b/browser/devtools/tilt/moz.build
@@ -1,15 +1,13 @@
 # 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/.
 
-JS_MODULES_PATH = 'modules/devtools/tilt'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.tilt += [
     'tilt-commands.js',
     'tilt-gl.js',
     'tilt-math.js',
     'tilt-utils.js',
     'tilt-visualizer-style.js',
     'tilt-visualizer.js',
     'tilt.js',
     'TiltWorkerCrafter.js',
--- a/browser/devtools/webaudioeditor/moz.build
+++ b/browser/devtools/webaudioeditor/moz.build
@@ -1,12 +1,10 @@
 # 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/.
 
-JS_MODULES_PATH = 'modules/devtools/webaudioeditor'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.webaudioeditor += [
     'panel.js'
 ]
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
--- a/browser/devtools/webconsole/moz.build
+++ b/browser/devtools/webconsole/moz.build
@@ -1,18 +1,16 @@
 # -*- 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/.
 
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
-JS_MODULES_PATH = 'modules/devtools/webconsole'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.webconsole += [
     'console-commands.js',
     'console-output.js',
     'hudservice.js',
     'network-panel.js',
     'panel.js',
     'webconsole.js',
 ]
--- a/browser/devtools/webide/moz.build
+++ b/browser/devtools/webide/moz.build
@@ -7,16 +7,14 @@
 DIRS += [
     'content',
     'components',
     'themes',
 ]
 
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
-JS_MODULES_PATH = 'modules/devtools/webide'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.webide += [
     'modules/addons.js',
     'modules/app-manager.js',
     'modules/remote-resources.js',
     'modules/runtimes.js'
 ]
--- a/browser/experiments/moz.build
+++ b/browser/experiments/moz.build
@@ -2,17 +2,15 @@
 # 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/.
 
 EXTRA_COMPONENTS += [
     'Experiments.manifest',
     'ExperimentsService.js',
 ]
 
-JS_MODULES_PATH = 'modules/experiments'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.experiments += [
   'Experiments.jsm',
 ]
 
 XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
 
 SPHINX_TREES['experiments'] = 'docs'
--- a/build/automationutils.py
+++ b/build/automationutils.py
@@ -72,16 +72,28 @@ DEBUGGER_INFO = {
   },
 
   "lldb": {
     "interactive": True,
     "args": "--",
     "requiresEscapedArgs": True
   },
 
+  # Visual Studio Debugger Support
+  "devenv.exe": {
+    "interactive": True,
+    "args": "-debugexe"
+  },
+
+  # Visual C++ Express Debugger Support
+  "wdexpress.exe": {
+    "interactive": True,
+    "args": "-debugexe"
+  },
+
   # valgrind doesn't explain much about leaks unless you set the
   # '--leak-check=full' flag. But there are a lot of objects that are
   # semi-deliberately leaked, so we set '--show-possibly-lost=no' to avoid
   # uninteresting output from those objects. We set '--smc-check==all-non-file'
   # and '--vex-iropt-register-updates=allregs-at-mem-access' so that valgrind
   # deals properly with JIT'd JavaScript code.
   "valgrind": {
     "interactive": False,
--- a/config/config.mk
+++ b/config/config.mk
@@ -50,17 +50,16 @@ endif
   HOST_CSRCS \
   HOST_CMMSRCS \
   HOST_LIBRARY_NAME \
   HOST_PROGRAM \
   HOST_SIMPLE_PROGRAMS \
   IS_COMPONENT \
   JAR_MANIFEST \
   JAVA_JAR_TARGETS \
-  JS_MODULES_PATH \
   LD_VERSION_SCRIPT \
   LIBRARY_NAME \
   LIBS \
   MAKE_FRAMEWORK \
   MODULE \
   MSVC_ENABLE_PGO \
   NO_DIST_INSTALL \
   PARALLEL_DIRS \
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1216,20 +1216,18 @@ endif
 EXTRA_MANIFESTS = $(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS))
 ifneq (,$(EXTRA_MANIFESTS))
 libs:: $(call mkdir_deps,$(FINAL_TARGET))
 	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest $(patsubst %,'manifest components/%',$(notdir $(EXTRA_MANIFESTS))))
 endif
 
 ################################################################################
 # Copy each element of EXTRA_JS_MODULES to
-# $(FINAL_TARGET)/$(JS_MODULES_PATH). JS_MODULES_PATH defaults to "modules"
-# if it is undefined.
-JS_MODULES_PATH ?= modules
-FINAL_JS_MODULES_PATH := $(FINAL_TARGET)/$(JS_MODULES_PATH)
+# $(FINAL_TARGET)/modules.
+FINAL_JS_MODULES_PATH := $(FINAL_TARGET)/modules
 
 ifdef EXTRA_JS_MODULES
 ifndef NO_DIST_INSTALL
 EXTRA_JS_MODULES_FILES := $(EXTRA_JS_MODULES)
 EXTRA_JS_MODULES_DEST := $(FINAL_JS_MODULES_PATH)
 INSTALL_TARGETS += EXTRA_JS_MODULES
 endif
 endif
--- a/configure.in
+++ b/configure.in
@@ -3839,17 +3839,16 @@ MOZ_LOCALE_SWITCHER=
 MOZ_ANDROID_SEARCH_ACTIVITY=
 MOZ_ANDROID_MLS_STUMBLER=
 ACCESSIBILITY=1
 MOZ_TIME_MANAGER=
 MOZ_PAY=
 MOZ_AUDIO_CHANNEL_MANAGER=
 NSS_NO_LIBPKIX=
 MOZ_CONTENT_SANDBOX=
-MOZ_GMP_SANDBOX=
 JSGC_USE_EXACT_ROOTING=1
 JSGC_GENERATIONAL=
 
 case "$target_os" in
     mingw*)
         NS_ENABLE_TSF=1
         AC_DEFINE(NS_ENABLE_TSF)
         ;;
@@ -5079,16 +5078,30 @@ MOZ_ARG_DISABLE_BOOL(webm,
     MOZ_WEBM=1)
 
 if test -n "$MOZ_WEBM"; then
     AC_DEFINE(MOZ_WEBM)
     MOZ_VPX=1
 fi;
 
 dnl ========================================================
+dnl = Apple platform decoder support
+dnl ========================================================
+if test "$MOZ_WIDGET_TOOLKIT" = "cocoa"; then
+  MOZ_APPLEMEDIA=1
+fi
+
+if test -n "$MOZ_APPLEMEDIA"; then
+  AC_DEFINE(MOZ_APPLEMEDIA)
+  # hack in frameworks for fmp4 - see bug 1029974
+  # We load VideoToolbox and CoreMedia dynamically, so they don't appear here.
+  LDFLAGS="$LDFLAGS -framework AudioToolbox"
+fi
+
+dnl ========================================================
 dnl = DirectShow support
 dnl ========================================================
 if test "$OS_ARCH" = "WINNT"; then
     dnl Enable DirectShow support by default.
     MOZ_DIRECTSHOW=1
 fi
 
 MOZ_ARG_DISABLE_BOOL(directshow,
@@ -5138,20 +5151,18 @@ MOZ_ARG_DISABLE_BOOL(ffmpeg,
 
 if test -n "$MOZ_FFMPEG"; then
     AC_DEFINE(MOZ_FFMPEG)
 fi;
 
 dnl ========================================================
 dnl = Built-in fragmented MP4 support.
 dnl ========================================================
-if test -n "$MOZ_WMF" -o -n "$MOZ_FFMPEG"; then
-    dnl Enable fragmented MP4 parser on Windows by default.
-    dnl We will also need to enable it on other platforms as we implement
-    dnl platform decoder support there too.
+if test -n "$MOZ_WMF" -o -n "$MOZ_FFMPEG" -o -n "$MOZ_APPLEMEDIA"; then
+    dnl Enable fragmented MP4 parser on platforms with decoder support.
     MOZ_FMP4=1
 fi
 
 MOZ_ARG_DISABLE_BOOL(fmp4,
 [  --disable-fmp4  Disable support for in built Fragmented MP4 parsing],
     MOZ_FMP4=,
     MOZ_FMP4=1)
 
@@ -5185,32 +5196,16 @@ MOZ_ARG_ENABLE_BOOL(android-omx,
     MOZ_ANDROID_OMX=1,
     MOZ_ANDROID_OMX=)
 
 if test -n "$MOZ_ANDROID_OMX"; then
   AC_DEFINE(MOZ_ANDROID_OMX)
 fi
 
 dnl ========================================================
-dnl = Disable platform MP3 decoder on OSX
-dnl ========================================================
-if test "$MOZ_WIDGET_TOOLKIT" = "cocoa"; then
-  MOZ_APPLEMEDIA=1
-fi
-
-MOZ_ARG_DISABLE_BOOL(apple-media,
-[  --disable-apple-media  Disable support for Apple AudioToolbox/VideoToolbox],
-    MOZ_APPLEMEDIA=,
-    MOZ_APPLEMEDIA=1)
-
-if test -n "$MOZ_APPLEMEDIA"; then
-  AC_DEFINE(MOZ_APPLEMEDIA)
-fi
-
-dnl ========================================================
 dnl = Enable getUserMedia support
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(media-navigator,
 [  --enable-media-navigator  Enable support for getUserMedia],
     MOZ_MEDIA_NAVIGATOR=1,
     MOZ_MEDIA_NAVIGATOR=)
 
 if test -n "$MOZ_MEDIA_NAVIGATOR"; then
@@ -6402,38 +6397,16 @@ MOZ_ARG_ENABLE_BOOL(content-sandbox,
 
 if test -n "$MOZ_CONTENT_SANDBOX"; then
     AC_DEFINE(MOZ_CONTENT_SANDBOX)
 fi
 
 AC_SUBST(MOZ_CONTENT_SANDBOX)
 
 dnl ========================================================
-dnl = Gecko Media Plugin sandboxing
-dnl ========================================================
-case $OS_TARGET in
-WINNT)
-    MOZ_GMP_SANDBOX=1
-    ;;
-Linux)
-    case $CPU_ARCH in
-    x86_64|x86)
-        MOZ_GMP_SANDBOX=1
-        ;;
-    esac
-    ;;
-esac
-
-if test -n "$MOZ_GMP_SANDBOX"; then
-    AC_DEFINE(MOZ_GMP_SANDBOX)
-fi
-
-AC_SUBST(MOZ_GMP_SANDBOX)
-
-dnl ========================================================
 dnl =
 dnl = Module specific options
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(Individual module options)
 
 dnl ========================================================
 dnl = Disable feed handling components
--- a/content/base/public/nsDOMFile.h
+++ b/content/base/public/nsDOMFile.h
@@ -743,26 +743,16 @@ private:
   nsCOMPtr<nsIFile> mFile;
   bool mWholeFile;
   bool mStoredFile;
 };
 
 } // dom namespace
 } // file namespace
 
-class MOZ_STACK_CLASS nsDOMFileInternalUrlHolder {
-public:
-  nsDOMFileInternalUrlHolder(nsIDOMBlob* aFile, nsIPrincipal* aPrincipal
-                             MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
-  ~nsDOMFileInternalUrlHolder();
-  nsAutoString mUrl;
-private:
-  MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
-};
-
 class nsDOMFileList MOZ_FINAL : public nsIDOMFileList,
                                 public nsWrapperCache
 {
   ~nsDOMFileList() {}
 
 public:
   nsDOMFileList(nsISupports *aParent) : mParent(aParent)
   {
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -1059,26 +1059,8 @@ nsDOMFileList::GetLength(uint32_t* aLeng
 
 NS_IMETHODIMP
 nsDOMFileList::Item(uint32_t aIndex, nsIDOMFile **aFile)
 {
   NS_IF_ADDREF(*aFile = Item(aIndex));
 
   return NS_OK;
 }
-
-////////////////////////////////////////////////////////////////////////////
-// nsDOMFileInternalUrlHolder implementation
-
-nsDOMFileInternalUrlHolder::nsDOMFileInternalUrlHolder(nsIDOMBlob* aFile,
-                                                       nsIPrincipal* aPrincipal
-                                                       MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL) {
-  MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-  aFile->GetInternalUrl(aPrincipal, mUrl);
-}
- 
-nsDOMFileInternalUrlHolder::~nsDOMFileInternalUrlHolder() {
-  if (!mUrl.IsEmpty()) {
-    nsAutoCString narrowUrl;
-    CopyUTF16toUTF8(mUrl, narrowUrl);
-    nsBlobProtocolHandler::RemoveDataEntry(narrowUrl);
-  }
-}
--- a/content/media/fmp4/MP4Decoder.cpp
+++ b/content/media/fmp4/MP4Decoder.cpp
@@ -12,16 +12,20 @@
 #include "prlog.h"
 
 #ifdef XP_WIN
 #include "mozilla/WindowsVersion.h"
 #endif
 #ifdef MOZ_FFMPEG
 #include "FFmpegRuntimeLinker.h"
 #endif
+#ifdef MOZ_APPLEMEDIA
+#include "apple/AppleCMLinker.h"
+#include "apple/AppleVTLinker.h"
+#endif
 
 namespace mozilla {
 
 MediaDecoderStateMachine* MP4Decoder::CreateStateMachine()
 {
   return new MediaDecoderStateMachine(this, new MP4Reader(this));
 }
 
@@ -98,24 +102,50 @@ IsFFmpegAvailable()
 
   // If we can link to FFmpeg, then we can almost certainly play H264 and AAC
   // with it.
   return FFmpegRuntimeLinker::Link();
 #endif
 }
 
 static bool
+IsAppleAvailable()
+{
+#ifndef MOZ_APPLEMEDIA
+  // Not the right platform.
+  return false;
+#else
+  if (!Preferences::GetBool("media.apple.mp4.enabled", false)) {
+    // Disabled by preference.
+    return false;
+  }
+  // Attempt to load the required frameworks.
+  bool haveCoreMedia = AppleCMLinker::Link();
+  if (!haveCoreMedia) {
+    return false;
+  }
+  bool haveVideoToolbox = AppleVTLinker::Link();
+  if (!haveVideoToolbox) {
+    return false;
+  }
+  // All hurdles cleared!
+  return true;
+#endif
+}
+
+static bool
 HavePlatformMPEGDecoders()
 {
   return Preferences::GetBool("media.fragmented-mp4.use-blank-decoder") ||
 #ifdef XP_WIN
          // We have H.264/AAC platform decoders on Windows Vista and up.
          IsVistaOrLater() ||
 #endif
          IsFFmpegAvailable() ||
+         IsAppleAvailable() ||
          // TODO: Other platforms...
          false;
 }
 
 /* static */
 bool
 MP4Decoder::IsEnabled()
 {
--- a/content/media/fmp4/PlatformDecoderModule.cpp
+++ b/content/media/fmp4/PlatformDecoderModule.cpp
@@ -6,16 +6,19 @@
 
 #include "PlatformDecoderModule.h"
 #ifdef XP_WIN
 #include "WMFDecoderModule.h"
 #endif
 #ifdef MOZ_FFMPEG
 #include "FFmpegRuntimeLinker.h"
 #endif
+#ifdef MOZ_APPLEMEDIA
+#include "AppleDecoderModule.h"
+#endif
 #include "mozilla/Preferences.h"
 #include "EMEDecoderModule.h"
 #include "mozilla/CDMProxy.h"
 #include "SharedThreadPool.h"
 #include "MediaTaskQueue.h"
 
 namespace mozilla {
 
@@ -37,16 +40,19 @@ PlatformDecoderModule::Init()
 
   Preferences::AddBoolVarCache(&sUseBlankDecoder,
                                "media.fragmented-mp4.use-blank-decoder");
   Preferences::AddBoolVarCache(&sFFmpegDecoderEnabled,
                                "media.fragmented-mp4.ffmpeg.enabled", false);
 #ifdef XP_WIN
   WMFDecoderModule::Init();
 #endif
+#ifdef MOZ_APPLEMEDIA
+  AppleDecoderModule::Init();
+#endif
 }
 
 class CreateTaskQueueTask : public nsRunnable {
 public:
   NS_IMETHOD Run() {
     MOZ_ASSERT(NS_IsMainThread());
     mTaskQueue = new MediaTaskQueue(GetMediaDecodeThreadPool());
     return NS_OK;
@@ -112,12 +118,18 @@ PlatformDecoderModule::Create()
     return m.forget();
   }
 #endif
 #ifdef MOZ_FFMPEG
   if (sFFmpegDecoderEnabled) {
     return FFmpegRuntimeLinker::CreateDecoderModule();
   }
 #endif
+#ifdef MOZ_APPLEMEDIA
+  nsAutoPtr<AppleDecoderModule> m(new AppleDecoderModule());
+  if (NS_SUCCEEDED(m->Startup())) {
+    return m.forget();
+  }
+#endif
   return nullptr;
 }
 
 } // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/AppleATDecoder.cpp
@@ -0,0 +1,354 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 <AudioToolbox/AudioToolbox.h>
+#include "AppleUtils.h"
+#include "MP4Reader.h"
+#include "MP4Decoder.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/ReentrantMonitor.h"
+#include "mp4_demuxer/DecoderData.h"
+#include "nsIThread.h"
+#include "AppleATDecoder.h"
+#include "prlog.h"
+
+#ifdef PR_LOGGING
+PRLogModuleInfo* GetDemuxerLog();
+#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
+#else
+#define LOG(...)
+#endif
+
+namespace mozilla {
+
+AppleATDecoder::AppleATDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
+                               MediaTaskQueue* anAudioTaskQueue,
+                               MediaDataDecoderCallback* aCallback)
+  : mConfig(aConfig)
+  , mTaskQueue(anAudioTaskQueue)
+  , mCallback(aCallback)
+  , mConverter(nullptr)
+  , mStream(nullptr)
+  , mCurrentAudioFrame(0)
+  , mSamplePosition(0)
+  , mHaveOutput(false)
+{
+  MOZ_COUNT_CTOR(AppleATDecoder);
+  LOG("Creating Apple AudioToolbox AAC decoder");
+  LOG("Audio Decoder configuration: %s %d Hz %d channels %d bits per channel",
+      mConfig.mime_type,
+      mConfig.samples_per_second,
+      mConfig.channel_count,
+      mConfig.bits_per_sample);
+  // TODO: Verify aConfig.mime_type.
+}
+
+AppleATDecoder::~AppleATDecoder()
+{
+  MOZ_COUNT_DTOR(AppleATDecoer);
+  MOZ_ASSERT(!mConverter);
+  MOZ_ASSERT(!mStream);
+}
+
+static void
+_MetadataCallback(void *aDecoder,
+                  AudioFileStreamID aStream,
+                  AudioFileStreamPropertyID aProperty,
+                  UInt32 *aFlags)
+{
+  LOG("AppleATDecoder metadata callback");
+  AppleATDecoder* decoder = static_cast<AppleATDecoder*>(aDecoder);
+  decoder->MetadataCallback(aStream, aProperty, aFlags);
+}
+
+static void
+_SampleCallback(void *aDecoder,
+                UInt32 aNumBytes, UInt32 aNumPackets,
+                const void *aData,
+                AudioStreamPacketDescription *aPackets)
+{
+  LOG("AppleATDecoder sample callback %u bytes %u packets",
+      aNumBytes, aNumPackets);
+  AppleATDecoder* decoder = static_cast<AppleATDecoder*>(aDecoder);
+  decoder->SampleCallback(aNumBytes, aNumPackets, aData, aPackets);
+}
+
+nsresult
+AppleATDecoder::Init()
+{
+  LOG("Initializing Apple AudioToolbox AAC decoder");
+  AudioFileTypeID fileType = kAudioFileAAC_ADTSType;
+  OSStatus rv = AudioFileStreamOpen(this,
+                                    _MetadataCallback,
+                                    _SampleCallback,
+                                    fileType,
+                                    &mStream);
+  if (rv) {
+    NS_ERROR("Couldn't open AudioFileStream");
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+AppleATDecoder::Input(mp4_demuxer::MP4Sample* aSample)
+{
+  LOG("mp4 input sample %p %lld us %lld pts%s %llu bytes audio",
+      aSample,
+      aSample->duration,
+      aSample->composition_timestamp,
+      aSample->is_sync_point ? " keyframe" : "",
+      (unsigned long long)aSample->size);
+
+  // Queue a task to perform the actual decoding on a separate thread.
+  mTaskQueue->Dispatch(
+      NS_NewRunnableMethodWithArg<nsAutoPtr<mp4_demuxer::MP4Sample>>(
+        this,
+        &AppleATDecoder::SubmitSample,
+        nsAutoPtr<mp4_demuxer::MP4Sample>(aSample)));
+
+  return NS_OK;
+}
+
+nsresult
+AppleATDecoder::Flush()
+{
+  LOG("Flushing AudioToolbox AAC decoder");
+  OSStatus rv = AudioConverterReset(mConverter);
+  if (rv) {
+    LOG("Error %d resetting AudioConverter", rv);
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
+nsresult
+AppleATDecoder::Drain()
+{
+  LOG("Draining AudioToolbox AAC decoder");
+  mTaskQueue->AwaitIdle();
+  return Flush();
+}
+
+nsresult
+AppleATDecoder::Shutdown()
+{
+  LOG("Shutdown: Apple AudioToolbox AAC decoder");
+  OSStatus rv1 = AudioConverterDispose(mConverter);
+  if (rv1) {
+    LOG("error %d disposing of AudioConverter", rv1);
+  } else {
+    mConverter = nullptr;
+  }
+
+  OSStatus rv2 = AudioFileStreamClose(mStream);
+  if (rv2) {
+    LOG("error %d closing AudioFileStream", rv2);
+  } else {
+    mStream = nullptr;
+  }
+
+  return (rv1 && rv2) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+void
+AppleATDecoder::MetadataCallback(AudioFileStreamID aFileStream,
+                                 AudioFileStreamPropertyID aPropertyID,
+                                 UInt32* aFlags)
+{
+  if (aPropertyID == kAudioFileStreamProperty_ReadyToProducePackets) {
+    SetupDecoder();
+  }
+}
+
+struct PassthroughUserData {
+  AppleATDecoder* mDecoder;
+  UInt32 mNumPackets;
+  UInt32 mDataSize;
+  const void *mData;
+  AudioStreamPacketDescription *mPacketDesc;
+  bool mDone;
+};
+
+// Error value we pass through the decoder to signal that nothing
+// has gone wrong during decoding, but more data is needed.
+const uint32_t kNeedMoreData = 'MOAR';
+
+static OSStatus
+_PassthroughInputDataCallback(AudioConverterRef aAudioConverter,
+                              UInt32 *aNumDataPackets /* in/out */,
+                              AudioBufferList *aData /* in/out */,
+                              AudioStreamPacketDescription **aPacketDesc,
+                              void *aUserData)
+{
+  PassthroughUserData *userData = (PassthroughUserData *)aUserData;
+  if (userData->mDone) {
+    // We make sure this callback is run _once_, with all the data we received
+    // from |AudioFileStreamParseBytes|. When we return an error, the decoder
+    // simply passes the return value on to the calling method,
+    // |SampleCallback|; and flushes all of the audio frames it had
+    // buffered. It does not change the decoder's state.
+    LOG("requested too much data; returning\n");
+    *aNumDataPackets = 0;
+    return kNeedMoreData;
+  }
+
+  userData->mDone = true;
+
+  LOG("AudioConverter wants %u packets of audio data\n", *aNumDataPackets);
+
+  *aNumDataPackets = userData->mNumPackets;
+  *aPacketDesc = userData->mPacketDesc;
+
+  aData->mBuffers[0].mNumberChannels = userData->mDecoder->mConfig.channel_count;
+  aData->mBuffers[0].mDataByteSize = userData->mDataSize;
+  aData->mBuffers[0].mData = const_cast<void *>(userData->mData);
+
+  return noErr;
+}
+
+void
+AppleATDecoder::SampleCallback(uint32_t aNumBytes,
+                               uint32_t aNumPackets,
+                               const void* aData,
+                               AudioStreamPacketDescription* aPackets)
+{
+  // Pick a multiple of the frame size close to a power of two
+  // for efficient allocation.
+  const uint32_t MAX_AUDIO_FRAMES = 128;
+  const uint32_t decodedSize = MAX_AUDIO_FRAMES * mConfig.channel_count *
+    sizeof(AudioDataValue);
+
+  // Descriptions for _decompressed_ audio packets. ignored.
+  nsAutoArrayPtr<AudioStreamPacketDescription>
+      packets(new AudioStreamPacketDescription[MAX_AUDIO_FRAMES]);
+
+  // This API insists on having packets spoon-fed to it from a callback.
+  // This structure exists only to pass our state and the result of the
+  // parser on to the callback above.
+  PassthroughUserData userData =
+      { this, aNumPackets, aNumBytes, aData, aPackets, false };
+
+  do {
+    // Decompressed audio buffer
+    nsAutoArrayPtr<uint8_t> decoded(new uint8_t[decodedSize]);
+
+    AudioBufferList decBuffer;
+    decBuffer.mNumberBuffers = 1;
+    decBuffer.mBuffers[0].mNumberChannels = mConfig.channel_count;
+    decBuffer.mBuffers[0].mDataByteSize = decodedSize;
+    decBuffer.mBuffers[0].mData = decoded.get();
+
+    // in: the max number of packets we can handle from the decoder.
+    // out: the number of packets the decoder is actually returning.
+    UInt32 numFrames = MAX_AUDIO_FRAMES;
+
+    OSStatus rv = AudioConverterFillComplexBuffer(mConverter,
+                                                  _PassthroughInputDataCallback,
+                                                  &userData,
+                                                  &numFrames /* in/out */,
+                                                  &decBuffer,
+                                                  packets.get());
+
+    if (rv && rv != kNeedMoreData) {
+      LOG("Error decoding audio stream: %#x\n", rv);
+      mCallback->Error();
+      break;
+    }
+    LOG("%d frames decoded", numFrames);
+
+    // If we decoded zero frames then AudioConverterFillComplexBuffer is out
+    // of data to provide.  We drained its internal buffer completely on the
+    // last pass.
+    if (numFrames == 0 && rv == kNeedMoreData) {
+      LOG("FillComplexBuffer out of data exactly\n");
+      mCallback->InputExhausted();
+      break;
+    }
+
+    const int rate = mConfig.samples_per_second;
+    int64_t time = FramesToUsecs(mCurrentAudioFrame, rate).value();
+    int64_t duration = FramesToUsecs(numFrames, rate).value();
+
+    LOG("pushed audio at time %lfs; duration %lfs\n",
+        (double)time / USECS_PER_S, (double)duration / USECS_PER_S);
+
+    AudioData *audio = new AudioData(mSamplePosition,
+                                     time, duration, numFrames,
+                                     reinterpret_cast<AudioDataValue *>(decoded.forget()),
+                                     rate);
+    mCallback->Output(audio);
+    mHaveOutput = true;
+
+    mCurrentAudioFrame += numFrames;
+
+    if (rv == kNeedMoreData) {
+      // No error; we just need more data.
+      LOG("FillComplexBuffer out of data\n");
+      mCallback->InputExhausted();
+      break;
+    }
+  } while (true);
+}
+
+void
+AppleATDecoder::SetupDecoder()
+{
+  AudioStreamBasicDescription inputFormat, outputFormat;
+  // Fill in the input format description from the stream.
+  AppleUtils::GetProperty(mStream,
+      kAudioFileStreamProperty_DataFormat, &inputFormat);
+
+  // Fill in the output format manually.
+  PodZero(&outputFormat);
+  outputFormat.mFormatID = kAudioFormatLinearPCM;
+  outputFormat.mSampleRate = inputFormat.mSampleRate;
+  outputFormat.mChannelsPerFrame = inputFormat.mChannelsPerFrame;
+#if defined(MOZ_SAMPLE_TYPE_FLOAT32)
+  outputFormat.mBitsPerChannel = 32;
+  outputFormat.mFormatFlags =
+    kLinearPCMFormatFlagIsFloat |
+    0;
+#else
+# error Unknown audio sample type
+#endif
+  // Set up the decoder so it gives us one sample per frame
+  outputFormat.mFramesPerPacket = 1;
+  outputFormat.mBytesPerPacket = outputFormat.mBytesPerFrame
+        = outputFormat.mChannelsPerFrame * outputFormat.mBitsPerChannel / 8;
+
+  OSStatus rv = AudioConverterNew(&inputFormat, &outputFormat, &mConverter);
+  if (rv) {
+    LOG("Error %d constructing AudioConverter", rv);
+    mConverter = nullptr;
+    mCallback->Error();
+  }
+  mHaveOutput = false;
+}
+
+void
+AppleATDecoder::SubmitSample(nsAutoPtr<mp4_demuxer::MP4Sample> aSample)
+{
+  mSamplePosition = aSample->byte_offset;
+  OSStatus rv = AudioFileStreamParseBytes(mStream,
+                                          aSample->size,
+                                          aSample->data,
+                                          0);
+  if (rv != noErr) {
+    LOG("Error %d parsing audio data", rv);
+    mCallback->Error();
+  }
+
+  // Sometimes we need multiple input samples before AudioToolbox
+  // starts decoding. If we haven't seen any output yet, ask for
+  // more data here.
+  if (!mHaveOutput) {
+    mCallback->InputExhausted();
+  }
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/AppleATDecoder.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_AppleATDecoder_h
+#define mozilla_AppleATDecoder_h
+
+#include <AudioToolbox/AudioToolbox.h>
+#include "PlatformDecoderModule.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/ReentrantMonitor.h"
+#include "nsIThread.h"
+
+namespace mozilla {
+
+class MediaTaskQueue;
+class MediaDataDecoderCallback;
+
+class AppleATDecoder : public MediaDataDecoder {
+public:
+  AppleATDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
+                 MediaTaskQueue* aVideoTaskQueue,
+                 MediaDataDecoderCallback* aCallback);
+  ~AppleATDecoder();
+
+  virtual nsresult Init() MOZ_OVERRIDE;
+  virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
+  virtual nsresult Flush() MOZ_OVERRIDE;
+  virtual nsresult Drain() MOZ_OVERRIDE;
+  virtual nsresult Shutdown() MOZ_OVERRIDE;
+
+
+  // Internal callbacks for the platform C api. Don't call externally.
+  void MetadataCallback(AudioFileStreamID aFileStream,
+                        AudioFileStreamPropertyID aPropertyID,
+                        UInt32* aFlags);
+  void SampleCallback(uint32_t aNumBytes,
+                      uint32_t aNumPackets,
+                      const void* aData,
+                      AudioStreamPacketDescription* aPackets);
+
+  // Callbacks also need access to the config.
+  const mp4_demuxer::AudioDecoderConfig& mConfig;
+
+private:
+  RefPtr<MediaTaskQueue> mTaskQueue;
+  MediaDataDecoderCallback* mCallback;
+  AudioConverterRef mConverter;
+  AudioFileStreamID mStream;
+  uint64_t mCurrentAudioFrame;
+  int64_t mSamplePosition;
+  bool mHaveOutput;
+
+  void SetupDecoder();
+  void SubmitSample(nsAutoPtr<mp4_demuxer::MP4Sample> aSample);
+};
+
+} // namespace mozilla
+
+#endif // mozilla_AppleATDecoder_h
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/AppleCMFunctions.h
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+// Construct references to each of the CoreMedia symbols we use.
+
+LINK_FUNC(CMVideoFormatDescriptionCreate)
+LINK_FUNC(CMBlockBufferCreateWithMemoryBlock)
+LINK_FUNC(CMSampleBufferCreate)
+LINK_FUNC(CMTimeMake)
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/AppleCMLinker.cpp
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 <dlfcn.h>
+
+#include "AppleCMLinker.h"
+#include "MainThreadUtils.h"
+#include "nsDebug.h"
+
+#ifdef PR_LOGGING
+PRLogModuleInfo* GetDemuxerLog();
+#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
+#else
+#define LOG(...)
+#endif
+
+namespace mozilla {
+
+AppleCMLinker::LinkStatus
+AppleCMLinker::sLinkStatus = LinkStatus_INIT;
+
+void* AppleCMLinker::sLink = nullptr;
+nsrefcnt AppleCMLinker::sRefCount = 0;
+
+#define LINK_FUNC(func) typeof(func) func;
+#include "AppleCMFunctions.h"
+#undef LINK_FUNC
+
+/* static */ bool
+AppleCMLinker::Link()
+{
+  // Bump our reference count every time we're called.
+  // Add a lock or change the thread assertion if
+  // you need to call this off the main thread.
+  MOZ_ASSERT(NS_IsMainThread());
+  ++sRefCount;
+
+  if (sLinkStatus) {
+    return sLinkStatus == LinkStatus_SUCCEEDED;
+  }
+
+  const char* dlname =
+    "/System/Library/Frameworks/CoreMedia.framework/CoreMedia";
+  if (!(sLink = dlopen(dlname, RTLD_NOW | RTLD_LOCAL))) {
+    NS_WARNING("Couldn't load CoreMedia framework");
+    goto fail;
+  }
+
+#define LINK_FUNC(func)                                        \
+  func = (typeof(func))dlsym(sLink, #func);                    \
+  if (!func) {                                                 \
+    NS_WARNING("Couldn't load CoreMedia function " #func ); \
+    goto fail;                                                 \
+  }
+#include "AppleCMFunctions.h"
+#undef LINK_FUNC
+
+  LOG("Loaded CoreMedia framework.");
+  sLinkStatus = LinkStatus_SUCCEEDED;
+  return true;
+
+fail:
+  Unlink();
+
+  sLinkStatus = LinkStatus_FAILED;
+  return false;
+}
+
+/* static */ void
+AppleCMLinker::Unlink()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(sLink && sRefCount > 0, "Unbalanced Unlink()");
+  --sRefCount;
+  if (sLink && sRefCount < 1) {
+    LOG("Unlinking CoreMedia framework.");
+    dlclose(sLink);
+    sLink = nullptr;
+  }
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/AppleCMLinker.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef AppleCMLinker_h
+#define AppleCMLinker_h
+
+extern "C" {
+#pragma GCC visibility push(default)
+#include <CoreMedia/CoreMedia.h>
+#pragma GCC visibility pop
+}
+
+#include "nscore.h"
+
+namespace mozilla {
+
+class AppleCMLinker
+{
+public:
+  static bool Link();
+  static void Unlink();
+
+private:
+  static void* sLink;
+  static nsrefcnt sRefCount;
+
+  static enum LinkStatus {
+    LinkStatus_INIT = 0,
+    LinkStatus_FAILED,
+    LinkStatus_SUCCEEDED
+  } sLinkStatus;
+};
+
+#define LINK_FUNC(func) extern typeof(func)* func;
+#include "AppleCMFunctions.h"
+#undef LINK_FUNC
+
+} // namespace mozilla
+
+#endif // AppleCMLinker_h
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/AppleDecoderModule.cpp
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 "AppleATDecoder.h"
+#include "AppleCMLinker.h"
+#include "AppleDecoderModule.h"
+#include "AppleVTDecoder.h"
+#include "AppleVTLinker.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/DebugOnly.h"
+
+namespace mozilla {
+
+bool AppleDecoderModule::sIsEnabled = false;
+
+AppleDecoderModule::AppleDecoderModule()
+{
+}
+
+AppleDecoderModule::~AppleDecoderModule()
+{
+}
+
+/* static */
+void
+AppleDecoderModule::Init()
+{
+  MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
+  sIsEnabled = Preferences::GetBool("media.apple.mp4.enabled", false);
+  if (!sIsEnabled) {
+    return;
+  }
+
+  // dlopen CoreMedia.framework if it's available.
+  sIsEnabled = AppleCMLinker::Link();
+  if (!sIsEnabled) {
+    return;
+  }
+
+  // dlopen VideoToolbox.framework if it's available.
+  sIsEnabled = AppleVTLinker::Link();
+}
+
+nsresult
+AppleDecoderModule::Startup()
+{
+  // We don't have any per-instance initialization to do.
+  // Check whether ::Init() above succeeded to know if
+  // we're functional.
+  if (!sIsEnabled) {
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
+nsresult
+AppleDecoderModule::Shutdown()
+{
+  MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
+  AppleVTLinker::Unlink();
+  AppleCMLinker::Unlink();
+
+  return NS_OK;
+}
+
+MediaDataDecoder*
+AppleDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
+                                      mozilla::layers::LayersBackend aLayersBackend,
+                                      mozilla::layers::ImageContainer* aImageContainer,
+                                      MediaTaskQueue* aVideoTaskQueue,
+                                      MediaDataDecoderCallback* aCallback)
+{
+  return new AppleVTDecoder(aConfig, aVideoTaskQueue, aCallback, aImageContainer);
+}
+
+MediaDataDecoder*
+AppleDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
+                                     MediaTaskQueue* aAudioTaskQueue,
+                                     MediaDataDecoderCallback* aCallback)
+{
+  return new AppleATDecoder(aConfig, aAudioTaskQueue, aCallback);
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/AppleDecoderModule.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_AppleDecoderModule_h
+#define mozilla_AppleDecoderModule_h
+
+#include "PlatformDecoderModule.h"
+
+namespace mozilla {
+
+class AppleDecoderModule : public PlatformDecoderModule {
+public:
+  AppleDecoderModule();
+  virtual ~AppleDecoderModule();
+
+  // Perform any per-instance initialization.
+  // Main thread only.
+  nsresult Startup();
+
+  // Called when the decoders have shutdown. Main thread only.
+  // Does this really need to be main thread only????
+  virtual nsresult Shutdown() MOZ_OVERRIDE;
+
+  // Decode thread.
+  virtual MediaDataDecoder*
+  CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
+                    mozilla::layers::LayersBackend aLayersBackend,
+                    mozilla::layers::ImageContainer* aImageContainer,
+                    MediaTaskQueue* aVideoTaskQueue,
+                    MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
+
+  // Decode thread.
+  virtual MediaDataDecoder* CreateAACDecoder(
+    const mp4_demuxer::AudioDecoderConfig& aConfig,
+    MediaTaskQueue* aAudioTaskQueue,
+    MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
+
+  static void Init();
+private:
+  static bool sIsEnabled;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_AppleDecoderModule_h
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/AppleUtils.cpp
@@ -0,0 +1,84 @@
+/* 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/. */
+
+// Utility functions to help with Apple API calls.
+
+#include <AudioToolbox/AudioToolbox.h>
+#include "AppleUtils.h"
+#include "prlog.h"
+
+#ifdef PR_LOGGING
+PRLogModuleInfo* GetDemuxerLog();
+#define WARN(...) PR_LOG(GetDemuxerLog(), PR_LOG_WARNING, (__VA_ARGS__))
+#else
+#define WARN(...)
+#endif
+
+#define PROPERTY_ID_FORMAT "%c%c%c%c"
+#define PROPERTY_ID_PRINT(x) ((x) >> 24), \
+                             ((x) >> 16) & 0xff, \
+                             ((x) >> 8) & 0xff, \
+                              (x) & 0xff
+
+namespace mozilla {
+
+nsresult
+AppleUtils::GetProperty(AudioFileStreamID aAudioFileStream,
+                        AudioFileStreamPropertyID aPropertyID,
+                        void *aData)
+{
+  UInt32 size;
+  Boolean writeable;
+  OSStatus rv = AudioFileStreamGetPropertyInfo(aAudioFileStream, aPropertyID,
+                                                             &size, &writeable);
+
+  if (rv) {
+    WARN("Couldn't get property " PROPERTY_ID_FORMAT "\n",
+         PROPERTY_ID_PRINT(aPropertyID));
+    return NS_ERROR_FAILURE;
+  }
+
+  rv = AudioFileStreamGetProperty(aAudioFileStream, aPropertyID,
+                                  &size, aData);
+
+  return NS_OK;
+}
+
+void
+AppleUtils::SetCFDict(CFMutableDictionaryRef dict,
+                      const char* key,
+                      const char* value)
+{
+  // We avoid using the CFSTR macros because there's no way to release those.
+  AutoCFRelease<CFStringRef> keyRef =
+    CFStringCreateWithCString(NULL, key, kCFStringEncodingUTF8);
+  AutoCFRelease<CFStringRef> valueRef =
+    CFStringCreateWithCString(NULL, value, kCFStringEncodingUTF8);
+  CFDictionarySetValue(dict, keyRef, valueRef);
+}
+
+void
+AppleUtils::SetCFDict(CFMutableDictionaryRef dict,
+                      const char* key,
+                      int32_t value)
+{
+  AutoCFRelease<CFNumberRef> valueRef =
+    CFNumberCreate(NULL, kCFNumberSInt32Type, &value);
+  AutoCFRelease<CFStringRef> keyRef =
+    CFStringCreateWithCString(NULL, key, kCFStringEncodingUTF8);
+  CFDictionarySetValue(dict, keyRef, valueRef);
+}
+
+void
+AppleUtils::SetCFDict(CFMutableDictionaryRef dict,
+                      const char* key,
+                      bool value)
+{
+  AutoCFRelease<CFStringRef> keyRef =
+    CFStringCreateWithCString(NULL, key, kCFStringEncodingUTF8);
+  CFDictionarySetValue(dict, keyRef, value ? kCFBooleanTrue : kCFBooleanFalse);
+}
+
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/AppleUtils.h
@@ -0,0 +1,66 @@
+/* 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/. */
+
+// Utility functions to help with Apple API calls.
+
+#ifndef mozilla_AppleUtils_h
+#define mozilla_AppleUtils_h
+
+#include <AudioToolbox/AudioToolbox.h>
+#include "nsError.h"
+
+namespace mozilla {
+
+struct AppleUtils {
+  // Helper to retrieve properties from AudioFileStream objects.
+  static nsresult GetProperty(AudioFileStreamID aAudioFileStream,
+                              AudioFileStreamPropertyID aPropertyID,
+                              void *aData);
+
+  // Helper to set a string, string pair on a CFMutableDictionaryRef.
+  static void SetCFDict(CFMutableDictionaryRef dict,
+                        const char* key,
+                        const char* value);
+  // Helper to set a string, int32_t pair on a CFMutableDictionaryRef.
+  static void SetCFDict(CFMutableDictionaryRef dict,
+                        const char* key,
+                        int32_t value);
+  // Helper to set a string, bool pair on a CFMutableDictionaryRef.
+  static void SetCFDict(CFMutableDictionaryRef dict,
+                        const char* key,
+                        bool value);
+};
+
+// Wrapper class to call CFRelease on reference types
+// when they go out of scope.
+template <class T>
+class AutoCFRelease {
+public:
+  AutoCFRelease(T aRef)
+    : mRef(aRef)
+  {
+  }
+  ~AutoCFRelease()
+  {
+    if (mRef) {
+      CFRelease(mRef);
+    }
+  }
+  // Return the wrapped ref so it can be used as an in parameter.
+  operator T()
+  {
+    return mRef;
+  }
+  // Return a pointer to the wrapped ref for use as an out parameter.
+  T* receive()
+  {
+    return &mRef;
+  }
+private:
+  T mRef;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_AppleUtils_h
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/AppleVTDecoder.cpp
@@ -0,0 +1,427 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 <CoreFoundation/CFString.h>
+
+#include "AppleUtils.h"
+#include "mozilla/SHA1.h"
+#include "mp4_demuxer/DecoderData.h"
+#include "MP4Reader.h"
+#include "MP4Decoder.h"
+#include "nsAutoPtr.h"
+#include "nsThreadUtils.h"
+#include "AppleCMLinker.h"
+#include "AppleVTDecoder.h"
+#include "AppleVTLinker.h"
+#include "prlog.h"
+#include "MediaData.h"
+#include "VideoUtils.h"
+
+#ifdef PR_LOGGING
+PRLogModuleInfo* GetDemuxerLog();
+#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
+#define LOG_MEDIA_SHA1
+#else
+#define LOG(...)
+#endif
+
+namespace mozilla {
+
+AppleVTDecoder::AppleVTDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
+                               MediaTaskQueue* aVideoTaskQueue,
+                               MediaDataDecoderCallback* aCallback,
+                               layers::ImageContainer* aImageContainer)
+  : mConfig(aConfig)
+  , mTaskQueue(aVideoTaskQueue)
+  , mCallback(aCallback)
+  , mImageContainer(aImageContainer)
+  , mFormat(nullptr)
+  , mSession(nullptr)
+{
+  MOZ_COUNT_CTOR(AppleVTDecoder);
+  // TODO: Verify aConfig.mime_type.
+  LOG("Creating AppleVTDecoder for %dx%d h.264 video",
+      mConfig.display_width,
+      mConfig.display_height
+     );
+}
+
+AppleVTDecoder::~AppleVTDecoder()
+{
+  MOZ_COUNT_DTOR(AppleVTDecoder);
+}
+
+nsresult
+AppleVTDecoder::Init()
+{
+  nsresult rv = InitializeSession();
+  return rv;
+}
+
+nsresult
+AppleVTDecoder::Shutdown()
+{
+  if (mSession) {
+    LOG("%s: cleaning up session %p", __func__, mSession);
+    VTDecompressionSessionInvalidate(mSession);
+    CFRelease(mSession);
+    mSession = nullptr;
+  }
+  if (mFormat) {
+    LOG("%s: releasing format %p", __func__, mFormat);
+    CFRelease(mFormat);
+    mFormat = nullptr;
+  }
+  return NS_OK;
+}
+
+nsresult
+AppleVTDecoder::Input(mp4_demuxer::MP4Sample* aSample)
+{
+  LOG("mp4 input sample %p pts %lld duration %lld us%s %d bytes",
+      aSample,
+      aSample->composition_timestamp,
+      aSample->duration,
+      aSample->is_sync_point ? " keyframe" : "",
+      aSample->size);
+
+#ifdef LOG_MEDIA_SHA1
+  SHA1Sum hash;
+  hash.update(aSample->data, aSample->size);
+  uint8_t digest_buf[SHA1Sum::kHashSize];
+  hash.finish(digest_buf);
+  nsAutoCString digest;
+  for (size_t i = 0; i < sizeof(digest_buf); i++) {
+    digest.AppendPrintf("%02x", digest_buf[i]);
+  }
+  LOG("    sha1 %s", digest.get());
+#endif // LOG_MEDIA_SHA1
+
+  mTaskQueue->Dispatch(
+      NS_NewRunnableMethodWithArg<nsAutoPtr<mp4_demuxer::MP4Sample>>(
+          this,
+          &AppleVTDecoder::SubmitFrame,
+          nsAutoPtr<mp4_demuxer::MP4Sample>(aSample)));
+  return NS_OK;
+}
+
+nsresult
+AppleVTDecoder::Flush()
+{
+  mReorderQueue.Clear();
+  return Drain();
+}
+
+nsresult
+AppleVTDecoder::Drain()
+{
+  OSStatus rv = VTDecompressionSessionWaitForAsynchronousFrames(mSession);
+  if (rv != noErr) {
+    LOG("Error %d draining frames", rv);
+    return NS_ERROR_FAILURE;
+  }
+  return DrainReorderedFrames();
+}
+
+//
+// Implementation details.
+//
+
+// Context object to hold a copy of sample metadata.
+class FrameRef {
+public:
+  Microseconds timestamp;
+  Microseconds duration;
+  int64_t byte_offset;
+  bool is_sync_point;
+
+  explicit FrameRef(mp4_demuxer::MP4Sample* aSample)
+  {
+    MOZ_ASSERT(aSample);
+    timestamp = aSample->composition_timestamp;
+    duration = aSample->duration;
+    byte_offset = aSample->byte_offset;
+    is_sync_point = aSample->is_sync_point;
+  }
+};
+
+// Callback passed to the VideoToolbox decoder for returning data.
+// This needs to be static because the API takes a C-style pair of
+// function and userdata pointers. This validates parameters and
+// forwards the decoded image back to an object method.
+static void
+PlatformCallback(void* decompressionOutputRefCon,
+                 void* sourceFrameRefCon,
+                 OSStatus status,
+                 VTDecodeInfoFlags flags,
+                 CVImageBufferRef image,
+                 CMTime presentationTimeStamp,
+                 CMTime presentationDuration)
+{
+  LOG("AppleVideoDecoder %s status %d flags %d", __func__, status, flags);
+
+  AppleVTDecoder* decoder =
+    static_cast<AppleVTDecoder*>(decompressionOutputRefCon);
+  nsAutoPtr<FrameRef> frameRef =
+    nsAutoPtr<FrameRef>(static_cast<FrameRef*>(sourceFrameRefCon));
+
+  LOG("mp4 output frame %lld pts %lld duration %lld us%s",
+    frameRef->byte_offset,
+    frameRef->timestamp,
+    frameRef->duration,
+    frameRef->is_sync_point ? " keyframe" : ""
+  );
+
+  // Validate our arguments.
+  if (status != noErr || !image) {
+    NS_WARNING("VideoToolbox decoder returned no data");
+    return;
+  }
+  if (flags & kVTDecodeInfo_FrameDropped) {
+    NS_WARNING("  ...frame dropped...");
+  }
+  MOZ_ASSERT(CFGetTypeID(image) == CVPixelBufferGetTypeID(),
+    "VideoToolbox returned an unexpected image type");
+
+  // Forward the data back to an object method which can access
+  // the correct MP4Reader callback.
+  decoder->OutputFrame(image, frameRef);
+}
+
+nsresult
+AppleVTDecoder::DrainReorderedFrames()
+{
+  while (!mReorderQueue.IsEmpty()) {
+    mCallback->Output(mReorderQueue.Pop());
+  }
+  return NS_OK;
+}
+
+// Copy and return a decoded frame.
+nsresult
+AppleVTDecoder::OutputFrame(CVPixelBufferRef aImage,
+                            nsAutoPtr<FrameRef> aFrameRef)
+{
+  size_t width = CVPixelBufferGetWidth(aImage);
+  size_t height = CVPixelBufferGetHeight(aImage);
+  LOG("  got decoded frame data... %ux%u %s", width, height,
+      CVPixelBufferIsPlanar(aImage) ? "planar" : "chunked");
+#ifdef DEBUG
+  size_t planes = CVPixelBufferGetPlaneCount(aImage);
+  for (size_t i = 0; i < planes; ++i) {
+    size_t stride = CVPixelBufferGetBytesPerRowOfPlane(aImage, i);
+    LOG("     plane %u %ux%u rowbytes %u",
+        (unsigned)i,
+        CVPixelBufferGetWidthOfPlane(aImage, i),
+        CVPixelBufferGetHeightOfPlane(aImage, i),
+        (unsigned)stride);
+  }
+  MOZ_ASSERT(planes == 2);
+#endif // DEBUG
+
+  VideoData::YCbCrBuffer buffer;
+
+  // Lock the returned image data.
+  CVReturn rv = CVPixelBufferLockBaseAddress(aImage, kCVPixelBufferLock_ReadOnly);
+  if (rv != kCVReturnSuccess) {
+    NS_ERROR("error locking pixel data");
+    mCallback->Error();
+    return NS_ERROR_FAILURE;
+  }
+  // Y plane.
+  buffer.mPlanes[0].mData =
+    static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 0));
+  buffer.mPlanes[0].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 0);
+  buffer.mPlanes[0].mWidth = width;
+  buffer.mPlanes[0].mHeight = height;
+  buffer.mPlanes[0].mOffset = 0;
+  buffer.mPlanes[0].mSkip = 0;
+  // Cb plane.
+  buffer.mPlanes[1].mData =
+    static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 1));
+  buffer.mPlanes[1].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 1);
+  buffer.mPlanes[1].mWidth = (width+1) / 2;
+  buffer.mPlanes[1].mHeight = (height+1) / 2;
+  buffer.mPlanes[1].mOffset = 0;
+  buffer.mPlanes[1].mSkip = 1;
+  // Cr plane.
+  buffer.mPlanes[2].mData =
+    static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 1));
+  buffer.mPlanes[2].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 1);
+  buffer.mPlanes[2].mWidth = (width+1) / 2;
+  buffer.mPlanes[2].mHeight = (height+1) / 2;
+  buffer.mPlanes[2].mOffset = 1;
+  buffer.mPlanes[2].mSkip = 1;
+
+  // Bounds.
+  VideoInfo info;
+  info.mDisplay = nsIntSize(width, height);
+  info.mHasVideo = true;
+  gfx::IntRect visible = gfx::IntRect(0,
+                                      0,
+                                      mConfig.display_width,
+                                      mConfig.display_height);
+
+  // Copy the image data into our own format.
+  nsAutoPtr<VideoData> data;
+  data =
+    VideoData::Create(info,
+                      mImageContainer,
+                      nullptr,
+                      aFrameRef->byte_offset,
+                      aFrameRef->timestamp,
+                      aFrameRef->duration,
+                      buffer,
+                      aFrameRef->is_sync_point,
+                      aFrameRef->timestamp,
+                      visible);
+  // Unlock the returned image data.
+  CVPixelBufferUnlockBaseAddress(aImage, kCVPixelBufferLock_ReadOnly);
+
+  // Frames come out in DTS order but we need to output them
+  // in composition order.
+  mReorderQueue.Push(data.forget());
+  if (mReorderQueue.Length() > 2) {
+    VideoData* readyData = mReorderQueue.Pop();
+    mCallback->Output(readyData);
+  }
+
+  return NS_OK;
+}
+
+// Helper to fill in a timestamp structure.
+static CMSampleTimingInfo
+TimingInfoFromSample(mp4_demuxer::MP4Sample* aSample)
+{
+  CMSampleTimingInfo timestamp;
+
+  timestamp.duration = CMTimeMake(aSample->duration, USECS_PER_S);
+  timestamp.presentationTimeStamp =
+    CMTimeMake(aSample->composition_timestamp, USECS_PER_S);
+  // No DTS value available from libstagefright.
+  timestamp.decodeTimeStamp = CMTimeMake(0, USECS_PER_S);
+
+  return timestamp;
+}
+
+nsresult
+AppleVTDecoder::SubmitFrame(mp4_demuxer::MP4Sample* aSample)
+{
+  // For some reason this gives me a double-free error with stagefright.
+  AutoCFRelease<CMBlockBufferRef> block = nullptr;
+  AutoCFRelease<CMSampleBufferRef> sample = nullptr;
+  VTDecodeInfoFlags flags;
+  OSStatus rv;
+
+  // FIXME: This copies the sample data. I think we can provide
+  // a custom block source which reuses the aSample buffer.
+  // But note that there may be a problem keeping the samples
+  // alive over multiple frames.
+  rv = CMBlockBufferCreateWithMemoryBlock(NULL // Struct allocator.
+                                         ,aSample->data
+                                         ,aSample->size
+                                         ,kCFAllocatorNull // Block allocator.
+                                         ,NULL // Block source.
+                                         ,0    // Data offset.
+                                         ,aSample->size
+                                         ,false
+                                         ,block.receive());
+  NS_ASSERTION(rv == noErr, "Couldn't create CMBlockBuffer");
+  CMSampleTimingInfo timestamp = TimingInfoFromSample(aSample);
+  rv = CMSampleBufferCreate(NULL, block, true, 0, 0, mFormat, 1, 1, &timestamp, 0, NULL, sample.receive());
+  NS_ASSERTION(rv == noErr, "Couldn't create CMSampleBuffer");
+  rv = VTDecompressionSessionDecodeFrame(mSession,
+                                         sample,
+                                         0,
+                                         new FrameRef(aSample),
+                                         &flags);
+  NS_ASSERTION(rv == noErr, "Couldn't pass frame to decoder");
+
+  // Ask for more data.
+  if (mTaskQueue->IsEmpty()) {
+    LOG("AppleVTDecoder task queue empty; requesting more data");
+    mCallback->InputExhausted();
+  }
+
+  return NS_OK;
+}
+
+nsresult
+AppleVTDecoder::InitializeSession()
+{
+  OSStatus rv;
+  AutoCFRelease<CFMutableDictionaryRef> extensions =
+    CFDictionaryCreateMutable(NULL, 0,
+                              &kCFTypeDictionaryKeyCallBacks,
+                              &kCFTypeDictionaryValueCallBacks);
+  AppleUtils::SetCFDict(extensions, "CVImageBufferChromaLocationBottomField", "left");
+  AppleUtils::SetCFDict(extensions, "CVImageBufferChromaLocationTopField", "left");
+  AppleUtils::SetCFDict(extensions, "FullRangeVideo", true);
+
+  AutoCFRelease<CFMutableDictionaryRef> atoms =
+    CFDictionaryCreateMutable(NULL, 0,
+                              &kCFTypeDictionaryKeyCallBacks,
+                              &kCFTypeDictionaryValueCallBacks);
+  AutoCFRelease<CFDataRef> avc_data = CFDataCreate(NULL,
+      mConfig.extra_data.begin(), mConfig.extra_data.length());
+
+#ifdef LOG_MEDIA_SHA1
+  SHA1Sum avc_hash;
+  avc_hash.update(mConfig.extra_data.begin(), mConfig.extra_data.length());
+  uint8_t digest_buf[SHA1Sum::kHashSize];
+  avc_hash.finish(digest_buf);
+  nsAutoCString avc_digest;
+  for (size_t i = 0; i < sizeof(digest_buf); i++) {
+    avc_digest.AppendPrintf("%02x", digest_buf[i]);
+  }
+  LOG("AVCDecoderConfig %ld bytes sha1 %s",
+      mConfig.extra_data.length(), avc_digest.get());
+#endif // LOG_MEDIA_SHA1
+
+  CFDictionarySetValue(atoms, CFSTR("avcC"), avc_data);
+  CFDictionarySetValue(extensions, CFSTR("SampleDescriptionExtensionAtoms"), atoms);
+  rv = CMVideoFormatDescriptionCreate(NULL, // Use default allocator.
+                                      kCMVideoCodecType_H264,
+                                      mConfig.display_width,
+                                      mConfig.display_height,
+                                      extensions,
+                                      &mFormat);
+  if (rv != noErr) {
+    NS_ERROR("Couldn't create format description!");
+    return NS_ERROR_FAILURE;
+  }
+
+  // Contruct video decoder selection spec.
+  AutoCFRelease<CFMutableDictionaryRef> spec =
+    CFDictionaryCreateMutable(NULL, 0,
+                              &kCFTypeDictionaryKeyCallBacks,
+                              &kCFTypeDictionaryValueCallBacks);
+  // This key is supported (or ignored) but not declared prior to OSX 10.9.
+  AutoCFRelease<CFStringRef>
+        kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder =
+        CFStringCreateWithCString(NULL, "EnableHardwareAcceleratedVideoDecoder",
+            kCFStringEncodingUTF8);
+
+  CFDictionarySetValue(spec,
+      kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder,
+      kCFBooleanTrue);
+
+  VTDecompressionOutputCallbackRecord cb = { PlatformCallback, this };
+  rv = VTDecompressionSessionCreate(NULL, // Allocator.
+                                    mFormat,
+                                    spec, // Video decoder selection.
+                                    NULL, // Output video format.
+                                    &cb,
+                                    &mSession);
+  if (rv != noErr) {
+    NS_ERROR("Couldn't create decompression session!");
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/AppleVTDecoder.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_AppleVTDecoder_h
+#define mozilla_AppleVTDecoder_h
+
+#include "PlatformDecoderModule.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/ReentrantMonitor.h"
+#include "nsIThread.h"
+#include "ReorderQueue.h"
+
+#include "VideoToolbox/VideoToolbox.h"
+
+namespace mozilla {
+
+class MediaTaskQueue;
+class MediaDataDecoderCallback;
+namespace layers {
+  class ImageContainer;
+}
+class FrameRef;
+
+class AppleVTDecoder : public MediaDataDecoder {
+public:
+  AppleVTDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
+                 MediaTaskQueue* aVideoTaskQueue,
+                 MediaDataDecoderCallback* aCallback,
+                 layers::ImageContainer* aImageContainer);
+  ~AppleVTDecoder();
+  virtual nsresult Init() MOZ_OVERRIDE;
+  virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
+  virtual nsresult Flush() MOZ_OVERRIDE;
+  virtual nsresult Drain() MOZ_OVERRIDE;
+  virtual nsresult Shutdown() MOZ_OVERRIDE;
+  // Return hook for VideoToolbox callback.
+  nsresult OutputFrame(CVPixelBufferRef aImage,
+                       nsAutoPtr<FrameRef> frameRef);
+private:
+  const mp4_demuxer::VideoDecoderConfig& mConfig;
+  RefPtr<MediaTaskQueue> mTaskQueue;
+  MediaDataDecoderCallback* mCallback;
+  layers::ImageContainer* mImageContainer;
+  CMVideoFormatDescriptionRef mFormat;
+  VTDecompressionSessionRef mSession;
+  ReorderQueue mReorderQueue;
+
+  // Method to pass a frame to VideoToolbox for decoding.
+  nsresult SubmitFrame(mp4_demuxer::MP4Sample* aSample);
+  // Method to set up the decompression session.
+  nsresult InitializeSession();
+  nsresult DrainReorderedFrames();
+};
+
+} // namespace mozilla
+
+#endif // mozilla_AppleVTDecoder_h
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/AppleVTFunctions.h
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+// Construct references to each of the VideoToolbox symbols we use.
+
+LINK_FUNC(VTDecompressionSessionCreate)
+LINK_FUNC(VTDecompressionSessionDecodeFrame)
+LINK_FUNC(VTDecompressionSessionInvalidate)
+LINK_FUNC(VTDecompressionSessionWaitForAsynchronousFrames)
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/AppleVTLinker.cpp
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 <dlfcn.h>
+
+#include "AppleVTLinker.h"
+#include "MainThreadUtils.h"
+#include "nsDebug.h"
+
+#ifdef PR_LOGGING
+PRLogModuleInfo* GetDemuxerLog();
+#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
+#else
+#define LOG(...)
+#endif
+
+namespace mozilla {
+
+AppleVTLinker::LinkStatus
+AppleVTLinker::sLinkStatus = LinkStatus_INIT;
+
+void* AppleVTLinker::sLink = nullptr;
+nsrefcnt AppleVTLinker::sRefCount = 0;
+
+#define LINK_FUNC(func) typeof(func) func;
+#include "AppleVTFunctions.h"
+#undef LINK_FUNC
+
+/* static */ bool
+AppleVTLinker::Link()
+{
+  // Bump our reference count every time we're called.
+  // Add a lock or change the thread assertion if
+  // you need to call this off the main thread.
+  MOZ_ASSERT(NS_IsMainThread());
+  ++sRefCount;
+
+  if (sLinkStatus) {
+    return sLinkStatus == LinkStatus_SUCCEEDED;
+  }
+
+  const char* dlname =
+    "/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox";
+  if (!(sLink = dlopen(dlname, RTLD_NOW | RTLD_LOCAL))) {
+    NS_WARNING("Couldn't load VideoToolbox framework");
+    goto fail;
+  }
+
+#define LINK_FUNC(func)                                        \
+  func = (typeof(func))dlsym(sLink, #func);                    \
+  if (!func) {                                                 \
+    NS_WARNING("Couldn't load VideoToolbox function " #func ); \
+    goto fail;                                                 \
+  }
+#include "AppleVTFunctions.h"
+#undef LINK_FUNC
+
+  LOG("Loaded VideoToolbox framework.");
+  sLinkStatus = LinkStatus_SUCCEEDED;
+  return true;
+
+fail:
+  Unlink();
+
+  sLinkStatus = LinkStatus_FAILED;
+  return false;
+}
+
+/* static */ void
+AppleVTLinker::Unlink()
+{
+  // We'll be called by multiple Decoders, one intantiated for
+  // each media element. Therefore we receive must maintain a
+  // reference count to avoidunloading our symbols when other
+  // instances still need them.
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(sLink && sRefCount > 0, "Unbalanced Unlink()");
+  --sRefCount;
+  if (sLink && sRefCount < 1) {
+    LOG("Unlinking VideoToolbox framework.");
+    dlclose(sLink);
+    sLink = nullptr;
+  }
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/AppleVTLinker.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef AppleVTLinker_h
+#define AppleVTLinker_h
+
+extern "C" {
+#pragma GCC visibility push(default)
+#include "VideoToolbox/VideoToolbox.h"
+#pragma GCC visibility pop
+}
+
+#include "nscore.h"
+
+namespace mozilla {
+
+class AppleVTLinker
+{
+public:
+  static bool Link();
+  static void Unlink();
+
+private:
+  static void* sLink;
+  static nsrefcnt sRefCount;
+
+  static enum LinkStatus {
+    LinkStatus_INIT = 0,
+    LinkStatus_FAILED,
+    LinkStatus_SUCCEEDED
+  } sLinkStatus;
+};
+
+#define LINK_FUNC(func) extern typeof(func)* func;
+#include "AppleVTFunctions.h"
+#undef LINK_FUNC
+
+} // namespace mozilla
+
+#endif // AppleVTLinker_h
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/ReorderQueue.h
@@ -0,0 +1,29 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Queue for ordering decoded video frames by presentation time.
+// Decoders often return frames out of order, which we need to
+// buffer so we can forward them in correct presentation order.
+
+#ifndef mozilla_ReorderQueue_h
+#define mozilla_ReorderQueue_h
+
+#include <MediaData.h>
+#include <nsTPriorityQueue.h>
+
+namespace mozilla {
+
+struct ReorderQueueComparator
+{
+  bool LessThan(VideoData* const& a, VideoData* const& b) const
+  {
+    return a->mTime < b->mTime;
+  }
+};
+
+typedef nsTPriorityQueue<VideoData*, ReorderQueueComparator> ReorderQueue;
+
+} // namespace mozilla
+
+#endif // mozilla_ReorderQueue_h
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/apple/VideoToolbox/VideoToolbox.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+// Stub header for VideoToolbox framework API.
+// We include our own copy so we can build on MacOS versions
+// where it's not available.
+
+#ifndef mozilla_VideoToolbox_VideoToolbox_h
+#define mozilla_VideoToolbox_VideoToolbox_h
+
+// CoreMedia is available starting in OS X 10.7,
+// so we need to dlopen it as well to run on 10.6,
+// but we can depend on the real framework headers at build time.
+
+#include <CoreMedia/CMBase.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreVideo/CVPixelBuffer.h>
+#include <CoreMedia/CMSampleBuffer.h>
+#include <CoreMedia/CMFormatDescription.h>
+#include <CoreMedia/CMTime.h>
+
+typedef uint32_t VTDecodeFrameFlags;
+typedef uint32_t VTDecodeInfoFlags;
+enum {
+  kVTDecodeInfo_Asynchronous = 1UL << 0,
+  kVTDecodeInfo_FrameDropped = 1UL << 1,
+};
+
+typedef struct OpaqueVTDecompressionSession* VTDecompressionSessionRef;
+typedef void (*VTDecompressionOutputCallback)(
+    void*,
+    void*,
+    OSStatus,
+    VTDecodeInfoFlags,
+    CVImageBufferRef,
+    CMTime,
+    CMTime
+);
+typedef struct VTDecompressionOutputCallbackRecord {
+    VTDecompressionOutputCallback decompressionOutputCallback;
+    void*                         decompressionOutputRefCon;
+} VTDecompressionOutputCallbackRecord;
+
+OSStatus
+VTDecompressionSessionCreate(
+    CFAllocatorRef,
+    CMVideoFormatDescriptionRef,
+    CFDictionaryRef,
+    CFDictionaryRef,
+    const VTDecompressionOutputCallbackRecord*,
+    VTDecompressionSessionRef*
+);
+
+OSStatus
+VTDecompressionSessionDecodeFrame(
+    VTDecompressionSessionRef,
+    CMSampleBufferRef,
+    VTDecodeFrameFlags,
+    void*,
+    VTDecodeInfoFlags*
+);
+
+OSStatus
+VTDecompressionSessionWaitForAsynchronousFrames(
+    VTDecompressionSessionRef
+);
+
+void
+VTDecompressionSessionInvalidate(
+    VTDecompressionSessionRef
+);
+
+#endif // mozilla_VideoToolbox_VideoToolbox_h
--- a/content/media/fmp4/moz.build
+++ b/content/media/fmp4/moz.build
@@ -37,11 +37,27 @@ if CONFIG['MOZ_FFMPEG']:
         'ffmpeg/libav53',
         'ffmpeg/libav54',
         'ffmpeg/libav55',
     ]
     LOCAL_INCLUDES += [
         'ffmpeg',
     ]
 
+if CONFIG['MOZ_APPLEMEDIA']:
+  EXPORTS += [
+      'apple/AppleDecoderModule.h',
+  ]
+  UNIFIED_SOURCES += [
+      'apple/AppleATDecoder.cpp',
+      'apple/AppleCMLinker.cpp',
+      'apple/AppleDecoderModule.cpp',
+      'apple/AppleUtils.cpp',
+      'apple/AppleVTDecoder.cpp',
+      'apple/AppleVTLinker.cpp',
+  ]
+  LDFLAGS += [
+      '-framework AudioToolbox',
+  ]
+
 FINAL_LIBRARY = 'xul'
 
 FAIL_ON_WARNINGS = True
--- a/content/media/gmp/GMPChild.cpp
+++ b/content/media/gmp/GMPChild.cpp
@@ -21,18 +21,16 @@ using mozilla::dom::CrashReporterChild;
 #include <stdlib.h> // for _exit()
 #else
 #include <unistd.h> // for _exit()
 #endif
 
 #if defined(XP_WIN)
 #define TARGET_SANDBOX_EXPORTS
 #include "mozilla/sandboxTarget.h"
-#elif defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
-#include "mozilla/Sandbox.h"
 #endif
 
 namespace mozilla {
 namespace gmp {
 
 GMPChild::GMPChild()
   : mLib(nullptr)
   , mGetAPIFunc(nullptr)
@@ -95,23 +93,16 @@ GMPChild::LoadPluginLibrary(const std::s
   nsAutoString binaryName =                            baseName + NS_LITERAL_STRING(".dll");
 #else
 #error not defined
 #endif
   libFile->AppendRelativePath(binaryName);
 
   nsAutoCString nativePath;
   libFile->GetNativePath(nativePath);
-
-#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
-  // Enable sandboxing here -- we know the plugin file's path, but
-  // this process's execution hasn't been affected by its content yet.
-  mozilla::SetMediaPluginSandbox(nativePath.get());
-#endif
-
   mLib = PR_LoadLibrary(nativePath.get());
   if (!mLib) {
     return false;
   }
 
   GMPInitFunc initFunc = reinterpret_cast<GMPInitFunc>(PR_FindFunctionSymbol(mLib, "GMPInit"));
   if (!initFunc) {
     return false;
--- a/content/media/webaudio/AudioDestinationNode.cpp
+++ b/content/media/webaudio/AudioDestinationNode.cpp
@@ -324,17 +324,16 @@ AudioDestinationNode::AudioDestinationNo
                             MediaStreamGraph::CreateNonRealtimeInstance(aSampleRate) :
                             MediaStreamGraph::GetInstance();
   AudioNodeEngine* engine = aIsOffline ?
                             new OfflineDestinationNodeEngine(this, aNumberOfChannels,
                                                              aLength, aSampleRate) :
                             static_cast<AudioNodeEngine*>(new DestinationNodeEngine(this));
 
   mStream = graph->CreateAudioNodeStream(engine, MediaStreamGraph::EXTERNAL_STREAM);
-  mStream->SetAudioChannelType(aChannel);
   mStream->AddMainThreadListener(this);
   mStream->AddAudioOutput(&gWebAudioOutputKey);
 
   if (aChannel != AudioChannel::Normal) {
     ErrorResult rv;
     SetMozAudioChannelType(aChannel, rv);
   }
 }
@@ -534,16 +533,20 @@ AudioDestinationNode::SetMozAudioChannel
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   if (aValue != mAudioChannel &&
       CheckAudioChannelPermissions(aValue)) {
     mAudioChannel = aValue;
 
+    if (mStream) {
+      mStream->SetAudioChannelType(mAudioChannel);
+    }
+
     if (mAudioChannelAgent) {
       CreateAudioChannelAgent();
     }
   }
 }
 
 bool
 AudioDestinationNode::CheckAudioChannelPermissions(AudioChannel aValue)
--- a/content/svg/content/src/SVGSVGElement.cpp
+++ b/content/svg/content/src/SVGSVGElement.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdint.h>
 #include "mozilla/ArrayUtils.h"
-#include "mozilla/BasicEvents.h"
+#include "mozilla/ContentEvents.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/Likely.h"
 
 #include "nsGkAtoms.h"
 #include "nsLayoutUtils.h"
 #include "nsLayoutStylesheetCache.h"
 #include "DOMSVGNumber.h"
 #include "DOMSVGLength.h"
@@ -513,21 +513,24 @@ SVGSVGElement::SetCurrentScaleTranslate(
   mCurrentScale = s;
   mCurrentTranslate = SVGPoint(x, y);
 
   // now dispatch the appropriate event if we are the root element
   nsIDocument* doc = GetCurrentDoc();
   if (doc) {
     nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
     if (presShell && IsRoot()) {
-      bool scaling = (mPreviousScale != mCurrentScale);
       nsEventStatus status = nsEventStatus_eIgnore;
-      WidgetGUIEvent event(true, scaling ? NS_SVG_ZOOM : NS_SVG_SCROLL, 0);
-      event.eventStructType = scaling ? NS_SVGZOOM_EVENT : NS_EVENT;
-      presShell->HandleDOMEventWithTarget(this, &event, &status);
+      if (mPreviousScale != mCurrentScale) {
+        InternalSVGZoomEvent svgZoomEvent(true, NS_SVG_ZOOM);
+        presShell->HandleDOMEventWithTarget(this, &svgZoomEvent, &status);
+      } else {
+        WidgetEvent svgScrollEvent(true, NS_SVG_SCROLL);
+        presShell->HandleDOMEventWithTarget(this, &svgScrollEvent, &status);
+      }
       InvalidateTransformNotifyFrame();
     }
   }
 }
 
 void
 SVGSVGElement::SetCurrentTranslate(float x, float y)
 {
--- a/content/svg/content/src/SVGZoomEvent.cpp
+++ b/content/svg/content/src/SVGZoomEvent.cpp
@@ -1,19 +1,20 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/dom/SVGZoomEvent.h"
 #include "DOMSVGPoint.h"
+#include "mozilla/ContentEvents.h"
+#include "mozilla/dom/Element.h"
 #include "mozilla/dom/SVGSVGElement.h"
-#include "nsIPresShell.h"
+#include "mozilla/dom/SVGZoomEvent.h"
 #include "nsIDocument.h"
-#include "mozilla/dom/Element.h"
+#include "nsIPresShell.h"
 #include "prtime.h"
 
 namespace mozilla {
 namespace dom {
 
 //----------------------------------------------------------------------
 // Implementation
 
@@ -22,33 +23,30 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(SVGZo
 NS_IMPL_ADDREF_INHERITED(SVGZoomEvent, UIEvent)
 NS_IMPL_RELEASE_INHERITED(SVGZoomEvent, UIEvent)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SVGZoomEvent)
 NS_INTERFACE_MAP_END_INHERITING(UIEvent)
 
 SVGZoomEvent::SVGZoomEvent(EventTarget* aOwner,
                            nsPresContext* aPresContext,
-                           WidgetGUIEvent* aEvent)
+                           InternalSVGZoomEvent* aEvent)
   : UIEvent(aOwner, aPresContext,
-            aEvent ? aEvent : new WidgetGUIEvent(false, NS_SVG_ZOOM, 0))
+            aEvent ? aEvent : new InternalSVGZoomEvent(false, NS_SVG_ZOOM))
   , mPreviousScale(0)
   , mNewScale(0)
 {
   if (aEvent) {
     mEventIsInternal = false;
   }
   else {
     mEventIsInternal = true;
-    mEvent->eventStructType = NS_SVGZOOM_EVENT;
     mEvent->time = PR_Now();
   }
 
-  mEvent->mFlags.mCancelable = false;
-
   // We must store the "Previous" and "New" values before this event is
   // dispatched. Reading the values from the root 'svg' element after we've
   // been dispatched is not an option since event handler code may change
   // currentScale and currentTranslate in response to this event.
   nsIPresShell *presShell;
   if (mPresContext && (presShell = mPresContext->GetPresShell())) {
     nsIDocument *doc = presShell->GetDocument();
     if (doc) {
@@ -90,14 +88,14 @@ SVGZoomEvent::~SVGZoomEvent()
 
 ////////////////////////////////////////////////////////////////////////
 // Exported creation functions:
 
 nsresult
 NS_NewDOMSVGZoomEvent(nsIDOMEvent** aInstancePtrResult,
                       mozilla::dom::EventTarget* aOwner,
                       nsPresContext* aPresContext,
-                      mozilla::WidgetGUIEvent* aEvent)
+                      mozilla::InternalSVGZoomEvent* aEvent)
 {
   mozilla::dom::SVGZoomEvent* it =
     new mozilla::dom::SVGZoomEvent(aOwner, aPresContext, aEvent);
   return CallQueryInterface(it, aInstancePtrResult);
 }
--- a/content/svg/content/src/SVGZoomEvent.h
+++ b/content/svg/content/src/SVGZoomEvent.h
@@ -23,17 +23,17 @@ namespace dom {
 class SVGZoomEvent MOZ_FINAL : public UIEvent
 {
 public:
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGZoomEvent, UIEvent)
   NS_DECL_ISUPPORTS_INHERITED
 
   SVGZoomEvent(EventTarget* aOwner, nsPresContext* aPresContext,
-               WidgetGUIEvent* aEvent);
+               InternalSVGZoomEvent* aEvent);
 
   // Forward to base class
   NS_FORWARD_TO_UIEVENT
 
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE
   {
     return SVGZoomEventBinding::Wrap(aCx, this);
   }
--- a/dom/events/EventDispatcher.cpp
+++ b/dom/events/EventDispatcher.cpp
@@ -724,20 +724,20 @@ EventDispatcher::CreateEvent(EventTarget
     case NS_TEXT_EVENT:
       return NS_NewDOMUIEvent(aDOMEvent, aOwner, aPresContext,
                               aEvent->AsTextEvent());
     case NS_CLIPBOARD_EVENT:
       return NS_NewDOMClipboardEvent(aDOMEvent, aOwner, aPresContext,
                                      aEvent->AsClipboardEvent());
     case NS_SVGZOOM_EVENT:
       return NS_NewDOMSVGZoomEvent(aDOMEvent, aOwner, aPresContext,
-                                   aEvent->AsGUIEvent());
+                                   aEvent->AsSVGZoomEvent());
     case NS_SMIL_TIME_EVENT:
-      return NS_NewDOMTimeEvent(aDOMEvent, aOwner, aPresContext, aEvent);
-
+      return NS_NewDOMTimeEvent(aDOMEvent, aOwner, aPresContext,
+                                aEvent->AsSMILTimeEvent());
     case NS_COMMAND_EVENT:
       return NS_NewDOMCommandEvent(aDOMEvent, aOwner, aPresContext,
                                    aEvent->AsCommandEvent());
     case NS_SIMPLE_GESTURE_EVENT:
       return NS_NewDOMSimpleGestureEvent(aDOMEvent, aOwner, aPresContext,
                                          aEvent->AsSimpleGestureEvent());
     case NS_POINTER_EVENT:
       return NS_NewDOMPointerEvent(aDOMEvent, aOwner, aPresContext,
--- a/dom/interfaces/events/nsIDOMEvent.idl
+++ b/dom/interfaces/events/nsIDOMEvent.idl
@@ -301,22 +301,22 @@ nsresult
 NS_NewDOMSVGEvent(nsIDOMEvent** aResult,
                   mozilla::dom::EventTarget* aOwner,
                   nsPresContext* aPresContext,
                   mozilla::WidgetEvent* aEvent);
 nsresult
 NS_NewDOMSVGZoomEvent(nsIDOMEvent** aResult,
                       mozilla::dom::EventTarget* aOwner,
                       nsPresContext* aPresContext,
-                      mozilla::WidgetGUIEvent* aEvent);
+                      mozilla::InternalSVGZoomEvent* aEvent);
 nsresult
 NS_NewDOMTimeEvent(nsIDOMEvent** aResult,
                    mozilla::dom::EventTarget* aOwner,
                    nsPresContext* aPresContext,
-                   mozilla::WidgetEvent* aEvent);
+                   mozilla::InternalSMILTimeEvent* aEvent);
 nsresult
 NS_NewDOMXULCommandEvent(nsIDOMEvent** aResult,
                          mozilla::dom::EventTarget* aOwner,
                          nsPresContext* aPresContext,
                          mozilla::WidgetInputEvent* aEvent);
 nsresult
 NS_NewDOMCommandEvent(nsIDOMEvent** aInstancePtrResult,
                       mozilla::dom::EventTarget* aOwner,
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -913,17 +913,17 @@ ContentChild::AllocPBackgroundChild(Tran
 
 bool
 ContentChild::RecvSetProcessSandbox()
 {
   // We may want to move the sandbox initialization somewhere else
   // at some point; see bug 880808.
 #if defined(MOZ_CONTENT_SANDBOX)
 #if defined(XP_LINUX)
-    SetContentProcessSandbox();
+    SetCurrentProcessSandbox();
 #elif defined(XP_WIN)
     mozilla::SandboxTarget::Instance()->StartSandbox();
 #endif
 #endif
     return true;
 }
 
 bool
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -41,19 +41,17 @@ UNIFIED_SOURCES += [
     'MediaManager.cpp',
 ]
 
 EXTRA_COMPONENTS += [
     'PeerConnection.js',
     'PeerConnection.manifest',
 ]
 
-JS_MODULES_PATH = 'modules/media'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.media += [
     'IdpProxy.jsm',
     'PeerConnectionIdp.jsm',
     'RTCStatsReport.jsm',
 ]
 
 if CONFIG['MOZ_B2G']:
     EXPORTS.mozilla += [
         'MediaPermissionGonk.h',
--- a/dom/mobilemessage/src/moz.build
+++ b/dom/mobilemessage/src/moz.build
@@ -14,17 +14,17 @@ EXPORTS.mozilla.dom.mobilemessage += [
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     SOURCES += [
         'android/MobileMessageDatabaseService.cpp',
         'android/SmsService.cpp',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
-    EXTRA_JS_MODULES = [
+    EXTRA_JS_MODULES += [
         'gonk/mms_consts.js',
         'gonk/MmsPduHelper.jsm',
         'gonk/MobileMessageDB.jsm',
         'gonk/wap_consts.js',
         'gonk/WspPduHelper.jsm',
     ]
     EXTRA_COMPONENTS += [
         'gonk/MmsService.js',
--- a/dom/network/src/moz.build
+++ b/dom/network/src/moz.build
@@ -22,17 +22,17 @@ UNIFIED_SOURCES += [
     'TCPServerSocketParent.cpp',
     'TCPSocketChild.cpp',
     'TCPSocketParent.cpp',
     'UDPSocketChild.cpp',
     'UDPSocketParent.cpp',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
-    EXTRA_JS_MODULES = [
+    EXTRA_JS_MODULES += [
         'NetworkStatsDB.jsm',
         'NetworkStatsService.jsm',
     ]
 
 EXTRA_COMPONENTS += [
     'TCPServerSocket.js',
     'TCPSocket.manifest',
     'TCPSocketParentIntermediary.js',
--- a/dom/smil/TimeEvent.cpp
+++ b/dom/smil/TimeEvent.cpp
@@ -1,44 +1,36 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "mozilla/ContentEvents.h"
 #include "mozilla/dom/TimeEvent.h"
-#include "mozilla/BasicEvents.h"
 #include "nsIDocShell.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsPresContext.h"
 
 namespace mozilla {
 namespace dom {
 
 TimeEvent::TimeEvent(EventTarget* aOwner,
                      nsPresContext* aPresContext,
-                     WidgetEvent* aEvent)
+                     InternalSMILTimeEvent* aEvent)
   : Event(aOwner, aPresContext,
-          aEvent ? aEvent : new InternalUIEvent(false, 0))
-  , mDetail(0)
+          aEvent ? aEvent : new InternalSMILTimeEvent(false, 0))
+  , mDetail(mEvent->AsSMILTimeEvent()->detail)
 {
   SetIsDOMBinding();
   if (aEvent) {
     mEventIsInternal = false;
   } else {
     mEventIsInternal = true;
-    mEvent->eventStructType = NS_SMIL_TIME_EVENT;
   }
 
-  if (mEvent->eventStructType == NS_SMIL_TIME_EVENT) {
-    mDetail = mEvent->AsUIEvent()->detail;
-  }
-
-  mEvent->mFlags.mBubbles = false;
-  mEvent->mFlags.mCancelable = false;
-
   if (mPresContext) {
     nsCOMPtr<nsIDocShell> docShell = mPresContext->GetDocShell();
     if (docShell) {
       mView = docShell->GetWindow();
     }
   }
 }
 
@@ -87,15 +79,15 @@ TimeEvent::InitTimeEvent(const nsAString
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsresult
 NS_NewDOMTimeEvent(nsIDOMEvent** aInstancePtrResult,
                    EventTarget* aOwner,
                    nsPresContext* aPresContext,
-                   WidgetEvent* aEvent)
+                   InternalSMILTimeEvent* aEvent)
 {
   TimeEvent* it = new TimeEvent(aOwner, aPresContext, aEvent);
   NS_ADDREF(it);
   *aInstancePtrResult = static_cast<Event*>(it);
   return NS_OK;
 }
--- a/dom/smil/TimeEvent.h
+++ b/dom/smil/TimeEvent.h
@@ -14,17 +14,17 @@ namespace mozilla {
 namespace dom {
 
 class TimeEvent MOZ_FINAL : public Event,
                             public nsIDOMTimeEvent
 {
 public:
   TimeEvent(EventTarget* aOwner,
             nsPresContext* aPresContext,
-            WidgetEvent* aEvent);
+            InternalSMILTimeEvent* aEvent);
 
   // nsISupports interface:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TimeEvent, Event)
 
   // nsIDOMTimeEvent interface:
   NS_DECL_NSIDOMTIMEEVENT
 
--- a/dom/smil/nsSMILTimedElement.cpp
+++ b/dom/smil/nsSMILTimedElement.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/DebugOnly.h"
 
-#include "mozilla/BasicEvents.h"
+#include "mozilla/ContentEvents.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/dom/SVGAnimationElement.h"
 #include "nsSMILTimedElement.h"
 #include "nsAttrValueInlines.h"
 #include "nsSMILAnimationFunction.h"
 #include "nsSMILTimeValue.h"
 #include "nsSMILTimeValueSpec.h"
 #include "nsSMILInstanceTime.h"
@@ -87,18 +87,17 @@ namespace
   public:
     AsyncTimeEventRunner(nsIContent* aTarget, uint32_t aMsg, int32_t aDetail)
       : mTarget(aTarget), mMsg(aMsg), mDetail(aDetail)
     {
     }
 
     NS_IMETHOD Run()
     {
-      InternalUIEvent event(true, mMsg);
-      event.eventStructType = NS_SMIL_TIME_EVENT;
+      InternalSMILTimeEvent event(true, mMsg);
       event.detail = mDetail;
 
       nsPresContext* context = nullptr;
       nsIDocument* doc = mTarget->GetCurrentDoc();
       if (doc) {
         nsCOMPtr<nsIPresShell> shell = doc->GetShell();
         if (shell) {
           context = shell->GetPresContext();
--- a/dom/wappush/src/moz.build
+++ b/dom/wappush/src/moz.build
@@ -1,14 +1,14 @@
 # -*- 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/.
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
-    EXTRA_JS_MODULES = [
+    EXTRA_JS_MODULES += [
         'gonk/CpPduHelper.jsm',
         'gonk/SiPduHelper.jsm',
         'gonk/SlPduHelper.jsm',
         'gonk/WapPushManager.js',
         'gonk/WbxmlPduHelper.jsm'
     ]
--- a/gfx/gl/GLBlitHelper.cpp
+++ b/gfx/gl/GLBlitHelper.cpp
@@ -540,18 +540,18 @@ GLBlitHelper::DeleteTexBlitProgram()
     if (mTexYUVPlanarBlit_Program) {
         mGL->fDeleteProgram(mTexYUVPlanarBlit_Program);
         mTexYUVPlanarBlit_Program = 0;
     }
 }
 
 void
 GLBlitHelper::BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB,
-                                        const gfx::IntSize& srcSize,
-                                        const gfx::IntSize& destSize)
+                                           const gfx::IntSize& srcSize,
+                                           const gfx::IntSize& destSize)
 {
     MOZ_ASSERT(!srcFB || mGL->fIsFramebuffer(srcFB));
     MOZ_ASSERT(!destFB || mGL->fIsFramebuffer(destFB));
 
     MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit));
 
     ScopedBindFramebuffer boundFB(mGL);
     ScopedGLState scissor(mGL, LOCAL_GL_SCISSOR_TEST, false);
@@ -562,19 +562,19 @@ GLBlitHelper::BlitFramebufferToFramebuff
     mGL->fBlitFramebuffer(0, 0,  srcSize.width,  srcSize.height,
                           0, 0, destSize.width, destSize.height,
                           LOCAL_GL_COLOR_BUFFER_BIT,
                           LOCAL_GL_NEAREST);
 }
 
 void
 GLBlitHelper::BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB,
-                                        const gfx::IntSize& srcSize,
-                                        const gfx::IntSize& destSize,
-                                        const GLFormats& srcFormats)
+                                           const gfx::IntSize& srcSize,
+                                           const gfx::IntSize& destSize,
+                                           const GLFormats& srcFormats)
 {
     MOZ_ASSERT(!srcFB || mGL->fIsFramebuffer(srcFB));
     MOZ_ASSERT(!destFB || mGL->fIsFramebuffer(destFB));
 
     if (mGL->IsSupported(GLFeature::framebuffer_blit)) {
         BlitFramebufferToFramebuffer(srcFB, destFB,
                                      srcSize, destSize);
         return;
@@ -585,17 +585,21 @@ GLBlitHelper::BlitFramebufferToFramebuff
 
     BlitFramebufferToTexture(srcFB, tex, srcSize, srcSize);
     BlitTextureToFramebuffer(tex, destFB, srcSize, destSize);
 
     mGL->fDeleteTextures(1, &tex);
 }
 
 void
-GLBlitHelper::BindAndUploadYUVTexture(Channel which, uint32_t width, uint32_t height, void* data, bool needsAllocation)
+GLBlitHelper::BindAndUploadYUVTexture(Channel which,
+                                      uint32_t width,
+                                      uint32_t height,
+                                      void* data,
+                                      bool needsAllocation)
 {
     MOZ_ASSERT(which < Channel_Max, "Invalid channel!");
     GLuint* srcTexArr[3] = {&mSrcTexY, &mSrcTexCb, &mSrcTexCr};
     GLuint& tex = *srcTexArr[which];
     if (!tex) {
         MOZ_ASSERT(needsAllocation);
         tex = CreateTexture(mGL, LOCAL_GL_LUMINANCE, LOCAL_GL_LUMINANCE, LOCAL_GL_UNSIGNED_BYTE,
                             gfx::IntSize(width, height), false);
@@ -623,34 +627,36 @@ GLBlitHelper::BindAndUploadYUVTexture(Ch
                          LOCAL_GL_LUMINANCE,
                          LOCAL_GL_UNSIGNED_BYTE,
                          data);
     }
 }
 
 #ifdef MOZ_WIDGET_GONK
 void
-GLBlitHelper::BindAndUploadExternalTexture(EGLImage image) {
+GLBlitHelper::BindAndUploadExternalTexture(EGLImage image)
+{
     MOZ_ASSERT(image != EGL_NO_IMAGE, "Bad EGLImage");
 
     if (!mSrcTexEGL) {
         mGL->fGenTextures(1, &mSrcTexEGL);
         mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, mSrcTexEGL);
         mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
         mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
         mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
         mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
     } else {
         mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, mSrcTexEGL);
     }
     mGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_EXTERNAL_OES, image);
 }
 
 bool
-GLBlitHelper::BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip) {
+GLBlitHelper::BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip)
+{
     ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0);
     mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
 
     EGLint attrs[] = {
         LOCAL_EGL_IMAGE_PRESERVED, LOCAL_EGL_TRUE,
         LOCAL_EGL_NONE, LOCAL_EGL_NONE
     };
     EGLImage image = sEGLLibrary.fCreateImage(sEGLLibrary.Display(),
@@ -708,33 +714,40 @@ GLBlitHelper::BlitPlanarYCbCrImage(layer
     for (int i = 0; i < 3; i++) {
         mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
         mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, oldTex[i]);
     }
     return true;
 }
 
 bool
-GLBlitHelper::BlitImageToTexture(layers::Image* srcImage, const gfx::IntSize& destSize, GLuint destTex, GLenum destTarget, bool yFlip, GLuint xoffset, GLuint yoffset, GLuint cropWidth, GLuint cropHeight)
+GLBlitHelper::BlitImageToTexture(layers::Image* srcImage,
+                                 const gfx::IntSize& destSize,
+                                 GLuint destTex,
+                                 GLenum destTarget,
+                                 bool yFlip,
+                                 GLuint xoffset,
+                                 GLuint yoffset,
+                                 GLuint cropWidth,
+                                 GLuint cropHeight)
 {
     ScopedGLDrawState autoStates(mGL);
 
     BlitType type;
-    switch (srcImage->GetFormat())
-    {
-        case ImageFormat::PLANAR_YCBCR:
-            type = ConvertPlanarYCbCr;
-            break;
-        case ImageFormat::GRALLOC_PLANAR_YCBCR:
+    switch (srcImage->GetFormat()) {
+    case ImageFormat::PLANAR_YCBCR:
+        type = ConvertPlanarYCbCr;
+        break;
+    case ImageFormat::GRALLOC_PLANAR_YCBCR:
 #ifdef MOZ_WIDGET_GONK
-            type = ConvertGralloc;
-            break;
+        type = ConvertGralloc;
+        break;
 #endif
-        default:
-            return false;
+    default:
+        return false;
     }
 
     bool init = InitTexQuadProgram(type);
     if (!init) {
         return false;
     }
 
     if (!mFBO) {
@@ -762,19 +775,19 @@ GLBlitHelper::BlitImageToTexture(layers:
         return BlitPlanarYCbCrImage(yuvImage, yFlip);
     }
 
     return false;
 }
 
 void
 GLBlitHelper::BlitTextureToFramebuffer(GLuint srcTex, GLuint destFB,
-                                    const gfx::IntSize& srcSize,
-                                    const gfx::IntSize& destSize,
-                                    GLenum srcTarget)
+                                       const gfx::IntSize& srcSize,
+                                       const gfx::IntSize& destSize,
+                                       GLenum srcTarget)
 {
     MOZ_ASSERT(mGL->fIsTexture(srcTex));
     MOZ_ASSERT(!destFB || mGL->fIsFramebuffer(destFB));
 
     if (mGL->IsSupported(GLFeature::framebuffer_blit)) {
         ScopedFramebufferForTexture srcWrapper(mGL, srcTex, srcTarget);
         MOZ_ASSERT(srcWrapper.IsComplete());
 
@@ -808,19 +821,19 @@ GLBlitHelper::BlitTextureToFramebuffer(G
         printf_stderr("[%s:%d] Fatal Error: Failed to prepare to blit texture->framebuffer.\n");
         MOZ_CRASH();
     }
     mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
 }
 
 void
 GLBlitHelper::BlitFramebufferToTexture(GLuint srcFB, GLuint destTex,
-                                    const gfx::IntSize& srcSize,
-                                    const gfx::IntSize& destSize,
-                                    GLenum destTarget)
+                                       const gfx::IntSize& srcSize,
+                                       const gfx::IntSize& destSize,
+                                       GLenum destTarget)
 {
     MOZ_ASSERT(!srcFB || mGL->fIsFramebuffer(srcFB));
     MOZ_ASSERT(mGL->fIsTexture(destTex));
 
     if (mGL->IsSupported(GLFeature::framebuffer_blit)) {
         ScopedFramebufferForTexture destWrapper(mGL, destTex, destTarget);
 
         BlitFramebufferToFramebuffer(srcFB, destWrapper.FB(),
@@ -835,19 +848,19 @@ GLBlitHelper::BlitFramebufferToTexture(G
     mGL->fCopyTexSubImage2D(destTarget, 0,
                        0, 0,
                        0, 0,
                        srcSize.width, srcSize.height);
 }
 
 void
 GLBlitHelper::BlitTextureToTexture(GLuint srcTex, GLuint destTex,
-                                const gfx::IntSize& srcSize,
-                                const gfx::IntSize& destSize,
-                                GLenum srcTarget, GLenum destTarget)
+                                   const gfx::IntSize& srcSize,
+                                   const gfx::IntSize& destSize,
+                                   GLenum srcTarget, GLenum destTarget)
 {
     MOZ_ASSERT(mGL->fIsTexture(srcTex));
     MOZ_ASSERT(mGL->fIsTexture(destTex));
 
     // Generally, just use the CopyTexSubImage path
     ScopedFramebufferForTexture srcWrapper(mGL, srcTex, srcTarget);
 
     BlitFramebufferToTexture(srcWrapper.FB(), destTex,
--- a/gfx/gl/GLReadTexImageHelper.cpp
+++ b/gfx/gl/GLReadTexImageHelper.cpp
@@ -1,21 +1,24 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* vim: set ts=8 sts=4 et sw=4 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GLReadTexImageHelper.h"
+
+#include "gfx2DGlue.h"
+#include "gfxTypes.h"
 #include "GLContext.h"
 #include "OGLShaderProgram.h"
-#include "gfxTypes.h"
 #include "ScopedGLHelpers.h"
+
 #include "mozilla/gfx/2D.h"
-#include "gfx2DGlue.h"
+#include "mozilla/Move.h"
 
 namespace mozilla {
 namespace gl {
 
 using namespace mozilla::gfx;
 
 GLReadTexImageHelper::GLReadTexImageHelper(GLContext* gl)
     : mGL(gl)
@@ -76,28 +79,27 @@ readTextureImageFS_TEXTURE_RECTANGLE[] =
     "#ifdef GL_ES\n"
     "precision mediump float;\n"
     "#endif\n"
     "varying vec2 vTexCoord;\n"
     "uniform sampler2DRect uTexture;\n"
     "void main() { gl_FragColor = texture2DRect(uTexture, vTexCoord).bgra; }";
 
 GLuint
-GLReadTexImageHelper::TextureImageProgramFor(GLenum aTextureTarget, int aConfig) {
+GLReadTexImageHelper::TextureImageProgramFor(GLenum aTextureTarget,
+                                             int aConfig)
+{
     int variant = 0;
     const GLchar* readTextureImageFS = nullptr;
-    if (aTextureTarget == LOCAL_GL_TEXTURE_2D)
-    {
-        if (aConfig & mozilla::layers::ENABLE_TEXTURE_RB_SWAP)
-        {   // Need to swizzle R/B.
+    if (aTextureTarget == LOCAL_GL_TEXTURE_2D) {
+        if (aConfig & mozilla::layers::ENABLE_TEXTURE_RB_SWAP) {
+            // Need to swizzle R/B.
             readTextureImageFS = readTextureImageFS_TEXTURE_2D_BGRA;
             variant = 1;
-        }
-        else
-        {
+        } else {
             readTextureImageFS = readTextureImageFS_TEXTURE_2D;
             variant = 0;
         }
     } else if (aTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL) {
         readTextureImageFS = readTextureImageFS_TEXTURE_EXTERNAL;
         variant = 2;
     } else if (aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE) {
         readTextureImageFS = readTextureImageFS_TEXTURE_RECTANGLE;
@@ -200,107 +202,134 @@ GetActualReadFormats(GLContext* gl,
         return false;
     } else {
         readFormat = destFormat;
         readType = destType;
         return true;
     }
 }
 
-static void SwapRAndBComponents(DataSourceSurface* surf)
+static void
+SwapRAndBComponents(DataSourceSurface* surf)
 {
-  uint8_t *row = surf->GetData();
-  if (!row) {
-      MOZ_ASSERT(false, "SwapRAndBComponents: Failed to get data from DataSourceSurface.");
-      return;
-  }
-
-  size_t rowBytes = surf->GetSize().width*4;
-  size_t rowHole = surf->Stride() - rowBytes;
+    DataSourceSurface::MappedSurface map;
+    MOZ_ALWAYS_TRUE( surf->Map(DataSourceSurface::MapType::READ_WRITE, &map) );
+    MOZ_ASSERT(map.mStride >= 0);
 
-  size_t rows = surf->GetSize().height;
-
-  while (rows) {
-
-    const uint8_t *rowEnd = row + rowBytes;
+    const size_t rowBytes = surf->GetSize().width*4;
+    const size_t rowHole = map.mStride - rowBytes;
 
-    while (row != rowEnd) {
-      row[0] ^= row[2];
-      row[2] ^= row[0];
-      row[0] ^= row[2];
-      row += 4;
+    uint8_t* row = map.mData;
+    if (!row) {
+        MOZ_ASSERT(false, "SwapRAndBComponents: Failed to get data from"
+                          " DataSourceSurface.");
+        surf->Unmap();
+        return;
     }
 
-    row += rowHole;
-    --rows;
-  }
+    const size_t rows = surf->GetSize().height;
+    for (size_t i = 0; i < rows; i++) {
+        const uint8_t* rowEnd = row + rowBytes;
+
+        while (row != rowEnd) {
+            Swap(row[0], row[2]);
+            row += 4;
+        }
+
+        row += rowHole;
+    }
+
+    surf->Unmap();
 }
 
-static uint16_t PackRGB565(uint8_t r, uint8_t g, uint8_t b)
+static uint16_t
+PackRGB565(uint8_t r, uint8_t g, uint8_t b)
 {
     uint16_t pixel = ((r << 11) & 0xf800) |
                      ((g <<  5) & 0x07e0) |
                      ((b      ) & 0x001f);
 
     return pixel;
 }
 
-static void CopyDataSourceSurface(DataSourceSurface* aSource,
-                                  DataSourceSurface* aDest)
+static void
+CopyDataSourceSurface(DataSourceSurface* aSource,
+                      DataSourceSurface* aDest)
 {
-  MOZ_ASSERT(aSource->GetSize() == aDest->GetSize());
-  MOZ_ASSERT(aSource->GetFormat() == SurfaceFormat::B8G8R8A8 ||
-             aSource->GetFormat() == SurfaceFormat::B8G8R8X8);
+    // Don't worry too much about speed.
+    MOZ_ASSERT(aSource->GetSize() == aDest->GetSize());
+    MOZ_ASSERT(aSource->GetFormat() == SurfaceFormat::R8G8B8A8 ||
+               aSource->GetFormat() == SurfaceFormat::R8G8B8X8 ||
+               aSource->GetFormat() == SurfaceFormat::B8G8R8A8 ||
+               aSource->GetFormat() == SurfaceFormat::B8G8R8X8);
+    MOZ_ASSERT(aDest->GetFormat() == SurfaceFormat::R8G8B8A8 ||
+               aDest->GetFormat() == SurfaceFormat::R8G8B8X8 ||
+               aDest->GetFormat() == SurfaceFormat::B8G8R8A8 ||
+               aDest->GetFormat() == SurfaceFormat::B8G8R8X8 ||
+               aDest->GetFormat() == SurfaceFormat::R5G6B5);
 
-  uint8_t *srcRow = aSource->GetData();
-  size_t srcRowBytes = aSource->GetSize().width * BytesPerPixel(aSource->GetFormat());
-  size_t srcRowHole = aSource->Stride() - srcRowBytes;
+    const bool isSrcBGR = aSource->GetFormat() == SurfaceFormat::B8G8R8A8 ||
+                          aSource->GetFormat() == SurfaceFormat::B8G8R8X8;
+    const bool isDestBGR = aDest->GetFormat() == SurfaceFormat::B8G8R8A8 ||
+                           aDest->GetFormat() == SurfaceFormat::B8G8R8X8;
+    const bool needsSwap02 = isSrcBGR != isDestBGR;
 
-  uint8_t *destRow = aDest->GetData();
-  size_t destRowBytes = aDest->GetSize().width * BytesPerPixel(aDest->GetFormat());
-  size_t destRowHole = aDest->Stride() - destRowBytes;
+    const bool srcHasAlpha = aSource->GetFormat() == SurfaceFormat::R8G8B8A8 ||
+                             aSource->GetFormat() == SurfaceFormat::B8G8R8A8;
+    const bool destHasAlpha = aDest->GetFormat() == SurfaceFormat::R8G8B8A8 ||
+                              aDest->GetFormat() == SurfaceFormat::B8G8R8A8;
+    const bool needsAlphaMask = !srcHasAlpha && destHasAlpha;
 
-  bool needsRBSwap = false;
-  if (aDest->GetFormat() == SurfaceFormat::B8G8R8A8 ||
-      aDest->GetFormat() == SurfaceFormat::B8G8R8X8) {
-      needsRBSwap = true;
-  }
+    const bool needsConvertTo16Bits = aDest->GetFormat() == SurfaceFormat::R5G6B5;
 
-  bool needsConvertTo16Bits = false;
-  if (aDest->GetFormat() == SurfaceFormat::R5G6B5) {
-      needsConvertTo16Bits = true;
-  }
+    DataSourceSurface::MappedSurface srcMap;
+    DataSourceSurface::MappedSurface destMap;
+    MOZ_ALWAYS_TRUE( aSource->Map(DataSourceSurface::MapType::READ, &srcMap) );
+    MOZ_ALWAYS_TRUE( aDest->Map(DataSourceSurface::MapType::WRITE, &destMap) );
+    MOZ_ASSERT(srcMap.mStride >= 0);
+    MOZ_ASSERT(destMap.mStride >= 0);
 
-  size_t rows = aSource->GetSize().height;
+    const size_t srcBPP = BytesPerPixel(aSource->GetFormat());
+    const size_t srcRowBytes = aSource->GetSize().width * srcBPP;
+    const size_t srcRowHole = srcMap.mStride - srcRowBytes;
 
-  while (rows) {
-    const uint8_t *srcRowEnd = srcRow + srcRowBytes;
+    const size_t destBPP = BytesPerPixel(aDest->GetFormat());
+    const size_t destRowBytes = aDest->GetSize().width * destBPP;
+    const size_t destRowHole = destMap.mStride - destRowBytes;
+
+    uint8_t* srcRow = srcMap.mData;
+    uint8_t* destRow = destMap.mData;
+    const size_t rows = aSource->GetSize().height;
+    for (size_t i = 0; i < rows; i++) {
+        const uint8_t* srcRowEnd = srcRow + srcRowBytes;
 
-    while (srcRow != srcRowEnd) {
-      uint8_t r = needsRBSwap ? srcRow[2] : srcRow[0];
-      uint8_t g = srcRow[1];
-      uint8_t b = needsRBSwap ? srcRow[0] : srcRow[2];
-      uint8_t a = srcRow[3];
+        while (srcRow != srcRowEnd) {
+            uint8_t d0 = needsSwap02 ? srcRow[2] : srcRow[0];
+            uint8_t d1 = srcRow[1];
+            uint8_t d2 = needsSwap02 ? srcRow[0] : srcRow[2];
+            uint8_t d3 = needsAlphaMask ? 0xff : srcRow[3];
 
-      if (needsConvertTo16Bits) {
-        *(uint16_t*)destRow = PackRGB565(r, g, b);
-      } else {
-        destRow[0] = r;
-        destRow[1] = g;
-        destRow[2] = b;
-        destRow[3] = a;
-      }
-      srcRow += BytesPerPixel(aSource->GetFormat());
-      destRow += BytesPerPixel(aDest->GetFormat());
+            if (needsConvertTo16Bits) {
+                *(uint16_t*)destRow = PackRGB565(d0, d1, d2);
+            } else {
+                destRow[0] = d0;
+                destRow[1] = d1;
+                destRow[2] = d2;
+                destRow[3] = d3;
+            }
+            srcRow += srcBPP;
+            destRow += destBPP;
+        }
+
+        srcRow += srcRowHole;
+        destRow += destRowHole;
     }
 
-    srcRow += srcRowHole;
-    destRow += destRowHole;
-    --rows;
-  }
+    aSource->Unmap();
+    aDest->Unmap();
 }
 
 static int
 CalcRowStride(int width, int pixelSize, int alignment)
 {
     MOZ_ASSERT(alignment);
 
     int rowStride = width * pixelSize;
@@ -321,47 +350,48 @@ GuessAlignment(int width, int pixelSize,
             NS_WARNING("Bad alignment for GLES. Will use temp surf for readback.");
             return 0;
         }
     }
     return alignment;
 }
 
 void
-ReadPixelsIntoDataSurface(GLContext* gl, DataSourceSurface* dest) {
+ReadPixelsIntoDataSurface(GLContext* gl, DataSourceSurface* dest)
+{
     gl->MakeCurrent();
     MOZ_ASSERT(dest->GetSize().width != 0);
     MOZ_ASSERT(dest->GetSize().height != 0);
 
     bool hasAlpha = dest->GetFormat() == SurfaceFormat::B8G8R8A8 ||
                     dest->GetFormat() == SurfaceFormat::R8G8B8A8;
 
     int destPixelSize;
     GLenum destFormat;
     GLenum destType;
 
     switch (dest->GetFormat()) {
-        case SurfaceFormat::B8G8R8A8:
-        case SurfaceFormat::B8G8R8X8:
-            // Needs host (little) endian ARGB.
-            destFormat = LOCAL_GL_BGRA;
-            destType = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
-            break;
-        case SurfaceFormat::R8G8B8A8:
-        case SurfaceFormat::R8G8B8X8:
-            // Needs host (little) endian ABGR.
-            destFormat = LOCAL_GL_RGBA;
-            destType = LOCAL_GL_UNSIGNED_BYTE;
-            break;
-        case SurfaceFormat::R5G6B5:
-            destFormat = LOCAL_GL_RGB;
-            destType = LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV;
-            break;
-        default:
-            MOZ_CRASH("Bad format.");
+    case SurfaceFormat::B8G8R8A8:
+    case SurfaceFormat::B8G8R8X8:
+        // Needs host (little) endian ARGB.
+        destFormat = LOCAL_GL_BGRA;
+        destType = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
+        break;
+    case SurfaceFormat::R8G8B8A8:
+    case SurfaceFormat::R8G8B8X8:
+        // Needs host (little) endian ABGR.
+        destFormat = LOCAL_GL_RGBA;
+        destType = LOCAL_GL_UNSIGNED_BYTE;
+        break;
+    case SurfaceFormat::R5G6B5:
+        destFormat = LOCAL_GL_RGB;
+        destType = LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV;
+        break;
+    default:
+        MOZ_CRASH("Bad format.");
     }
     destPixelSize = BytesPerPixel(dest->GetFormat());
     MOZ_ASSERT(dest->GetSize().width * destPixelSize <= dest->Stride());
 
     GLenum readFormat = destFormat;
     GLenum readType = destType;
     bool needsTempSurf = !GetActualReadFormats(gl,
                                                destFormat, destType,
@@ -377,17 +407,21 @@ ReadPixelsIntoDataSurface(GLContext* gl,
     }
     if (needsTempSurf) {
         if (gl->DebugMode()) {
             NS_WARNING("Needing intermediary surface for ReadPixels. This will be slow!");
         }
         SurfaceFormat readFormatGFX;
 
         switch (readFormat) {
-            case LOCAL_GL_RGBA:
+            case LOCAL_GL_RGBA: {
+                readFormatGFX = hasAlpha ? SurfaceFormat::R8G8B8A8
+                                         : SurfaceFormat::R8G8B8X8;
+                break;
+            }
             case LOCAL_GL_BGRA: {
                 readFormatGFX = hasAlpha ? SurfaceFormat::B8G8R8A8
                                          : SurfaceFormat::B8G8R8X8;
                 break;
             }
             case LOCAL_GL_RGB: {
                 MOZ_ASSERT(destPixelSize == 2);
                 MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV);
@@ -452,18 +486,17 @@ ReadPixelsIntoDataSurface(GLContext* gl,
         CopyDataSourceSurface(readSurf, dest);
     }
 
     // Check if GL is giving back 1.0 alpha for
     // RGBA reads to RGBA images from no-alpha buffers.
 #ifdef XP_MACOSX
     if (gl->WorkAroundDriverBugs() &&
         gl->Vendor() == gl::GLVendor::NVIDIA &&
-        (dest->GetFormat() == SurfaceFormat::R8G8B8A8 ||
-         dest->GetFormat() == SurfaceFormat::B8G8R8A8) &&
+        hasAlpha &&
         width && height)
     {
         GLint alphaBits = 0;
         gl->fGetIntegerv(LOCAL_GL_ALPHA_BITS, &alphaBits);
         if (!alphaBits) {
             const uint32_t alphaMask = gfxPackedPixelNoPreMultiply(0xff,0,0,0);
 
             MOZ_ASSERT(dest->GetSize().width * destPixelSize == dest->Stride());
@@ -478,46 +511,50 @@ ReadPixelsIntoDataSurface(GLContext* gl,
                     *itr |= alphaMask;
                 }
             }
         }
     }
 #endif
 }
 
-static TemporaryRef<DataSourceSurface> YInvertImageSurface(DataSourceSurface* aSurf)
+static TemporaryRef<DataSourceSurface>
+YInvertImageSurface(DataSourceSurface* aSurf)
 {
-  RefPtr<DataSourceSurface> temp =
-    Factory::CreateDataSourceSurfaceWithStride(aSurf->GetSize(),
-                                               aSurf->GetFormat(),
-                                               aSurf->Stride());
-  if (!temp) {
-    return nullptr;
-  }
-  DataSourceSurface::MappedSurface map;
-  if (!temp->Map(DataSourceSurface::MapType::WRITE, &map)) {
-    return nullptr;
-  }
-  RefPtr<DrawTarget> dt =
-    Factory::CreateDrawTargetForData(BackendType::CAIRO,
-                                     map.mData,
-                                     temp->GetSize(),
-                                     map.mStride,
-                                     temp->GetFormat());
-  if (!dt) {
+    RefPtr<DataSourceSurface> temp =
+      Factory::CreateDataSourceSurfaceWithStride(aSurf->GetSize(),
+                                                 aSurf->GetFormat(),
+                                                 aSurf->Stride());
+    if (!temp) {
+        return nullptr;
+    }
+
+    DataSourceSurface::MappedSurface map;
+    if (!temp->Map(DataSourceSurface::MapType::WRITE, &map)) {
+        return nullptr;
+    }
+
+    RefPtr<DrawTarget> dt =
+      Factory::CreateDrawTargetForData(BackendType::CAIRO,
+                                       map.mData,
+                                       temp->GetSize(),
+                                       map.mStride,
+                                       temp->GetFormat());
+    if (!dt) {
+        temp->Unmap();
+        return nullptr;
+    }
+
+    dt->SetTransform(Matrix::Translation(0.0, aSurf->GetSize().height) *
+                     Matrix::Scaling(1.0, -1.0));
+    Rect rect(0, 0, aSurf->GetSize().width, aSurf->GetSize().height);
+    dt->DrawSurface(aSurf, rect, rect, DrawSurfaceOptions(),
+                    DrawOptions(1.0, CompositionOp::OP_SOURCE, AntialiasMode::NONE));
     temp->Unmap();
-    return nullptr;
-  }
-  dt->SetTransform(Matrix::Translation(0.0, aSurf->GetSize().height) *
-                   Matrix::Scaling(1.0, -1.0));
-  Rect rect(0, 0, aSurf->GetSize().width, aSurf->GetSize().height);
-  dt->DrawSurface(aSurf, rect, rect, DrawSurfaceOptions(),
-                  DrawOptions(1.0, CompositionOp::OP_SOURCE, AntialiasMode::NONE));
-  temp->Unmap();
-  return temp.forget();
+    return temp.forget();
 }
 
 TemporaryRef<DataSourceSurface>
 ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, SurfaceFormat aFormat)
 {
     gl->MakeCurrent();
     gl->GuaranteeResolve();
     gl->fActiveTexture(LOCAL_GL_TEXTURE0);
@@ -535,27 +572,29 @@ ReadBackSurface(GLContext* gl, GLuint aT
         return nullptr;
     }
 
     uint32_t currentPackAlignment = 0;
     gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*)&currentPackAlignment);
     if (currentPackAlignment != 4) {
         gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
     }
+
     gl->fGetTexImage(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, surf->GetData());
+
     if (currentPackAlignment != 4) {
         gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
     }
 
     if (aFormat == SurfaceFormat::R8G8B8A8 || aFormat == SurfaceFormat::R8G8B8X8) {
-      SwapRAndBComponents(surf);
+        SwapRAndBComponents(surf);
     }
 
     if (aYInvert) {
-      surf = YInvertImageSurface(surf);
+        surf = YInvertImageSurface(surf);
     }
 
     return surf.forget();
 }
 
 #define CLEANUP_IF_GLERROR_OCCURRED(x)                                      \
     if (DidGLErrorOccur(x)) {                                               \
         isurf = nullptr;                                                    \
@@ -697,11 +736,10 @@ GLReadTexImageHelper::ReadTexImage(GLuin
     if (oldTexUnit != LOCAL_GL_TEXTURE0)
         mGL->fActiveTexture(oldTexUnit);
 
     return isurf.forget();
 }
 
 #undef CLEANUP_IF_GLERROR_OCCURRED
 
-
 }
 }
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -62,16 +62,17 @@
 #include "SharedMemoryBasic.h"          // for SharedMemoryBasic
 
 // #define APZC_ENABLE_RENDERTRACE
 
 #define ENABLE_APZC_LOGGING 0
 // #define ENABLE_APZC_LOGGING 1
 
 #if ENABLE_APZC_LOGGING
+#  include "LayersLogging.h"
 #  define APZC_LOG(...) printf_stderr("APZC: " __VA_ARGS__)
 #  define APZC_LOG_FM(fm, prefix, ...) \
     { std::stringstream ss; \
       ss << nsPrintfCString(prefix, __VA_ARGS__).get(); \
       AppendToString(ss, fm, ":", "", true); \
       APZC_LOG("%s", ss.str().c_str()); \
     }
 #else
--- a/gfx/thebes/gfxFontFamilyList.h
+++ b/gfx/thebes/gfxFontFamilyList.h
@@ -160,59 +160,46 @@ struct FontFamilyName MOZ_FINAL {
     nsString       mName; // empty if mType != eFamily_named
 };
 
 inline bool
 operator==(const FontFamilyName& a, const FontFamilyName& b) {
     return a.mType == b.mType && a.mName == b.mName;
 }
 
-class FontFamilyList;
-
-template<>
-struct HasDangerousPublicDestructor<FontFamilyList>
-{
-  static const bool value = true;
-};
-
 /**
  * font family list, array of font families and a default font type.
  * font family names are either named strings or generics. the default
  * font type is used to preserve the variable font fallback behavior
  */ 
 
-class FontFamilyList MOZ_FINAL {
+class FontFamilyList {
 public:
-    FontFamilyList() : mDefaultFontType(eFamily_none) {
-        MOZ_COUNT_CTOR(FontFamilyList);
+    FontFamilyList()
+        : mDefaultFontType(eFamily_none)
+    {
     }
 
     FontFamilyList(FontFamilyType aGenericType)
         : mDefaultFontType(eFamily_none)
     {
         Append(FontFamilyName(aGenericType));
-        MOZ_COUNT_CTOR(FontFamilyList);
     }
 
     FontFamilyList(const nsAString& aFamilyName,
                    QuotedName aQuoted)
         : mDefaultFontType(eFamily_none)
     {
         Append(FontFamilyName(aFamilyName, aQuoted));
-        MOZ_COUNT_CTOR(FontFamilyList);
     }
 
     FontFamilyList(const FontFamilyList& aOther)
-        : mFontlist(aOther.mFontlist), mDefaultFontType(aOther.mDefaultFontType)
+        : mFontlist(aOther.mFontlist)
+        , mDefaultFontType(aOther.mDefaultFontType)
     {
-        MOZ_COUNT_CTOR(FontFamilyList);
-    }
-
-    ~FontFamilyList() {
-        MOZ_COUNT_DTOR(FontFamilyList);
     }
 
     void Append(const FontFamilyName& aFamilyName) {
         mFontlist.AppendElement(aFamilyName);
     }
 
     void Append(const nsTArray<nsString>& aFamilyNameList) {
         uint32_t len = aFamilyNameList.Length();
@@ -305,18 +292,16 @@ public:
     size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
         return mFontlist.SizeOfExcludingThis(aMallocSizeOf);
     }
 
     size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
         return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
     }
 
-    NS_INLINE_DECL_REFCOUNTING(FontFamilyList)
-
 private:
     nsTArray<FontFamilyName>   mFontlist;
     FontFamilyType             mDefaultFontType; // none, serif or sans-serif
 };
 
 inline bool
 operator==(const FontFamilyList& a, const FontFamilyList& b) {
     return a.Equals(b);
--- a/js/public/Id.h
+++ b/js/public/Id.h
@@ -55,16 +55,26 @@ JSID_IS_STRING(jsid id)
 
 static MOZ_ALWAYS_INLINE JSString *
 JSID_TO_STRING(jsid id)
 {
     MOZ_ASSERT(JSID_IS_STRING(id));
     return (JSString *)JSID_BITS(id);
 }
 
+/*
+ * Only JSStrings that have been interned via the JSAPI can be turned into
+ * jsids by API clients.
+ *
+ * N.B. if a jsid is backed by a string which has not been interned, that
+ * string must be appropriately rooted to avoid being collected by the GC.
+ */
+JS_PUBLIC_API(jsid)
+INTERNED_STRING_TO_JSID(JSContext *cx, JSString *str);
+
 static MOZ_ALWAYS_INLINE bool
 JSID_IS_ZERO(jsid id)
 {
     return JSID_BITS(id) == 0;
 }
 
 static MOZ_ALWAYS_INLINE bool
 JSID_IS_INT(jsid id)
--- a/js/public/OldDebugAPI.h
+++ b/js/public/OldDebugAPI.h
@@ -125,93 +125,16 @@ extern JS_PUBLIC_API(const jschar *)
 JS_GetScriptSourceMap(JSContext *cx, JSScript *script);
 
 extern JS_PUBLIC_API(unsigned)
 JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script);
 
 extern JS_PUBLIC_API(unsigned)
 JS_GetScriptLineExtent(JSContext *cx, JSScript *script);
 
-/************************************************************************/
-
-/*
- * JSAbstractFramePtr is the public version of AbstractFramePtr, a pointer to a
- * StackFrame or baseline JIT frame.
- */
-class JS_PUBLIC_API(JSAbstractFramePtr)
-{
-    uintptr_t ptr_;
-    jsbytecode *pc_;
-
-  protected:
-    JSAbstractFramePtr()
-      : ptr_(0), pc_(nullptr)
-    { }
-
-  public:
-    JSAbstractFramePtr(void *raw, jsbytecode *pc);
-
-    uintptr_t raw() const { return ptr_; }
-    jsbytecode *pc() const { return pc_; }
-
-    operator bool() const { return !!ptr_; }
-
-    JSObject *scopeChain(JSContext *cx);
-    JSObject *callObject(JSContext *cx);
-
-    JSFunction *maybeFun();
-    JSScript *script();
-
-    bool getThisValue(JSContext *cx, JS::MutableHandleValue thisv);
-
-    bool isDebuggerFrame();
-
-    bool evaluateInStackFrame(JSContext *cx,
-                              const char *bytes, unsigned length,
-                              const char *filename, unsigned lineno,
-                              JS::MutableHandleValue rval);
-
-    bool evaluateUCInStackFrame(JSContext *cx,
-                                const jschar *chars, unsigned length,
-                                const char *filename, unsigned lineno,
-                                JS::MutableHandleValue rval);
-};
-
-class JS_PUBLIC_API(JSNullFramePtr) : public JSAbstractFramePtr
-{
-  public:
-    JSNullFramePtr()
-      : JSAbstractFramePtr()
-    {}
-};
-
-/*
- * This class does not work when IonMonkey is active. It's only used by jsd,
- * which can only be used when IonMonkey is disabled.
- *
- * To find the calling script and line number, use JS_DescribeSciptedCaller.
- * To summarize the call stack, use JS::DescribeStack.
- */
-class JS_PUBLIC_API(JSBrokenFrameIterator)
-{
-    void *data_;
-
-  public:
-    explicit JSBrokenFrameIterator(JSContext *cx);
-    ~JSBrokenFrameIterator();
-
-    bool done() const;
-    JSBrokenFrameIterator& operator++();
-
-    JSAbstractFramePtr abstractFramePtr() const;
-    jsbytecode *pc() const;
-
-    bool isConstructing() const;
-};
-
 
 /************************************************************************/
 
 /**
  * Add various profiling-related functions as properties of the given object.
  */
 extern JS_PUBLIC_API(bool)
 JS_DefineProfilingFunctions(JSContext *cx, JSObject *obj);
--- a/js/src/jit-test/tests/latin1/toLowerCase-toUpperCase.js
+++ b/js/src/jit-test/tests/latin1/toLowerCase-toUpperCase.js
@@ -27,19 +27,21 @@ function testToLowerCase() {
 testToLowerCase();
 
 function testToUpperCase() {
     var s1 = "abcdefgABCDEFGH 12345";
     assertEq(isLatin1(s1), true);
 
     // Latin1
     var s2 = s1.toUpperCase();
+    assertEq(isLatin1(s2), true);
     assertEq(s2, "ABCDEFGABCDEFGH 12345");
 
     s2 = s1.toLocaleUpperCase();
+    assertEq(isLatin1(s2), true);
     assertEq(s2, "ABCDEFGABCDEFGH 12345");
 
     // TwoByte
     s2 = "abcdefg\u1200ABCDEFGH 12345\u1E0F".toUpperCase();
     assertEq(s2, "ABCDEFG\u1200ABCDEFGH 12345\u1E0E");
 
     s2 = "abcdefg\u1200ABCDEFGH 12345\u1E0F".toLocaleUpperCase();
     assertEq(s2, "ABCDEFG\u1200ABCDEFGH 12345\u1E0E");
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -1789,17 +1789,17 @@ IonBuilder::inlineUnsafeSetReservedSlot(
 
     callInfo.setImplicitlyUsedUnchecked();
 
     MStoreFixedSlot *store = MStoreFixedSlot::New(alloc(), callInfo.getArg(0), slot, callInfo.getArg(2));
     current->add(store);
     current->push(store);
 
     if (NeedsPostBarrier(info(), callInfo.getArg(2)))
-        current->add(MPostWriteBarrier::New(alloc(), callInfo.thisArg(), callInfo.getArg(2)));
+        current->add(MPostWriteBarrier::New(alloc(), callInfo.getArg(0), callInfo.getArg(2)));
 
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningStatus
 IonBuilder::inlineUnsafeGetReservedSlot(CallInfo &callInfo)
 {
     if (callInfo.argc() != 2 || callInfo.constructing())
--- a/js/src/jit/arm/Simulator-arm.cpp
+++ b/js/src/jit/arm/Simulator-arm.cpp
@@ -1425,16 +1425,18 @@ ReturnType Simulator::getFromVFPRegister
     memcpy(&value, buffer, register_size * sizeof(vfp_registers_[0]));
     return value;
 }
 
 // These forced-instantiations are for jsapi-tests. Evidently, nothing
 // requires these to be instantiated.
 template double Simulator::getFromVFPRegister<double, 2>(int reg_index);
 template float Simulator::getFromVFPRegister<float, 1>(int reg_index);
+template void Simulator::setVFPRegister<double, 2>(int reg_index, const double& value);
+template void Simulator::setVFPRegister<float, 1>(int reg_index, const float& value);
 
 void
 Simulator::getFpArgs(double *x, double *y, int32_t *z)
 {
     if (UseHardFpABI()) {
         *x = get_double_from_d_register(0);
         *y = get_double_from_d_register(1);
         *z = get_register(0);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -798,26 +798,16 @@ JS_NumberValue(double d)
     return DOUBLE_TO_JSVAL(d);
 }
 
 /************************************************************************/
 
 JS_PUBLIC_API(bool)
 JS_StringHasBeenInterned(JSContext *cx, JSString *str);
 
-/*
- * Only JSStrings that have been interned via the JSAPI can be turned into
- * jsids by API clients.
- *
- * N.B. if a jsid is backed by a string which has not been interned, that
- * string must be appropriately rooted to avoid being collected by the GC.
- */
-JS_PUBLIC_API(jsid)
-INTERNED_STRING_TO_JSID(JSContext *cx, JSString *str);
-
 namespace JS {
 
 // Container class for passing in script source buffers to the JS engine.  This
 // not only groups the buffer and length values, it also provides a way to
 // optionally pass ownership of the buffer to the JS engine without copying.
 // Rules for use:
 //
 //  1) The data array must be allocated with js_malloc() or js_realloc() if
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -698,37 +698,54 @@ str_substring(JSContext *cx, unsigned ar
 }
 
 template <typename CharT>
 static JSString *
 ToLowerCase(JSContext *cx, JSLinearString *str)
 {
     // Unlike toUpperCase, toLowerCase has the nice invariant that if the input
     // is a Latin1 string, the output is also a Latin1 string.
+    UniquePtr<CharT[], JS::FreePolicy> newChars;
     size_t length = str->length();
-    ScopedJSFreePtr<CharT> newChars(cx->pod_malloc<CharT>(length + 1));
-    if (!newChars)
-        return nullptr;
-
     {
         AutoCheckCannotGC nogc;
         const CharT *chars = str->chars<CharT>(nogc);
-        for (size_t i = 0; i < length; i++) {
+
+        // Look for the first upper case character.
+        size_t i = 0;
+        for (; i < length; i++) {
+            jschar c = chars[i];
+            if (unicode::ToLowerCase(c) != c)
+                break;
+        }
+
+        // If all characters are lower case, return the input string.
+        if (i == length)
+            return str;
+
+        newChars = cx->make_pod_array<CharT>(length + 1);
+        if (!newChars)
+            return nullptr;
+
+        PodCopy(newChars.get(), chars, i);
+
+        for (; i < length; i++) {
             jschar c = unicode::ToLowerCase(chars[i]);
-            MOZ_ASSERT_IF((IsSame<CharT, Latin1Char>::value), c <= 0xff);
+            MOZ_ASSERT_IF((IsSame<CharT, Latin1Char>::value), c <= JSString::MAX_LATIN1_CHAR);
             newChars[i] = c;
         }
+
         newChars[length] = 0;
     }
 
     JSString *res = NewStringDontDeflate<CanGC>(cx, newChars.get(), length);
     if (!res)
         return nullptr;
 
-    newChars.forget();
+    newChars.release();
     return res;
 }
 
 static inline bool
 ToLowerCaseHelper(JSContext *cx, CallReceiver call)
 {
     RootedString str(cx, ThisToStringForStringProto(cx, call));
     if (!str)
@@ -775,40 +792,111 @@ str_toLocaleLowerCase(JSContext *cx, uns
 
         args.rval().set(result);
         return true;
     }
 
     return ToLowerCaseHelper(cx, args);
 }
 
+template <typename DestChar, typename SrcChar>
+static void
+ToUpperCaseImpl(DestChar *destChars, const SrcChar *srcChars, size_t firstLowerCase, size_t length)
+{
+    MOZ_ASSERT(firstLowerCase < length);
+
+    for (size_t i = 0; i < firstLowerCase; i++)
+        destChars[i] = srcChars[i];
+
+    for (size_t i = firstLowerCase; i < length; i++) {
+        jschar c = unicode::ToUpperCase(srcChars[i]);
+        MOZ_ASSERT_IF((IsSame<DestChar, Latin1Char>::value), c <= JSString::MAX_LATIN1_CHAR);
+        destChars[i] = c;
+    }
+
+    destChars[length] = '\0';
+}
+
 template <typename CharT>
 static JSString *
 ToUpperCase(JSContext *cx, JSLinearString *str)
 {
-    // toUpperCase on a Latin1 string can yield a non-Latin1 string. For now,
-    // we use a TwoByte string for the result.
+    typedef UniquePtr<Latin1Char[], JS::FreePolicy> Latin1CharPtr;
+    typedef UniquePtr<jschar[], JS::FreePolicy> TwoByteCharPtr;
+
+    mozilla::MaybeOneOf<Latin1CharPtr, TwoByteCharPtr> newChars;
     size_t length = str->length();
-    ScopedJSFreePtr<jschar> newChars(cx->pod_malloc<jschar>(length + 1));
-    if (!newChars)
-        return nullptr;
-
     {
         AutoCheckCannotGC nogc;
         const CharT *chars = str->chars<CharT>(nogc);
-        for (size_t i = 0; i < length; i++)
-            newChars[i] = unicode::ToUpperCase(chars[i]);
-        newChars[length] = 0;
+
+        // Look for the first lower case character.
+        size_t i = 0;
+        for (; i < length; i++) {
+            jschar c = chars[i];
+            if (unicode::ToUpperCase(c) != c)
+                break;
+        }
+
+        // If all characters are upper case, return the input string.
+        if (i == length)
+            return str;
+
+        // If the string is Latin1, check if it contains the MICRO SIGN (0xb5)
+        // or SMALL LETTER Y WITH DIAERESIS (0xff) character. The corresponding
+        // upper case characters are not in the Latin1 range.
+        bool resultIsLatin1;
+        if (IsSame<CharT, Latin1Char>::value) {
+            resultIsLatin1 = true;
+            for (size_t j = i; j < length; j++) {
+                Latin1Char c = chars[j];
+                if (c == 0xb5 || c == 0xff) {
+                    MOZ_ASSERT(unicode::ToUpperCase(c) > JSString::MAX_LATIN1_CHAR);
+                    resultIsLatin1 = false;
+                    break;
+                } else {
+                    MOZ_ASSERT(unicode::ToUpperCase(c) <= JSString::MAX_LATIN1_CHAR);
+                }
+            }
+        } else {
+            resultIsLatin1 = false;
+        }
+
+        if (resultIsLatin1) {
+            Latin1CharPtr buf = cx->make_pod_array<Latin1Char>(length + 1);
+            if (!buf)
+                return nullptr;
+
+            ToUpperCaseImpl(buf.get(), chars, i, length);
+            newChars.construct<Latin1CharPtr>(buf);
+        } else {
+            TwoByteCharPtr buf = cx->make_pod_array<jschar>(length + 1);
+            if (!buf)
+                return nullptr;
+
+            ToUpperCaseImpl(buf.get(), chars, i, length);
+            newChars.construct<TwoByteCharPtr>(buf);
+        }
     }
 
-    JSString *res = NewString<CanGC>(cx, newChars.get(), length);
-    if (!res)
-        return nullptr;
-
-    newChars.forget();
+    JSString *res;
+    if (newChars.constructed<Latin1CharPtr>()) {
+        res = NewStringDontDeflate<CanGC>(cx, newChars.ref<Latin1CharPtr>().get(), length);
+        if (!res)
+            return nullptr;
+
+        newChars.ref<Latin1CharPtr>().release();
+    } else {
+        res = NewStringDontDeflate<CanGC>(cx, newChars.ref<TwoByteCharPtr>().get(), length);
+        if (!res)
+            return nullptr;
+
+        newChars.ref<TwoByteCharPtr>().release();
+    }
+
     return res;
 }
 
 static bool
 ToUpperCaseHelper(JSContext *cx, CallReceiver call)
 {
     RootedString str(cx, ThisToStringForStringProto(cx, call));
     if (!str)
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -57,25 +57,29 @@
 #include "jit/arm/Simulator-arm.h"
 #include "jit/Ion.h"
 #include "js/OldDebugAPI.h"
 #include "js/StructuredClone.h"
 #include "perf/jsperf.h"
 #include "shell/jsheaptools.h"
 #include "shell/jsoptparse.h"
 #include "vm/ArgumentsObject.h"
+#include "vm/Debugger.h"
 #include "vm/HelperThreads.h"
 #include "vm/Monitor.h"
 #include "vm/Shape.h"
 #include "vm/TypedArrayObject.h"
 #include "vm/WrapperObject.h"
 
 #include "jscompartmentinlines.h"
 #include "jsobjinlines.h"
 
+#include "vm/Interpreter-inl.h"
+#include "vm/Stack-inl.h"
+
 #ifdef XP_WIN
 # define PATH_MAX (MAX_PATH > _MAX_DIR ? MAX_PATH : _MAX_DIR)
 #else
 # include <libgen.h>
 #endif
 
 using namespace js;
 using namespace js::cli;
@@ -2672,24 +2676,39 @@ EvalInFrame(JSContext *cx, unsigned argc
             return false;
         ac.construct(cx, DefaultObjectForContextOrNull(cx));
     }
 
     AutoStableStringChars stableChars(cx);
     if (!stableChars.initTwoByte(cx, str))
         return JSTRAP_ERROR;
 
-    mozilla::Range<const jschar> chars = stableChars.twoByteRange();
-    JSAbstractFramePtr frame(fi.abstractFramePtr().raw(), fi.pc());
+    AbstractFramePtr frame = fi.abstractFramePtr();
     RootedScript fpscript(cx, frame.script());
-    bool ok = !!frame.evaluateUCInStackFrame(cx, chars.start().get(), chars.length(),
-                                             fpscript->filename(),
-                                             JS_PCToLineNumber(cx, fpscript,
-                                                               fi.pc()),
-                                             MutableHandleValue::fromMarkedLocation(vp));
+
+    RootedObject scope(cx);
+    {
+        RootedObject scopeChain(cx, frame.scopeChain());
+        AutoCompartment ac(cx, scopeChain);
+        scope = GetDebugScopeForFrame(cx, frame, fi.pc());
+    }
+    Rooted<Env*> env(cx, scope);
+    if (!env)
+        return false;
+
+    if (!ComputeThis(cx, frame))
+        return false;
+    RootedValue thisv(cx, frame.thisValue());
+
+    bool ok;
+    {
+        AutoCompartment ac(cx, env);
+        ok = EvaluateInEnv(cx, env, thisv, frame, stableChars.twoByteRange(), fpscript->filename(),
+                           JS_PCToLineNumber(cx, fpscript, fi.pc()), args.rval());
+    }
     return ok;
 }
 
 struct WorkerInput
 {
     JSRuntime *runtime;
     jschar *chars;
     size_t length;
--- a/js/src/vm/OldDebugAPI.cpp
+++ b/js/src/vm/OldDebugAPI.cpp
@@ -496,180 +496,8 @@ JS::FormatStackDump(JSContext *cx, char 
         num++;
     }
 
     if (!num)
         buf = JS_sprintf_append(buf, "JavaScript stack is empty\n");
 
     return buf;
 }
-
-JSAbstractFramePtr::JSAbstractFramePtr(void *raw, jsbytecode *pc)
-  : ptr_(uintptr_t(raw)), pc_(pc)
-{ }
-
-JSObject *
-JSAbstractFramePtr::scopeChain(JSContext *cx)
-{
-    AbstractFramePtr frame(*this);
-    RootedObject scopeChain(cx, frame.scopeChain());
-    AutoCompartment ac(cx, scopeChain);
-    return GetDebugScopeForFrame(cx, frame, pc());
-}
-
-JSObject *
-JSAbstractFramePtr::callObject(JSContext *cx)
-{
-    AbstractFramePtr frame(*this);
-    if (!frame.isFunctionFrame())
-        return nullptr;
-
-    JSObject *o = GetDebugScopeForFrame(cx, frame, pc());
-
-    /*
-     * Given that fp is a function frame and GetDebugScopeForFrame always fills
-     * in missing scopes, we can expect to find fp's CallObject on 'o'. Note:
-     *  - GetDebugScopeForFrame wraps every ScopeObject (missing or not) with
-     *    a DebugScopeObject proxy.
-     *  - If fp is an eval-in-function, then fp has no callobj of its own and
-     *    JS_GetFrameCallObject will return the innermost function's callobj.
-     */
-    while (o) {
-        ScopeObject &scope = o->as<DebugScopeObject>().scope();
-        if (scope.is<CallObject>())
-            return o;
-        o = o->enclosingScope();
-    }
-    return nullptr;
-}
-
-JSFunction *
-JSAbstractFramePtr::maybeFun()
-{
-    AbstractFramePtr frame(*this);
-    return frame.maybeFun();
-}
-
-JSScript *
-JSAbstractFramePtr::script()
-{
-    AbstractFramePtr frame(*this);
-    return frame.script();
-}
-
-bool
-JSAbstractFramePtr::getThisValue(JSContext *cx, MutableHandleValue thisv)
-{
-    AbstractFramePtr frame(*this);
-
-    RootedObject scopeChain(cx, frame.scopeChain());
-    js::AutoCompartment ac(cx, scopeChain);
-    if (!ComputeThis(cx, frame))
-        return false;
-
-    thisv.set(frame.thisValue());
-    return true;
-}
-
-bool
-JSAbstractFramePtr::isDebuggerFrame()
-{
-    AbstractFramePtr frame(*this);
-    return frame.isDebuggerFrame();
-}
-
-bool
-JSAbstractFramePtr::evaluateInStackFrame(JSContext *cx,
-                                         const char *bytes, unsigned length,
-                                         const char *filename, unsigned lineno,
-                                         MutableHandleValue rval)
-{
-    if (!CheckDebugMode(cx))
-        return false;
-
-    size_t len = length;
-    jschar *chars = InflateString(cx, bytes, &len);
-    if (!chars)
-        return false;
-    length = (unsigned) len;
-
-    bool ok = evaluateUCInStackFrame(cx, chars, length, filename, lineno, rval);
-    js_free(chars);
-
-    return ok;
-}
-
-bool
-JSAbstractFramePtr::evaluateUCInStackFrame(JSContext *cx,
-                                           const jschar *chars, unsigned length,
-                                           const char *filename, unsigned lineno,
-                                           MutableHandleValue rval)
-{
-    if (!CheckDebugMode(cx))
-        return false;
-
-    RootedObject scope(cx, scopeChain(cx));
-    Rooted<Env*> env(cx, scope);
-    if (!env)
-        return false;
-
-    AbstractFramePtr frame(*this);
-    if (!ComputeThis(cx, frame))
-        return false;
-    RootedValue thisv(cx, frame.thisValue());
-
-    js::AutoCompartment ac(cx, env);
-    return EvaluateInEnv(cx, env, thisv, frame, mozilla::Range<const jschar>(chars, length),
-                         filename, lineno, rval);
-}
-
-JSBrokenFrameIterator::JSBrokenFrameIterator(JSContext *cx)
-{
-    // Show all frames on the stack whose principal is subsumed by the current principal.
-    NonBuiltinScriptFrameIter iter(cx,
-                                   ScriptFrameIter::ALL_CONTEXTS,
-                                   ScriptFrameIter::GO_THROUGH_SAVED,
-                                   cx->compartment()->principals);
-    data_ = iter.copyData();
-}
-
-JSBrokenFrameIterator::~JSBrokenFrameIterator()
-{
-    js_free((ScriptFrameIter::Data *)data_);
-}
-
-bool
-JSBrokenFrameIterator::done() const
-{
-    NonBuiltinScriptFrameIter iter(*(ScriptFrameIter::Data *)data_);
-    return iter.done();
-}
-
-JSBrokenFrameIterator &
-JSBrokenFrameIterator::operator++()
-{
-    ScriptFrameIter::Data *data = (ScriptFrameIter::Data *)data_;
-    NonBuiltinScriptFrameIter iter(*data);
-    ++iter;
-    *data = iter.data_;
-    return *this;
-}
-
-JSAbstractFramePtr
-JSBrokenFrameIterator::abstractFramePtr() const
-{
-    NonBuiltinScriptFrameIter iter(*(ScriptFrameIter::Data *)data_);
-    return JSAbstractFramePtr(iter.abstractFramePtr().raw(), iter.pc());
-}
-
-jsbytecode *
-JSBrokenFrameIterator::pc() const
-{
-    NonBuiltinScriptFrameIter iter(*(ScriptFrameIter::Data *)data_);
-    return iter.pc();
-}
-
-bool
-JSBrokenFrameIterator::isConstructing() const
-{
-    NonBuiltinScriptFrameIter iter(*(ScriptFrameIter::Data *)data_);
-    return iter.isConstructing();
-}
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -130,21 +130,16 @@ class AbstractFramePtr
     }
 
     MOZ_IMPLICIT AbstractFramePtr(jit::RematerializedFrame *fp)
       : ptr_(fp ? uintptr_t(fp) | Tag_RematerializedFrame : 0)
     {
         MOZ_ASSERT_IF(fp, asRematerializedFrame() == fp);
     }
 
-    explicit AbstractFramePtr(JSAbstractFramePtr frame)
-        : ptr_(uintptr_t(frame.raw()))
-    {
-    }
-
     static AbstractFramePtr FromRaw(void *raw) {
         AbstractFramePtr frame;
         frame.ptr_ = uintptr_t(raw);
         return frame;
     }
 
     bool isScriptFrameIterData() const {
         return !!ptr_ && (ptr_ & TagMask) == Tag_ScriptFrameIterData;
@@ -1674,18 +1669,16 @@ class FrameIter
     jit::InlineFrameIterator ionInlineFrames_;
 
     void popActivation();
     void popInterpreterFrame();
     void nextJitFrame();
     void popJitFrame();
     void popAsmJSFrame();
     void settleOnActivation();
-
-    friend class ::JSBrokenFrameIterator;
 };
 
 class ScriptFrameIter : public FrameIter
 {
     void settle() {
         while (!done() && !hasScript())
             FrameIter::operator++();
     }
--- a/js/xpconnect/idl/nsIXPConnect.idl
+++ b/js/xpconnect/idl/nsIXPConnect.idl
@@ -269,17 +269,17 @@ interface nsIXPCFunctionThisTranslator :
 %{ C++
 // For use with the service manager
 // {CB6593E0-F9B2-11d2-BDD6-000064657374}
 #define NS_XPCONNECT_CID \
 { 0xcb6593e0, 0xf9b2, 0x11d2, \
     { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
 %}
 
-[noscript, uuid(9ec7367c-0dde-4b7a-963c-5a590ee3ee42)]
+[noscript, uuid(89b8525d-5c22-48bd-8a79-66aac9cd705e)]
 interface nsIXPConnect : nsISupports
 {
 %{ C++
   NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCONNECT_CID)
 %}
 
     /**
      * Creates a new global object using the given aCOMObj as the global
@@ -429,18 +429,16 @@ interface nsIXPConnect : nsISupports
     readonly attribute nsIStackFrame                CurrentJSStack;
     readonly attribute nsAXPCNativeCallContextPtr   CurrentNativeCallContext;
 
     void debugDump(in short depth);
     void debugDumpObject(in nsISupports aCOMObj, in short depth);
     void debugDumpJSStack(in boolean showArgs,
                           in boolean showLocals,
                           in boolean showThisProps);
-    void debugDumpEvalInJSStackFrame(in uint32_t aFrameNumber,
-                                     in string aSourceText);
 
     /**
     * wrapJSAggregatedToNative is just like wrapJS except it is used in cases
     * where the JSObject is also aggregated to some native xpcom Object.
     * At present XBL is the only system that might want to do this.
     *
     * XXX write more!
     *
--- a/js/xpconnect/src/XPCDebug.cpp
+++ b/js/xpconnect/src/XPCDebug.cpp
@@ -50,65 +50,8 @@ xpc_PrintJSStack(JSContext* cx, bool sho
 
     char *buf = JS::FormatStackDump(cx, nullptr, showArgs, showLocals, showThisProps);
     if (!buf)
         DebugDump("%s", "Failed to format JavaScript stack for dump\n");
 
     state.restore();
     return buf;
 }
-
-/***************************************************************************/
-
-static void
-xpcDumpEvalErrorReporter(JSContext *cx, const char *message,
-                         JSErrorReport *report)
-{
-    DebugDump("Error: %s\n", message);
-}
-
-bool
-xpc_DumpEvalInJSStackFrame(JSContext* cx, uint32_t frameno, const char* text)
-{
-    if (!cx || !text) {
-        DebugDump("%s", "invalid params passed to xpc_DumpEvalInJSStackFrame!\n");
-        return false;
-    }
-
-    DebugDump("js[%d]> %s\n", frameno, text);
-
-    uint32_t num = 0;
-
-    JSAbstractFramePtr frame = JSNullFramePtr();
-
-    JSBrokenFrameIterator iter(cx);
-    while (!iter.done()) {
-        if (num == frameno) {
-            frame = iter.abstractFramePtr();
-            break;
-        }
-        ++iter;
-        num++;
-    }
-
-    if (!frame) {
-        DebugDump("%s", "invalid frame number!\n");
-        return false;
-    }
-
-    JS::AutoSaveExceptionState exceptionState(cx);
-    JSErrorReporter older = JS_SetErrorReporter(cx, xpcDumpEvalErrorReporter);
-
-    JS::RootedValue rval(cx);
-    JSString* str;
-    JSAutoByteString bytes;
-    if (frame.evaluateInStackFrame(cx, text, strlen(text), "eval", 1, &rval) &&
-        nullptr != (str = ToString(cx, rval)) &&
-        bytes.encodeLatin1(cx, str)) {
-        DebugDump("%s\n", bytes.ptr());
-    } else {
-        DebugDump("%s", "eval failed!\n");
-    }
-
-    JS_SetErrorReporter(cx, older);
-    exceptionState.restore();
-    return true;
-}
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -940,29 +940,16 @@ nsXPConnect::DebugPrintJSStack(bool show
     if (!cx)
         printf("there is no JSContext on the nsIThreadJSContextStack!\n");
     else
         return xpc_PrintJSStack(cx, showArgs, showLocals, showThisProps);
 
     return nullptr;
 }
 
-/* void debugDumpEvalInJSStackFrame (in uint32_t aFrameNumber, in string aSourceText); */
-NS_IMETHODIMP
-nsXPConnect::DebugDumpEvalInJSStackFrame(uint32_t aFrameNumber, const char *aSourceText)
-{
-    JSContext* cx = GetCurrentJSContext();
-    if (!cx)
-        printf("there is no JSContext on the nsIThreadJSContextStack!\n");
-    else
-        xpc_DumpEvalInJSStackFrame(cx, aFrameNumber, aSourceText);
-
-    return NS_OK;
-}
-
 /* jsval variantToJS (in JSContextPtr ctx, in JSObjectPtr scope, in nsIVariant value); */
 NS_IMETHODIMP
 nsXPConnect::VariantToJS(JSContext* ctx, JSObject* scopeArg, nsIVariant* value,
                          MutableHandleValue _retval)
 {
     NS_PRECONDITION(ctx, "bad param");
     NS_PRECONDITION(scopeArg, "bad param");
     NS_PRECONDITION(value, "bad param");
@@ -1403,26 +1390,16 @@ JS_EXPORT_API(char*) PrintJSStack()
 {
     nsresult rv;
     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
     return (NS_SUCCEEDED(rv) && xpc) ?
         xpc->DebugPrintJSStack(true, true, false) :
         nullptr;
 }
 
-JS_EXPORT_API(void) DumpJSEval(uint32_t frameno, const char* text)
-{
-    nsresult rv;
-    nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
-    if (NS_SUCCEEDED(rv) && xpc)
-        xpc->DebugDumpEvalInJSStackFrame(frameno, text);
-    else
-        printf("failed to get XPConnect service!\n");
-}
-
 JS_EXPORT_API(void) DumpCompleteHeap()
 {
     nsCOMPtr<nsICycleCollectorListener> listener =
       do_CreateInstance("@mozilla.org/cycle-collector-logger;1");
     if (!listener) {
       NS_WARNING("Failed to create CC logger");
       return;
     }
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2962,20 +2962,16 @@ xpc_DumpJSStack(JSContext* cx, bool show
 
 // Return a newly-allocated string containing a representation of the
 // current JS stack.  It is the *caller's* responsibility to free this
 // string with JS_smprintf_free().
 extern char*
 xpc_PrintJSStack(JSContext* cx, bool showArgs, bool showLocals,
                  bool showThisProps);
 
-extern bool
-xpc_DumpEvalInJSStackFrame(JSContext* cx, uint32_t frameno, const char* text);
-
-
 /***************************************************************************/
 
 // Definition of nsScriptError, defined here because we lack a place to put
 // XPCOM objects associated with the JavaScript engine.
 class nsScriptError : public nsIScriptError {
 public:
     nsScriptError();
 
--- a/layout/reftests/reftest.list
+++ b/layout/reftests/reftest.list
@@ -44,17 +44,17 @@ include box-properties/reftest.list
 # box-shadow/
 include box-shadow/reftest.list
 
 # bugs/
 include bugs/reftest.list
 
 # canvas
 include canvas/reftest.list
-skip-if(xulFennec) include ../../dom/canvas/test/reftest/reftest.list
+include ../../dom/canvas/test/reftest/reftest.list
 
 # css animations
 include css-animations/reftest.list
 
 # blending/
 include css-blending/reftest.list
 
 # Tests for the css-break spec
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -12240,17 +12240,18 @@ AppendGeneric(nsCSSKeyword aKeyword, Fon
   }
 
   return false;
 }
 
 bool
 CSSParserImpl::ParseFamily(nsCSSValue& aValue)
 {
-  nsRefPtr<FontFamilyList> familyList = new FontFamilyList();
+  nsRefPtr<css::FontFamilyListRefCnt> familyList =
+    new css::FontFamilyListRefCnt();
   nsAutoString family;
   bool single, quoted;
 
   // keywords only have meaning in the first position
   if (!ParseOneFamily(family, single, quoted))
     return false;
 
   // check for keywords, but only when keywords appear by themselves
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -106,17 +106,17 @@ nsCSSValue::nsCSSValue(nsCSSValueTokenSt
 
 nsCSSValue::nsCSSValue(mozilla::css::GridTemplateAreasValue* aValue)
   : mUnit(eCSSUnit_GridTemplateAreas)
 {
   mValue.mGridTemplateAreas = aValue;
   mValue.mGridTemplateAreas->AddRef();
 }
 
-nsCSSValue::nsCSSValue(FontFamilyList* aValue)
+nsCSSValue::nsCSSValue(css::FontFamilyListRefCnt* aValue)
   : mUnit(eCSSUnit_FontFamilyList)
 {
   mValue.mFontFamilyList = aValue;
   mValue.mFontFamilyList->AddRef();
 }
 
 nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
   : mUnit(aCopy.mUnit)
@@ -486,17 +486,17 @@ void nsCSSValue::SetTokenStreamValue(nsC
 void nsCSSValue::SetGridTemplateAreas(mozilla::css::GridTemplateAreasValue* aValue)
 {
   Reset();
   mUnit = eCSSUnit_GridTemplateAreas;
   mValue.mGridTemplateAreas = aValue;
   mValue.mGridTemplateAreas->AddRef();
 }
 
-void nsCSSValue::SetFontFamilyListValue(FontFamilyList* aValue)
+void nsCSSValue::SetFontFamilyListValue(css::FontFamilyListRefCnt* aValue)
 {
   Reset();
   mUnit = eCSSUnit_FontFamilyList;
   mValue.mFontFamilyList = aValue;
   mValue.mFontFamilyList->AddRef();
 }
 
 void nsCSSValue::SetPairValue(const nsCSSValuePair* aValue)
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -195,16 +195,51 @@ private:
   {
   }
 
   GridTemplateAreasValue(const GridTemplateAreasValue& aOther) MOZ_DELETE;
   GridTemplateAreasValue&
   operator=(const GridTemplateAreasValue& aOther) MOZ_DELETE;
 };
 
+class FontFamilyListRefCnt MOZ_FINAL : public FontFamilyList {
+public:
+    FontFamilyListRefCnt()
+        : FontFamilyList()
+    {
+        MOZ_COUNT_CTOR(FontFamilyListRefCnt);
+    }
+
+    FontFamilyListRefCnt(FontFamilyType aGenericType)
+        : FontFamilyList(aGenericType)
+    {
+        MOZ_COUNT_CTOR(FontFamilyListRefCnt);
+    }
+
+    FontFamilyListRefCnt(const nsAString& aFamilyName,
+                         QuotedName aQuoted)
+        : FontFamilyList(aFamilyName, aQuoted)
+    {
+        MOZ_COUNT_CTOR(FontFamilyListRefCnt);
+    }
+
+    FontFamilyListRefCnt(const FontFamilyListRefCnt& aOther)
+        : FontFamilyList(aOther)
+    {
+        MOZ_COUNT_CTOR(FontFamilyListRefCnt);
+    }
+
+    NS_INLINE_DECL_REFCOUNTING(FontFamilyListRefCnt);
+
+private:
+    ~FontFamilyListRefCnt() {
+        MOZ_COUNT_DTOR(FontFamilyListRefCnt);
+    }
+};
+
 }
 }
 
 enum nsCSSUnit {
   eCSSUnit_Null         = 0,      // (n/a) null unit, value is not specified
   eCSSUnit_Auto         = 1,      // (n/a) value is algorithmic
   eCSSUnit_Inherit      = 2,      // (n/a) value is inherited
   eCSSUnit_Initial      = 3,      // (n/a) value is default UA value
@@ -366,17 +401,17 @@ public:
   nsCSSValue(float aValue, nsCSSUnit aUnit);
   nsCSSValue(const nsString& aValue, nsCSSUnit aUnit);
   nsCSSValue(Array* aArray, nsCSSUnit aUnit);
   explicit nsCSSValue(mozilla::css::URLValue* aValue);
   explicit nsCSSValue(mozilla::css::ImageValue* aValue);
   explicit nsCSSValue(nsCSSValueGradient* aValue);
   explicit nsCSSValue(nsCSSValueTokenStream* aValue);
   explicit nsCSSValue(mozilla::css::GridTemplateAreasValue* aValue);
-  explicit nsCSSValue(mozilla::FontFamilyList* aValue);
+  explicit nsCSSValue(mozilla::css::FontFamilyListRefCnt* aValue);
   nsCSSValue(const nsCSSValue& aCopy);
   ~nsCSSValue() { Reset(); }
 
   nsCSSValue&  operator=(const nsCSSValue& aCopy);
   bool        operator==(const nsCSSValue& aOther) const;
 
   bool operator!=(const nsCSSValue& aOther) const
   {
@@ -634,17 +669,17 @@ public:
                           float aComponent3,
                           float aAlpha, nsCSSUnit aUnit);
   void SetArrayValue(nsCSSValue::Array* aArray, nsCSSUnit aUnit);
   void SetURLValue(mozilla::css::URLValue* aURI);
   void SetImageValue(mozilla::css::ImageValue* aImage);
   void SetGradientValue(nsCSSValueGradient* aGradient);
   void SetTokenStreamValue(nsCSSValueTokenStream* aTokenStream);
   void SetGridTemplateAreas(mozilla::css::GridTemplateAreasValue* aValue);
-  void SetFontFamilyListValue(mozilla::FontFamilyList* aFontListValue);
+  void SetFontFamilyListValue(mozilla::css::FontFamilyListRefCnt* aFontListValue);
   void SetPairValue(const nsCSSValuePair* aPair);
   void SetPairValue(const nsCSSValue& xValue, const nsCSSValue& yValue);
   void SetSharedListValue(nsCSSValueSharedList* aList);
   void SetDependentListValue(nsCSSValueList* aList);
   void SetDependentPairListValue(nsCSSValuePairList* aList);
   void SetTripletValue(const nsCSSValueTriplet* aTriplet);
   void SetTripletValue(const nsCSSValue& xValue, const nsCSSValue& yValue, const nsCSSValue& zValue);
   void SetAutoValue();
@@ -702,17 +737,17 @@ protected:
     nsCSSRect_heap* mRect;
     nsCSSValueTriplet_heap* mTriplet;
     nsCSSValueList_heap* mList;
     nsCSSValueList* mListDependent;
     nsCSSValueSharedList* mSharedList;
     nsCSSValuePairList_heap* mPairList;
     nsCSSValuePairList* mPairListDependent;
     nsCSSValueFloatColor* mFloatColor;
-    mozilla::FontFamilyList* mFontFamilyList;
+    mozilla::css::FontFamilyListRefCnt* mFontFamilyList;
   } mValue;
 };
 
 struct nsCSSValue::Array MOZ_FINAL {
 
   // return |Array| with reference count of zero
   static Array* Create(size_t aItemCount) {
     return new (aItemCount) Array(aItemCount);
--- a/layout/tools/reftest/reftest.js
+++ b/layout/tools/reftest/reftest.js
@@ -753,20 +753,16 @@ function BuildConditionSandbox(aURL) {
     sandbox.browserIsRemote = gBrowserIsRemote;
 
     try {
         sandbox.asyncPanZoom = prefs.getBoolPref("layers.async-pan-zoom.enabled");
     } catch (e) {
         sandbox.asyncPanZoom = false;
     }
 
-    // Distinguish the Fennecs:
-    sandbox.xulFennec    = sandbox.Android &&  sandbox.browserIsRemote;
-    sandbox.nativeFennec = sandbox.Android && !sandbox.browserIsRemote;
-
     if (!gDumpedConditionSandbox) {
         dump("REFTEST INFO | Dumping JSON representation of sandbox \n");
         dump("REFTEST INFO | " + JSON.stringify(sandbox) + " \n");
         gDumpedConditionSandbox = true;
     }
     return sandbox;
 }
 
--- a/media/libstagefright/binding/include/mp4_demuxer/mp4_demuxer.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/mp4_demuxer.h
@@ -62,11 +62,12 @@ public:
 
 private:
   AudioDecoderConfig mAudioConfig;
   VideoDecoderConfig mVideoConfig;
   CryptoFile mCrypto;
 
   nsAutoPtr<StageFrightPrivate> mPrivate;
 };
-}
 
-#endif
+} // namespace mozilla
+
+#endif // MP4_DEMUXER_H_
--- a/mfbt/RefPtr.h
+++ b/mfbt/RefPtr.h
@@ -387,166 +387,9 @@ template<typename T>
 OutParamRef<T>
 byRef(RefPtr<T>& aPtr)
 {
   return OutParamRef<T>(aPtr);
 }
 
 } // namespace mozilla
 
-#if 0
-
-// Command line that builds these tests
-//
-//   cp RefPtr.h test.cc && g++ -g -Wall -pedantic -DDEBUG -o test test.cc && ./test
-
-using namespace mozilla;
-
-struct Foo : public RefCounted<Foo>
-{
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(Foo)
-  Foo() : mDead(false) {}
-  ~Foo()
-  {
-    MOZ_ASSERT(!mDead);
-    mDead = true;
-    sNumDestroyed++;
-  }
-
-  bool mDead;
-  static int sNumDestroyed;
-};
-int Foo::sNumDestroyed;
-
-struct Bar : public Foo {};
-
-TemporaryRef<Foo>
-NewFoo()
-{
-  return RefPtr<Foo>(new Foo());
-}
-
-TemporaryRef<Foo>
-NewBar()
-{
-  return new Bar();
-}
-
-void
-GetNewFoo(Foo** f)
-{
-  *f = new Bar();
-  // Kids, don't try this at home
-  (*f)->AddRef();
-}
-
-void
-GetPassedFoo(Foo** f)
-{
-  // Kids, don't try this at home
-  (*f)->AddRef();
-}
-
-void
-GetNewFoo(RefPtr<Foo>* f)
-{
-  *f = new Bar();
-}
-
-void
-GetPassedFoo(RefPtr<Foo>* f)
-{}
-
-TemporaryRef<Foo>
-GetNullFoo()
-{
-  return 0;
-}
-
-int
-main(int argc, char** argv)
-{
-  // This should blow up
-//    Foo* f = new Foo(); delete f;
-
-  MOZ_ASSERT(0 == Foo::sNumDestroyed);
-  {
-    RefPtr<Foo> f = new Foo();
-    MOZ_ASSERT(f->refCount() == 1);
-  }
-  MOZ_ASSERT(1 == Foo::sNumDestroyed);
-
-  {
-    RefPtr<Foo> f1 = NewFoo();
-    RefPtr<Foo> f2(NewFoo());
-    MOZ_ASSERT(1 == Foo::sNumDestroyed);
-  }
-  MOZ_ASSERT(3 == Foo::sNumDestroyed);
-
-  {
-    RefPtr<Foo> b = NewBar();
-    MOZ_ASSERT(3 == Foo::sNumDestroyed);
-  }
-  MOZ_ASSERT(4 == Foo::sNumDestroyed);
-
-  {
-    RefPtr<Foo> f1;
-    {
-      f1 = new Foo();
-      RefPtr<Foo> f2(f1);
-      RefPtr<Foo> f3 = f2;
-      MOZ_ASSERT(4 == Foo::sNumDestroyed);
-    }
-    MOZ_ASSERT(4 == Foo::sNumDestroyed);
-  }
-  MOZ_ASSERT(5 == Foo::sNumDestroyed);
-
-  {
-    RefPtr<Foo> f = new Foo();
-    f.forget();
-    MOZ_ASSERT(6 == Foo::sNumDestroyed);
-  }
-
-  {
-    RefPtr<Foo> f = new Foo();
-    GetNewFoo(byRef(f));
-    MOZ_ASSERT(7 == Foo::sNumDestroyed);
-  }
-  MOZ_ASSERT(8 == Foo::sNumDestroyed);
-
-  {
-    RefPtr<Foo> f = new Foo();
-    GetPassedFoo(byRef(f));
-    MOZ_ASSERT(8 == Foo::sNumDestroyed);
-  }
-  MOZ_ASSERT(9 == Foo::sNumDestroyed);
-
-  {
-    RefPtr<Foo> f = new Foo();
-    GetNewFoo(&f);
-    MOZ_ASSERT(10 == Foo::sNumDestroyed);
-  }
-  MOZ_ASSERT(11 == Foo::sNumDestroyed);
-
-  {
-    RefPtr<Foo> f = new Foo();
-    GetPassedFoo(&f);
-    MOZ_ASSERT(11 == Foo::sNumDestroyed);
-  }
-  MOZ_ASSERT(12 == Foo::sNumDestroyed);
-
-  {
-    RefPtr<Foo> f1 = new Bar();
-  }
-  MOZ_ASSERT(13 == Foo::sNumDestroyed);
-
-  {
-    RefPtr<Foo> f = GetNullFoo();
-    MOZ_ASSERT(13 == Foo::sNumDestroyed);
-  }
-  MOZ_ASSERT(13 == Foo::sNumDestroyed);
-
-  return 0;
-}
-
-#endif
-
 #endif /* mozilla_RefPtr_h */
new file mode 100644
--- /dev/null
+++ b/mfbt/tests/TestRefPtr.cpp
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/RefPtr.h"
+
+using mozilla::RefCounted;
+using mozilla::RefPtr;
+using mozilla::TemporaryRef;
+
+class Foo : public RefCounted<Foo>
+{
+public:
+  MOZ_DECLARE_REFCOUNTED_TYPENAME(Foo)
+
+  Foo() : mDead(false) {}
+
+  static int sNumDestroyed;
+
+  ~Foo()
+  {
+    MOZ_ASSERT(!mDead);
+    mDead = true;
+    sNumDestroyed++;
+  }
+
+private:
+  bool mDead;
+};
+int Foo::sNumDestroyed;
+
+struct Bar : public Foo {};
+
+TemporaryRef<Foo>
+NewFoo()
+{
+  return RefPtr<Foo>(new Foo());
+}
+
+TemporaryRef<Foo>
+NewBar()
+{
+  return new Bar();
+}
+
+void
+GetNewFoo(Foo** aFoo)
+{
+  *aFoo = new Bar();
+  // Kids, don't try this at home
+  (*aFoo)->AddRef();
+}
+
+void
+GetPassedFoo(Foo** aFoo)
+{
+  // Kids, don't try this at home
+  (*aFoo)->AddRef();
+}
+
+void
+GetNewFoo(RefPtr<Foo>* aFoo)
+{
+  *aFoo = new Bar();
+}
+
+void
+GetPassedFoo(RefPtr<Foo>* aFoo)
+{}
+
+TemporaryRef<Foo>
+GetNullFoo()
+{
+  return 0;
+}
+
+int
+main()
+{
+  MOZ_RELEASE_ASSERT(0 == Foo::sNumDestroyed);
+  {
+    RefPtr<Foo> f = new Foo();
+    MOZ_RELEASE_ASSERT(f->refCount() == 1);
+  }
+  MOZ_RELEASE_ASSERT(1 == Foo::sNumDestroyed);
+
+  {
+    RefPtr<Foo> f1 = NewFoo();
+    RefPtr<Foo> f2(NewFoo());
+    MOZ_RELEASE_ASSERT(1 == Foo::sNumDestroyed);
+  }
+  MOZ_RELEASE_ASSERT(3 == Foo::sNumDestroyed);
+
+  {
+    RefPtr<Foo> b = NewBar();
+    MOZ_RELEASE_ASSERT(3 == Foo::sNumDestroyed);
+  }
+  MOZ_RELEASE_ASSERT(4 == Foo::sNumDestroyed);
+
+  {
+    RefPtr<Foo> f1;
+    {
+      f1 = new Foo();
+      RefPtr<Foo> f2(f1);
+      RefPtr<Foo> f3 = f2;
+      MOZ_RELEASE_ASSERT(4 == Foo::sNumDestroyed);
+    }
+    MOZ_RELEASE_ASSERT(4 == Foo::sNumDestroyed);
+  }
+  MOZ_RELEASE_ASSERT(5 == Foo::sNumDestroyed);
+
+  {
+    RefPtr<Foo> f = new Foo();
+    f.forget();
+    MOZ_RELEASE_ASSERT(6 == Foo::sNumDestroyed);
+  }
+
+  {
+    RefPtr<Foo> f = new Foo();
+    GetNewFoo(byRef(f));
+    MOZ_RELEASE_ASSERT(7 == Foo::sNumDestroyed);
+  }
+  MOZ_RELEASE_ASSERT(8 == Foo::sNumDestroyed);
+
+  {
+    RefPtr<Foo> f = new Foo();
+    GetPassedFoo(byRef(f));
+    MOZ_RELEASE_ASSERT(8 == Foo::sNumDestroyed);
+  }
+  MOZ_RELEASE_ASSERT(9 == Foo::sNumDestroyed);
+
+  {
+    RefPtr<Foo> f = new Foo();
+    GetNewFoo(&f);
+    MOZ_RELEASE_ASSERT(10 == Foo::sNumDestroyed);
+  }
+  MOZ_RELEASE_ASSERT(11 == Foo::sNumDestroyed);
+
+  {
+    RefPtr<Foo> f = new Foo();
+    GetPassedFoo(&f);
+    MOZ_RELEASE_ASSERT(11 == Foo::sNumDestroyed);
+  }
+  MOZ_RELEASE_ASSERT(12 == Foo::sNumDestroyed);
+
+  {
+    RefPtr<Foo> f1 = new Bar();
+  }
+  MOZ_RELEASE_ASSERT(13 == Foo::sNumDestroyed);
+
+  {
+    RefPtr<Foo> f = GetNullFoo();
+    MOZ_RELEASE_ASSERT(13 == Foo::sNumDestroyed);
+  }
+  MOZ_RELEASE_ASSERT(13 == Foo::sNumDestroyed);
+
+  return 0;
+}
+
--- a/mfbt/tests/moz.build
+++ b/mfbt/tests/moz.build
@@ -16,16 +16,17 @@ CPP_UNIT_TESTS += [
     'TestCountZeroes',
     'TestEndian',
     'TestEnumSet',
     'TestFloatingPoint',
     'TestIntegerPrintfMacros',
     'TestMacroArgs',
     'TestMacroForEach',
     'TestPair',
+    'TestRefPtr',
     'TestRollingMean',
     'TestSHA1',
     'TestTypedEnum',
     'TestTypeTraits',
     'TestUniquePtr',
     'TestWeakPtr',
 ]
 
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -265,16 +265,17 @@ pref("media.wave.enabled", true);
 #ifdef MOZ_WEBM
 pref("media.webm.enabled", true);
 #endif
 #ifdef MOZ_GSTREAMER
 pref("media.gstreamer.enabled", true);
 #endif
 #ifdef MOZ_APPLEMEDIA
 pref("media.apple.mp3.enabled", true);
+pref("media.apple.mp4.enabled", true);
 #endif
 #ifdef MOZ_WEBRTC
 pref("media.navigator.enabled", true);
 pref("media.navigator.video.enabled", true);
 pref("media.navigator.load_adapt", true);
 pref("media.navigator.load_adapt.measure_interval",1000);
 pref("media.navigator.load_adapt.avg_seconds",3);
 pref("media.navigator.load_adapt.high_load","0.90");
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -853,42 +853,55 @@ class RecursiveMakeBackend(CommonBackend
         # registered or not.
         self._traversal.add(backend_file.relobjdir)
 
         affected_tiers = set(obj.affected_tiers)
 
         for tier in set(self._may_skip.keys()) - affected_tiers:
             self._may_skip[tier].add(backend_file.relobjdir)
 
+    def _process_hierarchy_elements(self, obj, element, namespace, action):
+        """Walks the ``HierarchicalStringList`` ``element`` and performs
+        ``action`` on each HierarchicalStringList in the hierarchy.
+
+        ``action`` is a callback to be invoked with the following arguments:
+        - ``element``     - The HierarchicalStringList along the current namespace
+        - ``namespace``   - The namespace of the element
+        """
+        if namespace:
+            namespace += '/'
+
+        action(element, namespace)
+
+        children = element.get_children()
+        for subdir in sorted(children):
+            self._process_hierarchy_elements(obj, children[subdir],
+                                             namespace + subdir,
+                                             action)
+
     def _process_hierarchy(self, obj, element, namespace, action):
         """Walks the ``HierarchicalStringList`` ``element`` and performs
-        ``action`` on each string in the heirarcy.
+        ``action`` on each string in the hierarchy.
 
         ``action`` is a callback to be invoked with the following arguments:
         - ``source`` - The path to the source file named by the current string
         - ``dest``   - The relative path, including the namespace, of the
                        destination file.
         """
-        strings = element.get_strings()
-        if namespace:
-            namespace += '/'
+        def process_element(element, namespace):
+            strings = element.get_strings()
+            for s in strings:
+                source = mozpath.normpath(mozpath.join(obj.srcdir, s))
+                dest = '%s%s' % (namespace, mozpath.basename(s))
+                flags = None
+                if '__getitem__' in dir(element):
+                    flags = element[s]
+                action(source, dest, flags)
 
-        for s in strings:
-            source = mozpath.normpath(mozpath.join(obj.srcdir, s))
-            dest = '%s%s' % (namespace, mozpath.basename(s))
-            flags = None
-            if '__getitem__' in dir(element):
-                flags = element[s]
-            action(source, dest, flags)
-
-        children = element.get_children()
-        for subdir in sorted(children):
-            self._process_hierarchy(obj, children[subdir],
-                namespace=namespace + subdir,
-                action=action)
+        self._process_hierarchy_elements(obj, element, namespace, process_element)
 
     def _process_exports(self, obj, exports, backend_file):
         # This may not be needed, but is present for backwards compatibility
         # with the old make rules, just in case.
         if not obj.dist_install:
             return
 
         def handle_export(source, dest, flags):
@@ -933,18 +946,44 @@ class RecursiveMakeBackend(CommonBackend
             backend_file.write('FINAL_TARGET = $(DEPTH)/%s\n' % (obj.target))
         else:
             backend_file.write('FINAL_TARGET = $(if $(XPI_NAME),$(DIST)/xpi-stage/$(XPI_NAME),$(DIST)/bin)$(DIST_SUBDIR:%=/%)\n')
 
         if not obj.enabled:
             backend_file.write('NO_DIST_INSTALL := 1\n')
 
     def _process_javascript_modules(self, obj, backend_file):
-        if obj.flavor != 'testing':
-            raise Exception('We only support testing JavaScriptModules instances.')
+        if obj.flavor not in ('extra', 'extra_pp', 'testing'):
+            raise Exception('Unsupported JavaScriptModules instance: %s' % obj.flavor)
+
+        if obj.flavor == 'extra':
+            def onelement(element, namespace):
+                if not element.get_strings():
+                    return
+
+                prefix = 'extra_js_%s' % namespace.replace('/', '_')
+                backend_file.write('%s_FILES := %s\n'
+                                   % (prefix, ' '.join(element.get_strings())))
+                backend_file.write('%s_DEST = $(FINAL_TARGET)/%s\n' % (prefix, namespace))
+                backend_file.write('INSTALL_TARGETS += %s\n\n' % prefix)
+            self._process_hierarchy_elements(obj, obj.modules, 'modules', onelement)
+            return
+
+        if obj.flavor == 'extra_pp':
+            def onelement(element, namespace):
+                if not element.get_strings():
+                    return
+
+                prefix = 'extra_pp_js_%s' % namespace.replace('/', '_')
+                backend_file.write('%s := %s\n'
+                                   % (prefix, ' '.join(element.get_strings())))
+                backend_file.write('%s_PATH = $(FINAL_TARGET)/%s\n' % (prefix, namespace))
+                backend_file.write('PP_TARGETS += %s\n\n' % prefix)
+            self._process_hierarchy_elements(obj, obj.modules, 'modules', onelement)
+            return
 
         if not self.environment.substs.get('ENABLE_TESTS', False):
             return
 
         manifest = self._install_manifests['tests']
 
         def onmodule(source, dest, flags):
             manifest.add_symlink(source, mozpath.join('modules', dest))
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -368,25 +368,22 @@ class TreeMetadataEmitter(LoggingMixin):
         varlist = [
             'ANDROID_GENERATED_RESFILES',
             'ANDROID_RES_DIRS',
             'DISABLE_STL_WRAPPING',
             'EXTRA_ASSEMBLER_FLAGS',
             'EXTRA_COMPILE_FLAGS',
             'EXTRA_COMPONENTS',
             'EXTRA_DSO_LDOPTS',
-            'EXTRA_JS_MODULES',
             'EXTRA_PP_COMPONENTS',
-            'EXTRA_PP_JS_MODULES',
             'FAIL_ON_WARNINGS',
             'FILES_PER_UNIFIED_FILE',
             'USE_STATIC_LIBS',
             'GENERATED_FILES',
             'IS_GYP_DIR',
-            'JS_MODULES_PATH',
             'MSVC_ENABLE_PGO',
             'NO_DIST_INSTALL',
             'OS_LIBS',
             'PYTHON_UNIT_TESTS',
             'RCFILE',
             'RESFILE',
             'RCINCLUDE',
             'DEFFILE',
@@ -502,16 +499,24 @@ class TreeMetadataEmitter(LoggingMixin):
                         'because it is already used in %s' % (program, kind,
                         self._binaries[program].relativedir), sandbox)
                 self._binaries[program] = cls(sandbox, program,
                     is_unit_test=kind == 'CPP_UNIT_TESTS')
                 self._linkage.append((sandbox, self._binaries[program],
                     'HOST_USE_LIBS' if kind == 'HOST_SIMPLE_PROGRAMS'
                     else 'USE_LIBS'))
 
+        extra_js_modules = sandbox.get('EXTRA_JS_MODULES')
+        if extra_js_modules:
+            yield JavaScriptModules(sandbox, extra_js_modules, 'extra')
+
+        extra_pp_js_modules = sandbox.get('EXTRA_PP_JS_MODULES')
+        if extra_pp_js_modules:
+            yield JavaScriptModules(sandbox, extra_pp_js_modules, 'extra_pp')
+
         test_js_modules = sandbox.get('TESTING_JS_MODULES')
         if test_js_modules:
             yield JavaScriptModules(sandbox, test_js_modules, 'testing')
 
         simple_lists = [
             ('GENERATED_EVENTS_WEBIDL_FILES', GeneratedEventWebIDLFile),
             ('GENERATED_WEBIDL_FILES', GeneratedWebIDLFile),
             ('IPDL_SOURCES', IPDLFile),
--- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
@@ -181,30 +181,28 @@ VARIABLES = {
 
     'EXTRA_COMPONENTS': (StrictOrderingOnAppendList, list,
         """Additional component files to distribute.
 
        This variable contains a list of files to copy into
        ``$(FINAL_TARGET)/components/``.
         """, 'libs'),
 
-    'EXTRA_JS_MODULES': (StrictOrderingOnAppendList, list,
+    'EXTRA_JS_MODULES': (HierarchicalStringList, list,
         """Additional JavaScript files to distribute.
 
         This variable contains a list of files to copy into
-        ``$(FINAL_TARGET)/$(JS_MODULES_PATH)``. ``JS_MODULES_PATH`` defaults
-        to ``modules`` if left undefined.
+        ``$(FINAL_TARGET)/modules.
         """, 'libs'),
 
-    'EXTRA_PP_JS_MODULES': (StrictOrderingOnAppendList, list,
+    'EXTRA_PP_JS_MODULES': (HierarchicalStringList, list,
         """Additional JavaScript files to distribute.
 
         This variable contains a list of files to copy into
-        ``$(FINAL_TARGET)/$(JS_MODULES_PATH)``, after preprocessing.
-        ``JS_MODULES_PATH`` defaults to ``modules`` if left undefined.
+        ``$(FINAL_TARGET)/modules``, after preprocessing.
         """, 'libs'),
 
     'TESTING_JS_MODULES': (HierarchicalStringList, list,
         """JavaScript modules to install in the test-only destination.
 
         Some JavaScript modules (JSMs) are test-only and not distributed
         with Firefox. This variable defines them.
 
@@ -287,26 +285,16 @@ VARIABLES = {
 
     'JAVA_JAR_TARGETS': (dict, dict,
         """Defines Java JAR targets to be built.
 
         This variable should not be populated directly. Instead, it should
         populated by calling add_java_jar().
         """, 'libs'),
 
-    'JS_MODULES_PATH': (unicode, unicode,
-        """Sub-directory of ``$(FINAL_TARGET)`` to install
-        ``EXTRA_JS_MODULES``.
-
-        ``EXTRA_JS_MODULES`` files are copied to
-        ``$(FINAL_TARGET)/$(JS_MODULES_PATH)``. This variable does not
-        need to be defined if the desired destination directory is
-        ``$(FINAL_TARGET)/modules``.
-        """, None),
-
     'LIBRARY_NAME': (unicode, unicode,
         """The code name of the library generated for a directory.
 
         By default STATIC_LIBRARY_NAME and SHARED_LIBRARY_NAME take this name.
         In ``example/components/moz.build``,::
 
            LIBRARY_NAME = 'xpcomsample'
 
--- a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build
+++ b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build
@@ -2,19 +2,16 @@
 # Any copyright is dedicated to the Public Domain.
 # http://creativecommons.org/publicdomain/zero/1.0/
 
 SOURCES += ['bar.s', 'foo.asm']
 
 EXTRA_COMPONENTS = ['bar.js', 'foo.js']
 EXTRA_PP_COMPONENTS = ['bar.pp.js', 'foo.pp.js']
 
-EXTRA_JS_MODULES = ['bar.jsm', 'foo.jsm']
-EXTRA_PP_JS_MODULES = ['bar.pp.jsm', 'foo.pp.jsm']
-
 HOST_SOURCES += ['bar.cpp', 'foo.cpp']
 HOST_SOURCES += ['bar.c', 'foo.c']
 
 OS_LIBS = ['foo.so', '-l123', 'bar.a']
 
 SOURCES += ['bar.c', 'foo.c']
 
 SOURCES += ['bar.mm', 'foo.mm']
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -271,24 +271,16 @@ class TestRecursiveMakeBackend(BackendTe
             'EXTRA_COMPONENTS': [
                 'EXTRA_COMPONENTS += bar.js',
                 'EXTRA_COMPONENTS += foo.js',
             ],
             'EXTRA_PP_COMPONENTS': [
                 'EXTRA_PP_COMPONENTS += bar.pp.js',
                 'EXTRA_PP_COMPONENTS += foo.pp.js',
             ],
-            'EXTRA_JS_MODULES': [
-                'EXTRA_JS_MODULES += bar.jsm',
-                'EXTRA_JS_MODULES += foo.jsm',
-            ],
-            'EXTRA_PP_JS_MODULES': [
-                'EXTRA_PP_JS_MODULES += bar.pp.jsm',
-                'EXTRA_PP_JS_MODULES += foo.pp.jsm',
-            ],
             'FAIL_ON_WARNINGS': [
                 'FAIL_ON_WARNINGS := 1',
             ],
             'HOST_CPPSRCS': [
                 'HOST_CPPSRCS += bar.cpp',
                 'HOST_CPPSRCS += foo.cpp',
             ],
             'HOST_CSRCS': [
--- a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build
+++ b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build
@@ -2,19 +2,16 @@
 # Any copyright is dedicated to the Public Domain.
 # http://creativecommons.org/publicdomain/zero/1.0/
 
 SOURCES += ['fans.asm', 'tans.s']
 
 EXTRA_COMPONENTS=['fans.js', 'tans.js']
 EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js']
 
-EXTRA_JS_MODULES = ['bar.jsm', 'foo.jsm']
-EXTRA_PP_JS_MODULES = ['bar.pp.jsm', 'foo.pp.jsm']
-
 HOST_SOURCES += ['fans.cpp', 'tans.cpp']
 HOST_SOURCES += ['fans.c', 'tans.c']
 
 OS_LIBS += ['foo.so', '-l123', 'aaa.a']
 
 SOURCES += ['fans.c', 'tans.c']
 
 SOURCES += ['fans.mm', 'tans.mm']
--- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py
@@ -149,18 +149,16 @@ class TestEmitterBasic(unittest.TestCase
 
         wanted = dict(
             ASFILES=['fans.asm', 'tans.s'],
             CMMSRCS=['fans.mm', 'tans.mm'],
             CSRCS=['fans.c', 'tans.c'],
             DISABLE_STL_WRAPPING=True,
             EXTRA_COMPONENTS=['fans.js', 'tans.js'],
             EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js'],
-            EXTRA_JS_MODULES=['bar.jsm', 'foo.jsm'],
-            EXTRA_PP_JS_MODULES=['bar.pp.jsm', 'foo.pp.jsm'],
             FAIL_ON_WARNINGS=True,
             HOST_CPPSRCS=['fans.cpp', 'tans.cpp'],
             HOST_CSRCS=['fans.c', 'tans.c'],
             MSVC_ENABLE_PGO=True,
             NO_DIST_INSTALL=True,
             OS_LIBS=['foo.so', '-l123', 'aaa.a'],
             SSRCS=['bans.S', 'fans.S'],
             VISIBILITY_FLAGS='',
--- a/python/mozbuild/mozbuild/util.py
+++ b/python/mozbuild/mozbuild/util.py
@@ -431,37 +431,46 @@ class HierarchicalStringList(object):
         # EXPORTS.foo = ['file.h']
         #
         # In this case, we need to overwrite foo's current list of strings.
         #
         # However, __setattr__ is also called with a HierarchicalStringList
         # to try to actually set the attribute. We want to ignore this case,
         # since we don't actually create an attribute called 'foo', but just add
         # it to our list of children (using _get_exportvariable()).
-        exports = self._get_exportvariable(name)
-        if not isinstance(value, HierarchicalStringList):
-            exports._check_list(value)
-            exports._strings = value
+        self._set_exportvariable(name, value)
 
     def __getattr__(self, name):
         if name.startswith('__'):
             return object.__getattr__(self, name)
         return self._get_exportvariable(name)
 
     def __delattr__(self, name):
         raise MozbuildDeletionError('Unable to delete attributes for this object')
 
     def __iadd__(self, other):
         self._check_list(other)
         self._strings += other
         return self
 
+    def __getitem__(self, name):
+        return self._get_exportvariable(name)
+
+    def __setitem__(self, name, value):
+        self._set_exportvariable(name, value)
+
     def _get_exportvariable(self, name):
         return self._children.setdefault(name, HierarchicalStringList())
 
+    def _set_exportvariable(self, name, value):
+        exports = self._get_exportvariable(name)
+        if not isinstance(value, HierarchicalStringList):
+            exports._check_list(value)
+            exports._strings = value
+
     def _check_list(self, value):
         if not isinstance(value, list):
             raise ValueError('Expected a list of strings, not %s' % type(value))
         for v in value:
             if not isinstance(v, str_type):
                 raise ValueError(
                     'Expected a list of strings, not an element of %s' % type(v))
 
--- a/security/sandbox/linux/Sandbox.cpp
+++ b/security/sandbox/linux/Sandbox.cpp
@@ -14,17 +14,16 @@
 #include <signal.h>
 #include <string.h>
 #include <linux/futex.h>
 #include <sys/time.h>
 #include <dirent.h>
 #include <stdlib.h>
 #include <pthread.h>
 #include <errno.h>
-#include <fcntl.h>
 
 #include "mozilla/Atomics.h"
 #include "mozilla/NullPtr.h"
 #include "mozilla/unused.h"
 #include "mozilla/dom/Exceptions.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 
@@ -32,18 +31,20 @@
 #include "nsExceptionHandler.h"
 #endif
 
 #if defined(ANDROID)
 #include "android_ucontext.h"
 #include <android/log.h>
 #endif
 
+#if defined(MOZ_CONTENT_SANDBOX)
 #include "linux_seccomp.h"
 #include "SandboxFilter.h"
+#endif
 
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG 1
 #endif
 #include "prlog.h"
 #include "prenv.h"
 
 // See definition of SandboxDie, below.
@@ -54,24 +55,16 @@ namespace mozilla {
 #define LOG_ERROR(args...) __android_log_print(ANDROID_LOG_ERROR, "Sandbox", ## args)
 #elif defined(PR_LOGGING)
 static PRLogModuleInfo* gSeccompSandboxLog;
 #define LOG_ERROR(args...) PR_LOG(mozilla::gSeccompSandboxLog, PR_LOG_ERROR, (args))
 #else
 #define LOG_ERROR(args...)
 #endif
 
-#ifdef MOZ_GMP_SANDBOX
-// For media plugins, we can start the sandbox before we dlopen the
-// module, so we have to pre-open the file and simulate the sandboxed
-// open().
-static int gMediaPluginFileDesc = -1;
-static nsCString gMediaPluginFilePath;
-#endif
-
 /**
  * Log JS stack info in the same place as the sandbox violation
  * message.  Useful in case the responsible code is JS and all we have
  * are logs and a minidump with the C++ stacks (e.g., on TBPL).
  */
 static void
 SandboxLogJSStack(void)
 {
@@ -139,37 +132,16 @@ Reporter(int nr, siginfo_t *info, void *
   syscall_nr = SECCOMP_SYSCALL(ctx);
   args[0] = SECCOMP_PARM1(ctx);
   args[1] = SECCOMP_PARM2(ctx);
   args[2] = SECCOMP_PARM3(ctx);
   args[3] = SECCOMP_PARM4(ctx);
   args[4] = SECCOMP_PARM5(ctx);
   args[5] = SECCOMP_PARM6(ctx);
 
-#ifdef MOZ_GMP_SANDBOX
-  if (syscall_nr == __NR_open && !gMediaPluginFilePath.IsEmpty()) {
-    const char *path = reinterpret_cast<const char*>(args[0]);
-    int flags = int(args[1]);
-
-    if ((flags & O_ACCMODE) != O_RDONLY) {
-      LOG_ERROR("non-read-only open of file %s attempted (flags=0%o)",
-                path, flags);
-    } else if (strcmp(path, gMediaPluginFilePath.get()) != 0) {
-      LOG_ERROR("attempt to open file %s which is not the media plugin %s",
-                path, gMediaPluginFilePath.get());
-    } else if (gMediaPluginFileDesc == -1) {
-      LOG_ERROR("multiple opens of media plugin file unimplemented");
-    } else {
-      SECCOMP_RESULT(ctx) = gMediaPluginFileDesc;
-      gMediaPluginFileDesc = -1;
-      return;
-    }
-  }
-#endif
-
   LOG_ERROR("seccomp sandbox violation: pid %d, syscall %lu, args %lu %lu %lu"
             " %lu %lu %lu.  Killing process.", pid, syscall_nr,
             args[0], args[1], args[2], args[3], args[4], args[5]);
 
 #ifdef MOZ_CRASHREPORTER
   // Bug 1017393: record syscall number somewhere useful.
   info->si_addr = reinterpret_cast<void*>(syscall_nr);
   bool dumped = CrashReporter::WriteMinidumpForSigInfo(nr, info, void_context);
@@ -277,17 +249,18 @@ FindFreeSignalNumber()
   return 0;
 }
 
 static bool
 SetThreadSandbox()
 {
   bool didAnything = false;
 
-  if (prctl(PR_GET_SECCOMP, 0, 0, 0, 0) == 0) {
+  if (PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX") == nullptr &&
+      prctl(PR_GET_SECCOMP, 0, 0, 0, 0) == 0) {
     if (InstallSyscallFilter(sSetSandboxFilter) == 0) {
       didAnything = true;
     }
     /*
      * Bug 880797: when all B2G devices are required to support
      * seccomp-bpf, this should exit/crash if InstallSyscallFilter
      * returns nonzero (ifdef MOZ_WIDGET_GONK).
      */
@@ -307,29 +280,29 @@ SetThreadSandboxHandler(int signum)
   }
   // Wake up the main thread.  See the FUTEX_WAIT call, below, for an
   // explanation.
   syscall(__NR_futex, reinterpret_cast<int*>(&sSetSandboxDone),
           FUTEX_WAKE, 1);
 }
 
 static void
-BroadcastSetThreadSandbox(SandboxType aType)
+BroadcastSetThreadSandbox()
 {
   int signum;
-  pid_t pid, tid, myTid;
+  pid_t pid, tid;
   DIR *taskdp;
   struct dirent *de;
-  SandboxFilter filter(&sSetSandboxFilter, aType,
-                       PR_GetEnv("MOZ_SANDBOX_VERBOSE"));
+  SandboxFilter filter(&sSetSandboxFilter,
+                       PR_GetEnv("MOZ_CONTENT_SANDBOX_VERBOSE"));
 
   static_assert(sizeof(mozilla::Atomic<int>) == sizeof(int),
                 "mozilla::Atomic<int> isn't represented by an int");
+  MOZ_ASSERT(NS_IsMainThread());
   pid = getpid();
-  myTid = syscall(__NR_gettid);
   taskdp = opendir("/proc/self/task");
   if (taskdp == nullptr) {
     LOG_ERROR("opendir /proc/self/task: %s\n", strerror(errno));
     MOZ_CRASH();
   }
   signum = FindFreeSignalNumber();
   if (signum == 0) {
     LOG_ERROR("No available signal numbers!");
@@ -352,19 +325,19 @@ BroadcastSetThreadSandbox(SandboxType aT
     // For each thread...
     while ((de = readdir(taskdp))) {
       char *endptr;
       tid = strtol(de->d_name, &endptr, 10);
       if (*endptr != '\0' || tid <= 0) {
         // Not a task ID.
         continue;
       }
-      if (tid == myTid) {
-        // Drop this thread's privileges last, below, so we can
-        // continue to signal other threads.
+      if (tid == pid) {
+        // Drop the main thread's privileges last, below, so
+        // we can continue to signal other threads.
         continue;
       }
       // Reset the futex cell and signal.
       sSetSandboxDone = 0;
       if (syscall(__NR_tgkill, pid, tid, signum) != 0) {
         if (errno == ESRCH) {
           LOG_ERROR("Thread %d unexpectedly exited.", tid);
           // Rescan threads, in case it forked before exiting.
@@ -447,86 +420,41 @@ BroadcastSetThreadSandbox(SandboxType aT
 // This function can overapproximate (i.e., return true even if
 // sandboxing isn't supported, but not the reverse).  See bug 993145.
 static bool
 IsSandboxingSupported(void)
 {
   return prctl(PR_GET_SECCOMP) != -1;
 }
 
-// Common code for sandbox startup.
-static void
-SetCurrentProcessSandbox(SandboxType aType)
+/**
+ * Starts the seccomp sandbox for this process and sets user/group-based privileges.
+ * Should be called only once, and before any potentially harmful content is loaded.
+ *
+ * Should normally make the process exit on failure.
+*/
+void
+SetCurrentProcessSandbox()
 {
 #if !defined(ANDROID) && defined(PR_LOGGING)
   if (!gSeccompSandboxLog) {
     gSeccompSandboxLog = PR_NewLogModule("SeccompSandbox");
   }
   PR_ASSERT(gSeccompSandboxLog);
 #endif
 
   if (InstallSyscallReporter()) {
     LOG_ERROR("install_syscall_reporter() failed\n");
   }
 
   if (IsSandboxingSupported()) {
-    BroadcastSetThreadSandbox(aType);
+    BroadcastSetThreadSandbox();
   }
 }
 
-#ifdef MOZ_CONTENT_SANDBOX
-/**
- * Starts the seccomp sandbox for a content process.  Should be called
- * only once, and before any potentially harmful content is loaded.
- *
- * Will normally make the process exit on failure.
-*/
-void
-SetContentProcessSandbox()
-{
-  if (PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX")) {
-    return;
-  }
-
-  SetCurrentProcessSandbox(kSandboxContentProcess);
-}
-#endif // MOZ_CONTENT_SANDBOX
-
-#ifdef MOZ_GMP_SANDBOX
-/**
- * Starts the seccomp sandbox for a media plugin process.  Should be
- * called only once, and before any potentially harmful content is
- * loaded -- including the plugin itself, if it's considered untrusted.
- *
- * The file indicated by aFilePath, if non-null, can be open()ed once
- * read-only after the sandbox starts; it should be the .so file
- * implementing the not-yet-loaded plugin.
- *
- * Will normally make the process exit on failure.
-*/
-void
-SetMediaPluginSandbox(const char *aFilePath)
-{
-  if (PR_GetEnv("MOZ_DISABLE_GMP_SANDBOX")) {
-    return;
-  }
-
-  if (aFilePath) {
-    gMediaPluginFilePath.Assign(aFilePath);
-    gMediaPluginFileDesc = open(aFilePath, O_RDONLY | O_CLOEXEC);
-    if (gMediaPluginFileDesc == -1) {
-      LOG_ERROR("failed to open plugin file %s: %s", aFilePath, strerror(errno));
-      MOZ_CRASH();
-    }
-  }
-  // Finally, start the sandbox.
-  SetCurrentProcessSandbox(kSandboxMediaPlugin);
-}
-#endif // MOZ_GMP_SANDBOX
-
 } // namespace mozilla
 
 
 // "Polyfill" for sandbox::Die, the real version of which requires
 // Chromium's logging code.
 namespace sandbox {
 
 void
--- a/security/sandbox/linux/Sandbox.h
+++ b/security/sandbox/linux/Sandbox.h
@@ -4,19 +4,14 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_Sandbox_h
 #define mozilla_Sandbox_h
 
 namespace mozilla {
 
-#ifdef MOZ_CONTENT_SANDBOX
-void SetContentProcessSandbox();
-#endif
-#ifdef MOZ_GMP_SANDBOX
-void SetMediaPluginSandbox(const char *aFilePath);
-#endif
+void SetCurrentProcessSandbox();
 
 } // namespace mozilla
 
 #endif // mozilla_Sandbox_h
 
--- a/security/sandbox/linux/SandboxFilter.cpp
+++ b/security/sandbox/linux/SandboxFilter.cpp
@@ -9,82 +9,97 @@
 
 #include "linux_seccomp.h"
 #include "linux_syscalls.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/NullPtr.h"
 
 #include <errno.h>
-#include <linux/ipc.h>
+#include <unistd.h>
 #include <linux/net.h>
-#include <linux/prctl.h>
-#include <linux/sched.h>
-#include <sys/mman.h>
-#include <time.h>
-#include <unistd.h>
+#include <linux/ipc.h>
 
 namespace mozilla {
 
 class SandboxFilterImpl : public SandboxAssembler
 {
+  void Build();
 public:
-  virtual void Build() = 0;
-  virtual ~SandboxFilterImpl() { }
+  SandboxFilterImpl() {
+    Build();
+    Finish();
+  }
 };
 
-// Some helper macros to make the code that builds the filter more
-// readable, and to help deal with differences among architectures.
+SandboxFilter::SandboxFilter(const sock_fprog** aStored, bool aVerbose)
+  : mStored(aStored)
+{
+  MOZ_ASSERT(*mStored == nullptr);
+  std::vector<struct sock_filter> filterVec;
+  {
+    SandboxFilterImpl impl;
+    impl.Compile(&filterVec, aVerbose);
+  }
+  mProg = new sock_fprog;
+  mProg->len = filterVec.size();
+  mProg->filter = mFilter = new sock_filter[mProg->len];
+  for (size_t i = 0; i < mProg->len; ++i) {
+    mFilter[i] = filterVec[i];
+  }
+  *mStored = mProg;
+}
 
+SandboxFilter::~SandboxFilter()
+{
+  *mStored = nullptr;
+  delete[] mFilter;
+  delete mProg;
+}
+
+void
+SandboxFilterImpl::Build() {
 #define SYSCALL_EXISTS(name) (defined(__NR_##name))
 
 #define SYSCALL(name) (Condition(__NR_##name))
 #if defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__))
 #define ARM_SYSCALL(name) (Condition(__ARM_NR_##name))
 #endif
 
 #define SYSCALL_WITH_ARG(name, arg, values...) ({ \
   uint32_t argValues[] = { values };              \
   Condition(__NR_##name, arg, argValues);         \
 })
 
-// Some architectures went through a transition from 32-bit to
-// 64-bit off_t and had to version all the syscalls that referenced
-// it; others (newer and/or 64-bit ones) didn't.  Adjust the
-// conditional as needed.
+  // Some architectures went through a transition from 32-bit to
+  // 64-bit off_t and had to version all the syscalls that referenced
+  // it; others (newer and/or 64-bit ones) didn't.  Adjust the
+  // conditional as needed.
 #if SYSCALL_EXISTS(stat64)
 #define SYSCALL_LARGEFILE(plain, versioned) SYSCALL(versioned)
 #else
 #define SYSCALL_LARGEFILE(plain, versioned) SYSCALL(plain)
 #endif
 
-// i386 multiplexes all the socket-related interfaces into a single
-// syscall.
+  // i386 multiplexes all the socket-related interfaces into a single
+  // syscall.
 #if SYSCALL_EXISTS(socketcall)
 #define SOCKETCALL(name, NAME) SYSCALL_WITH_ARG(socketcall, 0, SYS_##NAME)
 #else
 #define SOCKETCALL(name, NAME) SYSCALL(name)
 #endif
 
-// i386 multiplexes all the SysV-IPC-related interfaces into a single
-// syscall.
+  // i386 multiplexes all the SysV-IPC-related interfaces into a single
+  // syscall.
 #if SYSCALL_EXISTS(ipc)
 #define SYSVIPCCALL(name, NAME) SYSCALL_WITH_ARG(ipc, 0, NAME)
 #else
 #define SYSVIPCCALL(name, NAME) SYSCALL(name)
 #endif
 
-#ifdef MOZ_CONTENT_SANDBOX
-class SandboxFilterImplContent : public SandboxFilterImpl {
-protected:
-  virtual void Build() MOZ_OVERRIDE;
-};
-
-void
-SandboxFilterImplContent::Build() {
   /* Most used system calls should be at the top of the whitelist
    * for performance reasons. The whitelist BPF filter exits after
    * processing any ALLOW_SYSCALL macro.
    *
    * How are those syscalls found?
    * 1) via strace -p <child pid> or/and
    * 2) the child will report which system call has been denied by seccomp-bpf,
    *    just before exiting, via NSPR or Android logging.
@@ -305,155 +320,10 @@ SandboxFilterImplContent::Build() {
 #endif
 
   /* nsSystemInfo uses uname (and we cache an instance, so */
   /* the info remains present even if we block the syscall) */
   Allow(SYSCALL(uname));
   Allow(SYSCALL(exit_group));
   Allow(SYSCALL(exit));
 }
-#endif // MOZ_CONTENT_SANDBOX
-
-#ifdef MOZ_GMP_SANDBOX
-class SandboxFilterImplGMP : public SandboxFilterImpl {
-protected:
-  virtual void Build() MOZ_OVERRIDE;
-};
-
-void SandboxFilterImplGMP::Build() {
-  // As for content processes, check the most common syscalls first.
-
-  Allow(SYSCALL_WITH_ARG(clock_gettime, 0, CLOCK_MONOTONIC, CLOCK_REALTIME));
-  Allow(SYSCALL(futex));
-  Allow(SYSCALL(gettimeofday));
-  Allow(SYSCALL(poll));
-  Allow(SYSCALL(write));
-  Allow(SYSCALL(read));
-  Allow(SYSCALL(epoll_wait));
-  Allow(SOCKETCALL(recvmsg, RECVMSG));
-  Allow(SOCKETCALL(sendmsg, SENDMSG));
-  Allow(SYSCALL(time));
-
-  // Nothing after this line is performance-critical.
-
-#if SYSCALL_EXISTS(mmap2)
-  Allow(SYSCALL(mmap2));
-#else
-  Allow(SYSCALL(mmap));
-#endif
-  Allow(SYSCALL_LARGEFILE(fstat, fstat64));
-  Allow(SYSCALL(munmap));
-
-  Allow(SYSCALL(gettid));
-
-  // The glibc source hasn't changed the thread creation clone flags
-  // since 2004, so this *should* be safe to hard-code.  Bionic is
-  // different, but MOZ_GMP_SANDBOX isn't supported there yet.
-  //
-  // At minimum we should require CLONE_THREAD, so that a single
-  // SIGKILL from the parent will destroy all descendant tasks.  In
-  // general, pinning down as much of the flags word as possible is a
-  // good idea, because it exposes a lot of subtle (and probably not
-  // well tested in all cases) kernel functionality.
-  //
-  // WARNING: s390 and cris pass the flags in a different arg -- see
-  // CLONE_BACKWARDS2 in arch/Kconfig in the kernel source -- but we
-  // don't support seccomp-bpf on those archs yet.
-  static const int new_thread_flags = CLONE_VM | CLONE_FS | CLONE_FILES |
-    CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS |
-    CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
-  Allow(SYSCALL_WITH_ARG(clone, 0, new_thread_flags));
-
-  Allow(SYSCALL_WITH_ARG(prctl, 0, PR_GET_SECCOMP, PR_SET_NAME));
-
-#if SYSCALL_EXISTS(set_robust_list)
-  Allow(SYSCALL(set_robust_list));
-#endif
-
-  // NSPR can call this when creating a thread, but it will accept a
-  // polite "no".
-  Deny(EACCES, SYSCALL(getpriority));
-
-  Allow(SYSCALL(mprotect));
-  Allow(SYSCALL_WITH_ARG(madvise, 2, MADV_DONTNEED));
-
-#if SYSCALL_EXISTS(sigreturn)
-  Allow(SYSCALL(sigreturn));
-#endif
-  Allow(SYSCALL(rt_sigreturn));
-
-  Allow(SYSCALL(restart_syscall));
-  Allow(SYSCALL(close));
-
-  // "Sleeping for 300 seconds" in debug crashes; possibly other uses.
-  Allow(SYSCALL(nanosleep));
-
-  // For the crash reporter:
-#if SYSCALL_EXISTS(sigprocmask)
-  Allow(SYSCALL(sigprocmask));
-#endif
-  Allow(SYSCALL(rt_sigprocmask));
-#if SYSCALL_EXISTS(sigaction)
-  Allow(SYSCALL(sigaction));
-#endif
-  Allow(SYSCALL(rt_sigaction));
-  Allow(SOCKETCALL(socketpair, SOCKETPAIR));
-  Allow(SYSCALL_WITH_ARG(tgkill, 0, uint32_t(getpid())));
-  Allow(SYSCALL_WITH_ARG(prctl, 0, PR_SET_DUMPABLE));
-
-  // Note for when GMP is supported on an ARM platform: Add whichever
-  // of the ARM-specific syscalls are needed for this type of process.
-
-  Allow(SYSCALL(epoll_ctl));
-  Allow(SYSCALL(exit));
-  Allow(SYSCALL(exit_group));
-}
-#endif // MOZ_GMP_SANDBOX
-
-SandboxFilter::SandboxFilter(const sock_fprog** aStored, SandboxType aType,
-                             bool aVerbose)
-  : mStored(aStored)
-{
-  MOZ_ASSERT(*mStored == nullptr);
-  std::vector<struct sock_filter> filterVec;
-  SandboxFilterImpl *impl;
-
-  switch (aType) {
-  case kSandboxContentProcess:
-#ifdef MOZ_CONTENT_SANDBOX
-    impl = new SandboxFilterImplContent();
-#else
-    MOZ_CRASH("Content process sandboxing not supported in this build!");
-#endif
-    break;
-  case kSandboxMediaPlugin:
-#ifdef MOZ_GMP_SANDBOX
-    impl = new SandboxFilterImplGMP();
-#else
-    MOZ_CRASH("Gecko Media Plugin process sandboxing not supported in this"
-              " build!");
-#endif
-    break;
-  default:
-    MOZ_CRASH("Nonexistent sandbox type!");
-  }
-  impl->Build();
-  impl->Finish();
-  impl->Compile(&filterVec, aVerbose);
-  delete impl;
-
-  mProg = new sock_fprog;
-  mProg->len = filterVec.size();
-  mProg->filter = mFilter = new sock_filter[mProg->len];
-  for (size_t i = 0; i < mProg->len; ++i) {
-    mFilter[i] = filterVec[i];
-  }
-  *mStored = mProg;
-}
-
-SandboxFilter::~SandboxFilter()
-{
-  *mStored = nullptr;
-  delete[] mFilter;
-  delete mProg;
-}
 
 }
--- a/security/sandbox/linux/SandboxFilter.h
+++ b/security/sandbox/linux/SandboxFilter.h
@@ -6,30 +6,22 @@
 
 #ifndef mozilla_SandboxFilter_h
 #define mozilla_SandboxFilter_h
 
 struct sock_fprog;
 struct sock_filter;
 
 namespace mozilla {
-
-enum SandboxType {
-  kSandboxContentProcess,
-  kSandboxMediaPlugin
-};
-
-class SandboxFilter {
-  sock_filter *mFilter;
-  sock_fprog *mProg;
-  const sock_fprog **mStored;
-public:
+  class SandboxFilter {
+    sock_filter *mFilter;
+    sock_fprog *mProg;
+    const sock_fprog **mStored;
+  public:
   // RAII: on construction, builds the filter and stores it in the
   // provided variable (with optional logging); on destruction, frees
   // the filter and nulls out the pointer.
-  SandboxFilter(const sock_fprog** aStored, SandboxType aBox,
-                bool aVerbose = false);
-  ~SandboxFilter();
-};
-
-} // namespace mozilla
+    SandboxFilter(const sock_fprog** aStored, bool aVerbose = false);
+    ~SandboxFilter();
+  };
+}
 
 #endif
--- a/services/metrics/moz.build
+++ b/services/metrics/moz.build
@@ -1,19 +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/.
 
 TEST_DIRS += ['tests']
 
-EXTRA_PP_JS_MODULES += [
+EXTRA_PP_JS_MODULES.services.metrics += [
     'dataprovider.jsm',
     'providermanager.jsm',
     'storage.jsm',
 ]
 
-JS_MODULES_PATH = 'modules/services/metrics'
-
 TESTING_JS_MODULES.services.metrics += [
     'modules-testing/mocks.jsm',
 ]
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -203,21 +203,16 @@ class MessageLogger(object):
         # Cleaning the list of buffered messages
         self.buffered_messages = []
 
     def finish(self):
         self.dump_buffered()
         self.buffering = False
         self.logger.suite_end()
 
-# Global logger
-log = StructuredLogger('mochitest')
-stream_handler = StreamHandler(stream=sys.stdout, formatter=MochitestFormatter())
-log.add_handler(stream_handler)
-
 ####################
 # PROCESS HANDLING #
 ####################
 
 def call(*args, **kwargs):
   """front-end function to mozprocess.ProcessHandler"""
   # TODO: upstream -> mozprocess
   # https://bugzilla.mozilla.org/show_bug.cgi?id=791383
@@ -989,18 +984,23 @@ class Mochitest(MochitestUtilsMixin):
 
   # XXX use automation.py for test name to avoid breaking legacy
   # TODO: replace this with 'runtests.py' or 'mochitest' or the like
   test_name = 'automation.py'
 
   def __init__(self):
     super(Mochitest, self).__init__()
 
+    # Structured logger
+    structured_log = StructuredLogger('mochitest')
+    stream_handler = StreamHandler(stream=sys.stdout, formatter=MochitestFormatter())
+    structured_log.add_handler(stream_handler)
+
     # Structured logs parser
-    self.message_logger = MessageLogger(logger=log)
+    self.message_logger = MessageLogger(logger=structured_log)
 
     # environment function for browserEnv
     self.environment = environment
 
     # Max time in seconds to wait for server startup before tests will fail -- if
     # this seems big, it's mostly for debug machines where cold startup
     # (particularly after a build) takes forever.
     self.SERVER_STARTUP_TIMEOUT = 180 if mozinfo.info.get('debug') else 90
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -764,17 +764,20 @@ SpecialPowersAPI.prototype = {
         } else if (this.testPermission(permission.type, Ci.nsICookiePermission.ACCESS_SESSION, context)) {
           originalValue = Ci.nsICookiePermission.ACCESS_SESSION;
         } else if (this.testPermission(permission.type, Ci.nsICookiePermission.ACCESS_ALLOW_FIRST_PARTY_ONLY, context)) {
           originalValue = Ci.nsICookiePermission.ACCESS_ALLOW_FIRST_PARTY_ONLY;
         } else if (this.testPermission(permission.type, Ci.nsICookiePermission.ACCESS_LIMIT_THIRD_PARTY, context)) {
           originalValue = Ci.nsICookiePermission.ACCESS_LIMIT_THIRD_PARTY;
         }
 
-        let [url, appId, isInBrowserElement] = this._getInfoFromPermissionArg(context);
+        let [url, appId, isInBrowserElement, isSystem] = this._getInfoFromPermissionArg(context);
+        if (isSystem) {
+          continue;
+        }
 
         let perm;
         if (typeof permission.allow !== 'boolean') {
           perm = permission.allow;
         } else {
           perm = permission.allow ? Ci.nsIPermissionManager.ALLOW_ACTION
                              : Ci.nsIPermissionManager.DENY_ACTION;
         }
@@ -1667,16 +1670,17 @@ SpecialPowersAPI.prototype = {
   removeFullscreenAllowed: function(document) {
     Services.perms.removeFromPrincipal(document.nodePrincipal, "fullscreen");
   },
 
   _getInfoFromPermissionArg: function(arg) {
     let url = "";
     let appId = Ci.nsIScriptSecurityManager.NO_APP_ID;
     let isInBrowserElement = false;
+    let isSystem = false;
 
     if (typeof(arg) == "string") {
       // It's an URL.
       url = Cc["@mozilla.org/network/io-service;1"]
               .getService(Ci.nsIIOService)
               .newURI(arg, null, null)
               .spec;
     } else if (arg.manifestURL) {
@@ -1689,30 +1693,42 @@ SpecialPowersAPI.prototype = {
         throw "No app for this manifest!";
       }
 
       appId = appsSvc.getAppLocalIdByManifestURL(arg.manifestURL);
       url = app.origin;
       isInBrowserElement = arg.isInBrowserElement || false;
     } else if (arg.nodePrincipal) {
       // It's a document.
-      url = arg.nodePrincipal.URI.spec;
-      appId = arg.nodePrincipal.appId;
-      isInBrowserElement = arg.nodePrincipal.isInBrowserElement;
+      isSystem = (arg.nodePrincipal instanceof Ci.nsIPrincipal) &&
+                 Cc["@mozilla.org/scriptsecuritymanager;1"].
+                 getService(Ci.nsIScriptSecurityManager).
+                 isSystemPrincipal(arg.nodePrincipal);
+      if (!isSystem) {
+        // System principals don't have a URL associated with them, and they
+        // don't really need any permissions to be registered with the
+        // permission manager anyway.
+        url = arg.nodePrincipal.URI.spec;
+        appId = arg.nodePrincipal.appId;
+        isInBrowserElement = arg.nodePrincipal.isInBrowserElement;
+      }
     } else {
       url = arg.url;
       appId = arg.appId;
       isInBrowserElement = arg.isInBrowserElement;
     }
 
-    return [ url, appId, isInBrowserElement ];
+    return [ url, appId, isInBrowserElement, isSystem ];
   },
 
   addPermission: function(type, allow, arg) {
-    let [url, appId, isInBrowserElement] = this._getInfoFromPermissionArg(arg);
+    let [url, appId, isInBrowserElement, isSystem] = this._getInfoFromPermissionArg(arg);
+    if (isSystem) {
+      return; // nothing to do
+    }
 
     let permission;
     if (typeof allow !== 'boolean') {
       permission = allow;
     } else {
       permission = allow ? Ci.nsIPermissionManager.ALLOW_ACTION
                          : Ci.nsIPermissionManager.DENY_ACTION;
     }
@@ -1725,44 +1741,53 @@ SpecialPowersAPI.prototype = {
       'appId': appId,
       'isInBrowserElement': isInBrowserElement
     };
 
     this._sendSyncMessage('SPPermissionManager', msg);
   },
 
   removePermission: function(type, arg) {
-    let [url, appId, isInBrowserElement] = this._getInfoFromPermissionArg(arg);
+    let [url, appId, isInBrowserElement, isSystem] = this._getInfoFromPermissionArg(arg);
+    if (isSystem) {
+      return; // nothing to do
+    }
 
     var msg = {
       'op': 'remove',
       'type': type,
       'url': url,
       'appId': appId,
       'isInBrowserElement': isInBrowserElement
     };
 
     this._sendSyncMessage('SPPermissionManager', msg);
   },
 
   hasPermission: function (type, arg) {
-   let [url, appId, isInBrowserElement] = this._getInfoFromPermissionArg(arg);
+    let [url, appId, isInBrowserElement, isSystem] = this._getInfoFromPermissionArg(arg);
+    if (isSystem) {
+      return true; // system principals have all permissions
+    }
 
     var msg = {
       'op': 'has',
       'type': type,
       'url': url,
       'appId': appId,
       'isInBrowserElement': isInBrowserElement
     };
 
     return this._sendSyncMessage('SPPermissionManager', msg)[0];
   },
   testPermission: function (type, value, arg) {
-   let [url, appId, isInBrowserElement] = this._getInfoFromPermissionArg(arg);
+    let [url, appId, isInBrowserElement, isSystem] = this._getInfoFromPermissionArg(arg);
+    if (isSystem) {
+      return true; // system principals have all permissions
+    }
 
     var msg = {
       'op': 'test',
       'type': type,
       'value': value, 
       'url': url,
       'appId': appId,
       'isInBrowserElement': isInBrowserElement
--- a/testing/xpcshell/mach_commands.py
+++ b/testing/xpcshell/mach_commands.py
@@ -136,20 +136,26 @@ class XPCShellRunner(MozbuildObject):
         xpcshell_filter = TestStartFilter()
         self.log_manager.terminal_handler.addFilter(xpcshell_filter)
 
         tests_dir = os.path.join(self.topobjdir, '_tests', 'xpcshell')
         modules_dir = os.path.join(self.topobjdir, '_tests', 'modules')
         # We want output from the test to be written immediately if we are only
         # running a single test.
         verbose_output = test_path is not None or (manifest and len(manifest.test_paths())==1)
+        
+        # We need to attach the '.exe' extension on Windows for the debugger to
+        # work properly.
+        xpcsExecutable = 'xpcshell'
+        if os.name == 'nt':
+          xpcsExecutable += '.exe'
 
         args = {
             'manifest': manifest,
-            'xpcshell': os.path.join(self.bindir, 'xpcshell'),
+            'xpcshell': os.path.join(self.bindir, xpcsExecutable),
             'mozInfo': os.path.join(self.topobjdir, 'mozinfo.json'),
             'symbolsPath': os.path.join(self.distdir, 'crashreporter-symbols'),
             'interactive': interactive,
             'keepGoing': keep_going,
             'logfiles': False,
             'sequential': sequential,
             'shuffle': shuffle,
             'testsRootDir': tests_dir,
--- a/toolkit/components/crashmonitor/moz.build
+++ b/toolkit/components/crashmonitor/moz.build
@@ -1,16 +1,16 @@
 # -*- 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/.
 
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 
-EXTRA_JS_MODULES = [
+EXTRA_JS_MODULES += [
     'CrashMonitor.jsm',
 ]
 
 EXTRA_COMPONENTS += [
     'crashmonitor.manifest',
     'nsCrashMonitor.js',
-]
\ No newline at end of file
+]
--- a/toolkit/components/osfile/modules/moz.build
+++ b/toolkit/components/osfile/modules/moz.build
@@ -1,17 +1,15 @@
 # -*- 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/.
 
-JS_MODULES_PATH = 'modules/osfile'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.osfile += [
     'osfile_async_front.jsm',
     'osfile_async_worker.js',
     'osfile_native.jsm',
     'osfile_shared_allthreads.jsm',
     'osfile_shared_front.jsm',
     'osfile_unix_allthreads.jsm',
     'osfile_unix_back.jsm',
     'osfile_unix_front.jsm',
--- a/toolkit/components/places/moz.build
+++ b/toolkit/components/places/moz.build
@@ -54,17 +54,17 @@ if CONFIG['MOZ_PLACES']:
         'SQLFunctions.cpp',
         'VisitInfo.cpp',
     ]
 
     LOCAL_INCLUDES += [
         '../build',
     ]
 
-    EXTRA_JS_MODULES = [
+    EXTRA_JS_MODULES += [
         'BookmarkHTMLUtils.jsm',
         'BookmarkJSONUtils.jsm',
         'ClusterLib.js',
         'ColorAnalyzer_worker.js',
         'ColorConversion.js',
         'PlacesBackups.jsm',
         'PlacesDBUtils.jsm',
         'PlacesTransactions.jsm',
--- a/toolkit/components/promiseworker/moz.build
+++ b/toolkit/components/promiseworker/moz.build
@@ -3,11 +3,11 @@
 # 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/.
 
 DIRS += [
     'worker'
 ]
 
-EXTRA_JS_MODULES = [
+EXTRA_JS_MODULES += [
     'PromiseWorker.jsm',
 ]
--- a/toolkit/components/promiseworker/worker/moz.build
+++ b/toolkit/components/promiseworker/worker/moz.build
@@ -1,11 +1,9 @@
 # -*- 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/.
 
-JS_MODULES_PATH = 'modules/workers'
-
-EXTRA_JS_MODULES = [
+EXTRA_JS_MODULES.workers = [
     'PromiseWorker.js',
 ]
--- a/toolkit/components/social/moz.build
+++ b/toolkit/components/social/moz.build
@@ -5,17 +5,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
 
 if CONFIG['MOZ_SOCIAL']:
     BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
 
     # social is turned off for android
-    EXTRA_JS_MODULES = [
+    EXTRA_JS_MODULES += [
         'FrameWorker.jsm',
         'FrameWorkerContent.js',
         'MessagePortBase.jsm',
         'MessagePortWorker.js',
         'MozSocialAPI.jsm',
         'SocialService.jsm',
         'WorkerAPI.jsm',
     ]
--- a/toolkit/components/sqlite/moz.build
+++ b/toolkit/components/sqlite/moz.build
@@ -1,13 +1,11 @@
 # -*- 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/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/sqlite'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.sqlite += [
     'sqlite_internal.js',
 ]
--- a/toolkit/components/workerloader/moz.build
+++ b/toolkit/components/workerloader/moz.build
@@ -1,13 +1,11 @@
 # -*- 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/.
 
 MOCHITEST_CHROME_MANIFESTS += ['tests/chrome.ini']
 
-JS_MODULES_PATH = 'modules/workers'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.workers += [
     'require.js'
 ]
--- a/toolkit/components/workerlz4/moz.build
+++ b/toolkit/components/workerlz4/moz.build
@@ -1,19 +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/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/workers'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.workers += [
     'lz4.js',
     'lz4_internal.js',
 ]
 
 SOURCES += [
     'lz4.cpp',
 ]
 
--- a/toolkit/crashreporter/test/Makefile.in
+++ b/toolkit/crashreporter/test/Makefile.in
@@ -1,14 +1,14 @@
 #
 # 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/.
 
 EXTRA_LIBS += $(NSPR_LIBS)
 
-UNIT_FILES = $(SHARED_LIBRARY) $(EXTRA_JS_MODULES)
+UNIT_FILES = $(SHARED_LIBRARY) CrashTestUtils.jsm
 UNIT_DEST = $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/
 INSTALL_TARGETS += UNIT
 
 UNIT_IPC_FILES = $(UNIT_FILES)
 UNIT_IPC_DEST = $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit_ipc/
 INSTALL_TARGETS += UNIT_IPC
--- a/toolkit/crashreporter/tools/symbolstore.py
+++ b/toolkit/crashreporter/tools/symbolstore.py
@@ -310,17 +310,18 @@ def validate_install_manifests(install_m
 def make_file_mapping(install_manifests):
     file_mapping = {}
     for manifest, destination in install_manifests:
         destination = os.path.abspath(destination)
         reg = FileRegistry()
         manifest.populate_registry(reg)
         for dst, src in reg:
             if hasattr(src, 'path'):
-                file_mapping[os.path.join(destination, dst)] = src.path
+                abs_dest = os.path.normpath(os.path.join(destination, dst))
+                file_mapping[abs_dest] = src.path
     return file_mapping
 
 def GetPlatformSpecificDumper(**kwargs):
     """This function simply returns a instance of a subclass of Dumper
     that is appropriate for the current platform."""
     # Python 2.5 has a bug where platform.system() returns 'Microsoft'.
     # Remove this when we no longer support Python 2.5.
     return {'Windows': Dumper_Win32,
--- a/toolkit/devtools/acorn/moz.build
+++ b/toolkit/devtools/acorn/moz.build
@@ -1,15 +1,13 @@
 # -*- 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/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/devtools/acorn'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.acorn += [
     'acorn.js',
     'acorn_loose.js',
     'walk.js',
 ]
--- a/toolkit/devtools/apps/moz.build
+++ b/toolkit/devtools/apps/moz.build
@@ -1,14 +1,12 @@
 # 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/.
 
 TEST_DIRS += ['tests']
 
-JS_MODULES_PATH = 'modules/devtools'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools += [
     'app-actor-front.js',
     'Devices.jsm',
     'Simulator.jsm'
 ]
--- a/toolkit/devtools/discovery/moz.build
+++ b/toolkit/devtools/discovery/moz.build
@@ -1,13 +1,11 @@
 # -*- 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/.
 
 TEST_DIRS += ['tests']
 
-JS_MODULES_PATH = 'modules/devtools/discovery'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.discovery += [
     'discovery.js',
 ]
--- a/toolkit/devtools/jsbeautify/moz.build
+++ b/toolkit/devtools/jsbeautify/moz.build
@@ -1,19 +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/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/devtools/jsbeautify'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.jsbeautify += [
     'beautify.js',
     'lib/sanitytest.js',
     'lib/urlencode_unpacker.js',
     'src/beautify-css.js',
     'src/beautify-html.js',
     'src/beautify-js.js',
     'src/beautify-tests.js'
 ]
--- a/toolkit/devtools/pretty-fast/moz.build
+++ b/toolkit/devtools/pretty-fast/moz.build
@@ -1,13 +1,11 @@
 # -*- 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/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/devtools'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools += [
     'pretty-fast.js',
 ]
--- a/toolkit/devtools/qrcode/decoder/moz.build
+++ b/toolkit/devtools/qrcode/decoder/moz.build
@@ -1,11 +1,9 @@
 # -*- 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/.
 
-JS_MODULES_PATH = 'modules/devtools/qrcode/decoder'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.qrcode.decoder += [
     'index.js',
 ]
--- a/toolkit/devtools/qrcode/encoder/moz.build
+++ b/toolkit/devtools/qrcode/encoder/moz.build
@@ -1,11 +1,9 @@
 # -*- 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/.
 
-JS_MODULES_PATH = 'modules/devtools/qrcode/encoder'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.qrcode.encoder += [
     'index.js',
 ]
--- a/toolkit/devtools/qrcode/moz.build
+++ b/toolkit/devtools/qrcode/moz.build
@@ -9,16 +9,14 @@ DIRS += [
 ]
 
 # Save file size on Fennec until there are active plans to use the decoder there
 if CONFIG['MOZ_BUILD_APP'] != 'mobile/android':
     DIRS += [
         'decoder'
     ]
 
-JS_MODULES_PATH = 'modules/devtools/qrcode'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.qrcode += [
     'index.js',
 ]
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 MOCHITEST_CHROME_MANIFESTS += ['tests/mochitest/chrome.ini']
--- a/toolkit/devtools/styleinspector/moz.build
+++ b/toolkit/devtools/styleinspector/moz.build
@@ -1,11 +1,9 @@
 # -*- 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/.
 
-JS_MODULES_PATH = 'modules/devtools/styleinspector'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.styleinspector += [
     'css-logic.js'
 ]
--- a/toolkit/devtools/tern/moz.build
+++ b/toolkit/devtools/tern/moz.build
@@ -1,19 +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/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/devtools/tern'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.tern += [
     'browser.js',
     'comment.js',
     'condense.js',
     'def.js',
     'ecma5.js',
     'infer.js',
     'signal.js',
     'tern.js',
--- a/toolkit/devtools/transport/moz.build
+++ b/toolkit/devtools/transport/moz.build
@@ -1,15 +1,13 @@
 # -*- 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/.
 
 TEST_DIRS += ['tests']
 
-JS_MODULES_PATH = 'modules/devtools/transport'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.transport += [
     'packets.js',
     'stream-utils.js',
     'transport.js'
 ]
--- a/toolkit/devtools/webconsole/moz.build
+++ b/toolkit/devtools/webconsole/moz.build
@@ -3,16 +3,14 @@
 # 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/.
 
 if CONFIG['OS_TARGET'] != 'Android':
     MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
     XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 
-JS_MODULES_PATH = 'modules/devtools/toolkit/webconsole'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.devtools.toolkit.webconsole += [
     'client.js',
     'network-helper.js',
     'network-monitor.js',
     'utils.js',
 ]
--- a/toolkit/identity/moz.build
+++ b/toolkit/identity/moz.build
@@ -12,29 +12,27 @@ XPIDL_SOURCES += [
 ]
 
 XPIDL_MODULE = 'identity'
 
 SOURCES += [
     'IdentityCryptoService.cpp',
 ]
 
-JS_MODULES_PATH = 'modules/identity'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.identity += [
     'Identity.jsm',
     'IdentityProvider.jsm',
     'IdentityStore.jsm',
     'IdentityUtils.jsm',
     'jwcrypto.jsm',
     'LogUtils.jsm',
     'MinimalIdentity.jsm',
     'RelyingParty.jsm',
     'Sandbox.jsm',
 ]
 
-EXTRA_PP_JS_MODULES += [
+EXTRA_PP_JS_MODULES.identity += [
     'FirefoxAccounts.jsm',
 ]
 
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'xul'
--- a/toolkit/mozapps/extensions/internal/moz.build
+++ b/toolkit/mozapps/extensions/internal/moz.build
@@ -1,29 +1,27 @@
 # -*- 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/.
 
-JS_MODULES_PATH = 'modules/addons'
-
-EXTRA_JS_MODULES += [
+EXTRA_JS_MODULES.addons += [
     'AddonLogging.jsm',
     'AddonRepository.jsm',
     'AddonRepository_SQLiteMigrator.jsm',
     'AddonUpdateChecker.jsm',
     'Content.js',
     'LightweightThemeImageOptimizer.jsm',
     'OpenH264Provider.jsm',
     'PluginProvider.jsm',
     'SpellCheckDictionaryBootstrap.js',
 ]
 
-EXTRA_PP_JS_MODULES += [
+EXTRA_PP_JS_MODULES.addons += [
     'XPIProvider.jsm',
     'XPIProviderUtils.js',
 ]
 
 # This is used in multiple places, so is defined here to avoid it getting
 # out of sync.
 DEFINES['MOZ_EXTENSIONS_DB_SCHEMA'] = 16
 
--- a/toolkit/toolkit.mozbuild
+++ b/toolkit/toolkit.mozbuild
@@ -1,17 +1,17 @@
 # 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/.
 
 if CONFIG['LIBXUL_SDK']:
     error('toolkit.mozbuild is not compatible with --enable-libxul-sdk=')
 
-if CONFIG['MOZ_CONTENT_SANDBOX'] or CONFIG['MOZ_GMP_SANDBOX']:
+if CONFIG['MOZ_CONTENT_SANDBOX'] or (CONFIG['OS_ARCH'] == 'WINNT'):
     add_tier_dir('sandbox', 'security/sandbox')
 
 # Depends on NSS and NSPR, and must be built after sandbox or else B2G emulator
 # builds fail.
 add_tier_dir('platform', 'security/certverifier')
 
 # Depends on certverifier
 add_tier_dir('platform', 'security/apps')
--- a/tools/profiler/moz.build
+++ b/tools/profiler/moz.build
@@ -14,17 +14,17 @@ if CONFIG['MOZ_ENABLE_PROFILER_SPS']:
     ]
     EXPORTS += [
         'GeckoProfilerFunc.h',
         'GeckoProfilerImpl.h',
         'ProfilerMarkers.h',
         'PseudoStack.h',
         'shared-libraries.h',
     ]
-    EXTRA_JS_MODULES = [
+    EXTRA_JS_MODULES += [
         'Profiler.jsm',
     ]
     UNIFIED_SOURCES += [
         'BreakpadSampler.cpp',
         'JSStreamWriter.cpp',
         'nsProfiler.cpp',
         'nsProfilerFactory.cpp',
         'platform.cpp',
--- a/widget/BasicEvents.h
+++ b/widget/BasicEvents.h
@@ -53,30 +53,26 @@ enum nsEventStructType
   // ContentEvents.h
   NS_SCROLLPORT_EVENT,               // InternalScrollPortEvent
   NS_SCROLLAREA_EVENT,               // InternalScrollAreaEvent
   NS_FORM_EVENT,                     // InternalFormEvent
   NS_FOCUS_EVENT,                    // InternalFocusEvent
   NS_CLIPBOARD_EVENT,                // InternalClipboardEvent
   NS_TRANSITION_EVENT,               // InternalTransitionEvent
   NS_ANIMATION_EVENT,                // InternalAnimationEvent
+  NS_SVGZOOM_EVENT,                  // InternalSVGZoomEvent
+  NS_SMIL_TIME_EVENT,                // InternalSMILTimeEvent
 
   // MiscEvents.h
   NS_COMMAND_EVENT,                  // WidgetCommandEvent
   NS_CONTENT_COMMAND_EVENT,          // WidgetContentCommandEvent
   NS_PLUGIN_EVENT,                   // WidgetPluginEvent
 
   // InternalMutationEvent.h (dom/events)
-  NS_MUTATION_EVENT,                 // InternalMutationEvent
-
-  // Follwoing struct type values are ugly.  They indicate other struct type
-  // actually.  However, they are used for distinguishing which DOM event
-  // should be created for the event.
-  NS_SVGZOOM_EVENT,                  // WidgetGUIEvent
-  NS_SMIL_TIME_EVENT                 // InternalUIEvent
+  NS_MUTATION_EVENT                  // InternalMutationEvent
 };
 
 /******************************************************************************
  * Messages
  *
  * TODO: Make them enum.
  ******************************************************************************/
 
@@ -857,18 +853,17 @@ public:
   WidgetGUIEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
     WidgetEvent(aIsTrusted, aMessage, NS_GUI_EVENT),
     widget(aWidget)
   {
   }
 
   virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
   {
-    MOZ_ASSERT(eventStructType == NS_GUI_EVENT ||
-                 eventStructType == NS_SVGZOOM_EVENT,
+    MOZ_ASSERT(eventStructType == NS_GUI_EVENT,
                "Duplicate() must be overridden by sub class");
     // Not copying widget, it is a weak reference.
     WidgetGUIEvent* result = new WidgetGUIEvent(false, message, nullptr);
     result->AssignGUIEventData(*this, true);
     result->mFlags = mFlags;
     return result;
   }
 
@@ -1170,18 +1165,17 @@ public:
   InternalUIEvent(bool aIsTrusted, uint32_t aMessage)
     : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, NS_UI_EVENT)
     , detail(0)
   {
   }
 
   virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
   {
-    MOZ_ASSERT(eventStructType == NS_UI_EVENT ||
-                 eventStructType == NS_SMIL_TIME_EVENT,
+    MOZ_ASSERT(eventStructType == NS_UI_EVENT,
                "Duplicate() must be overridden by sub class");
     InternalUIEvent* result = new InternalUIEvent(false, message);
     result->AssignUIEventData(*this, true);
     result->mFlags = mFlags;
     return result;
   }
 
   int32_t detail;
--- a/widget/ContentEvents.h
+++ b/widget/ContentEvents.h
@@ -310,11 +310,81 @@ public:
     AssignEventData(aEvent, aCopyTargets);
 
     animationName = aEvent.animationName;
     elapsedTime = aEvent.elapsedTime;
     pseudoElement = aEvent.pseudoElement;
   }
 };
 
+/******************************************************************************
+ * mozilla::InternalSVGZoomEvent
+ ******************************************************************************/
+
+class InternalSVGZoomEvent : public WidgetGUIEvent
+{
+public:
+  virtual InternalSVGZoomEvent* AsSVGZoomEvent() MOZ_OVERRIDE { return this; }
+
+  InternalSVGZoomEvent(bool aIsTrusted, uint32_t aMessage) :
+    WidgetGUIEvent(aIsTrusted, aMessage, nullptr, NS_SVGZOOM_EVENT)
+  {
+    mFlags.mCancelable = false;
+  }
+
+  virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(eventStructType == NS_SVGZOOM_EVENT,
+               "Duplicate() must be overridden by sub class");
+    // Not copying widget, it is a weak reference.
+    InternalSVGZoomEvent* result = new InternalSVGZoomEvent(false, message);
+    result->AssignSVGZoomEventData(*this, true);
+    result->mFlags = mFlags;
+    return result;
+  }
+
+  void AssignSVGZoomEventData(const InternalSVGZoomEvent& aEvent,
+                              bool aCopyTargets)
+  {
+    AssignGUIEventData(aEvent, aCopyTargets);
+  }
+};
+
+/******************************************************************************
+ * mozilla::InternalSMILTimeEvent
+ ******************************************************************************/
+
+class InternalSMILTimeEvent : public InternalUIEvent
+{
+public:
+  virtual InternalSMILTimeEvent* AsSMILTimeEvent() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
+  InternalSMILTimeEvent(bool aIsTrusted, uint32_t aMessage) :
+    InternalUIEvent(aIsTrusted, aMessage, NS_SMIL_TIME_EVENT)
+  {
+    mFlags.mBubbles = false;
+    mFlags.mCancelable = false;
+  }
+
+  virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(eventStructType == NS_SMIL_TIME_EVENT,
+               "Duplicate() must be overridden by sub class");
+    InternalSMILTimeEvent* result = new InternalSMILTimeEvent(false, message);
+    result->AssignSMILTimeEventData(*this, true);
+    result->mFlags = mFlags;
+    return result;
+  }
+
+  void AssignSMILTimeEventData(const InternalSMILTimeEvent& aEvent,
+                               bool aCopyTargets)
+  {
+    AssignUIEventData(aEvent, aCopyTargets);
+  }
+};
+
+
 } // namespace mozilla
 
 #endif // mozilla_ContentEvents_h__
--- a/widget/EventClassList.h
+++ b/widget/EventClassList.h
@@ -44,16 +44,18 @@ NS_EVENT_CLASS(Widget, TouchEvent)
 // ContentEvents.h
 NS_EVENT_CLASS(Internal, ScrollPortEvent)
 NS_EVENT_CLASS(Internal, ScrollAreaEvent)
 NS_EVENT_CLASS(Internal, FormEvent)
 NS_EVENT_CLASS(Internal, ClipboardEvent)
 NS_EVENT_CLASS(Internal, FocusEvent)
 NS_EVENT_CLASS(Internal, TransitionEvent)
 NS_EVENT_CLASS(Internal, AnimationEvent)
+NS_EVENT_CLASS(Internal, SVGZoomEvent)
+NS_EVENT_CLASS(Internal, SMILTimeEvent)
 
 // MiscEvents.h
 NS_EVENT_CLASS(Widget, CommandEvent)
 NS_EVENT_CLASS(Widget, ContentCommandEvent)
 NS_EVENT_CLASS(Widget, PluginEvent)
 
 // InternalMutationEvent.h (dom/events)
 NS_EVENT_CLASS(Internal, MutationEvent)
rename from xpcom/tests/TestRefPtr.cpp
rename to xpcom/tests/TestNsRefPtr.cpp
--- a/xpcom/tests/moz.build
+++ b/xpcom/tests/moz.build
@@ -60,21 +60,21 @@ CPP_UNIT_TESTS += [
     'TestAutoRef',
     'TestCOMArray',
     'TestCOMPtr',
     'TestCOMPtrEq',
     'TestDeque',
     'TestFile',
     'TestHashtables',
     'TestID',
+    'TestNsRefPtr',
     'TestObserverArray',
     'TestObserverService',
     'TestPipe',
     'TestPLDHash',
-    'TestRefPtr',
     'TestStringAPI',
     'TestTArray',
     'TestTextFormatter',
     'TestThreadUtils'
 ]
 
 if CONFIG['MOZ_MEMORY']:
     CPP_UNIT_TESTS += [