merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 17 Jul 2014 16:01:43 +0200
changeset 216508 f92e4d13b3c6e20501703994f8c8d7fe0618ffc4
parent 216418 f6912a8e9ccc6a6ae2d66d43bd3bce6688deed77 (current diff)
parent 216507 42d1935444659dee9ff9ebd21e5dafdadc050fbc (diff)
child 216530 75db55f6fd2cd1d557639abf4250079221532cd7
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
caps/idl/moz.build
caps/idl/nsIDomainPolicy.idl
caps/idl/nsIPrincipal.idl
caps/idl/nsIScriptSecurityManager.idl
caps/include/DomainPolicy.h
caps/include/moz.build
caps/include/nsJSPrincipals.h
caps/include/nsNullPrincipal.h
caps/include/nsPrincipal.h
caps/include/nsScriptSecurityManager.h
caps/include/nsSystemPrincipal.h
caps/src/DomainPolicy.cpp
caps/src/moz.build
caps/src/nsJSPrincipals.cpp
caps/src/nsNullPrincipal.cpp
caps/src/nsNullPrincipalURI.cpp
caps/src/nsNullPrincipalURI.h
caps/src/nsPrincipal.cpp
caps/src/nsScriptSecurityManager.cpp
caps/src/nsSystemPrincipal.cpp
content/media/plugins/MPAPI.h
content/media/plugins/MediaPluginDecoder.cpp
content/media/plugins/MediaPluginDecoder.h
content/media/plugins/MediaPluginHost.cpp
content/media/plugins/MediaPluginHost.h
content/media/plugins/MediaPluginReader.cpp
content/media/plugins/MediaPluginReader.h
content/media/plugins/MediaResourceServer.cpp
content/media/plugins/MediaResourceServer.h
content/media/plugins/moz.build
dom/imptests/failures/html/html/semantics/forms/the-form-element/mochitest.ini
dom/imptests/failures/html/html/semantics/forms/the-form-element/test_form-elements-nameditem-01.html.json
editor/idl/moz.build
editor/idl/nsIContentFilter.idl
editor/idl/nsIDocumentStateListener.idl
editor/idl/nsIEditActionListener.idl
editor/idl/nsIEditor.idl
editor/idl/nsIEditorIMESupport.idl
editor/idl/nsIEditorMailSupport.idl
editor/idl/nsIEditorObserver.idl
editor/idl/nsIEditorSpellCheck.idl
editor/idl/nsIEditorStyleSheets.idl
editor/idl/nsIHTMLAbsPosEditor.idl
editor/idl/nsIHTMLEditor.idl
editor/idl/nsIHTMLInlineTableEditor.idl
editor/idl/nsIHTMLObjectResizeListener.idl
editor/idl/nsIHTMLObjectResizer.idl
editor/idl/nsIPlaintextEditor.idl
editor/idl/nsITableEditor.idl
editor/idl/nsIURIRefObject.idl
editor/idl/nsPIEditorTransaction.idl
editor/public/moz.build
editor/public/nsEditorCID.h
netwerk/dns/nsIDNSRequest.idl
rdf/tests/dsds/DataSourceViewer.css
rdf/tests/dsds/DataSourceViewer.xul
rdf/tests/dsds/Makefile.in
rdf/tests/dsds/moz.build
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1038799 - And be wary of your ccache too.
+Clobber to work around bug 959928.
--- a/accessible/jsat/EventManager.jsm
+++ b/accessible/jsat/EventManager.jsm
@@ -24,18 +24,19 @@ XPCOMUtils.defineLazyModuleGetter(this, 
   'resource://gre/modules/accessibility/Constants.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Events',
   'resource://gre/modules/accessibility/Constants.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'States',
   'resource://gre/modules/accessibility/Constants.jsm');
 
 this.EXPORTED_SYMBOLS = ['EventManager'];
 
-this.EventManager = function EventManager(aContentScope) {
+this.EventManager = function EventManager(aContentScope, aContentControl) {
   this.contentScope = aContentScope;
+  this.contentControl = aContentControl;
   this.addEventListener = this.contentScope.addEventListener.bind(
     this.contentScope);
   this.removeEventListener = this.contentScope.removeEventListener.bind(
     this.contentScope);
   this.sendMsgFunc = this.contentScope.sendAsyncMessage.bind(
     this.contentScope);
   this.webProgress = this.contentScope.docShell.
     QueryInterface(Ci.nsIInterfaceRequestor).
@@ -94,17 +95,17 @@ this.EventManager.prototype = {
     });
 
     try {
       switch (aEvent.type) {
       case 'wheel':
       {
         let attempts = 0;
         let delta = aEvent.deltaX || aEvent.deltaY;
-        this.contentScope.contentControl.autoMove(
+        this.contentControl.autoMove(
          null,
          { moveMethod: delta > 0 ? 'moveNext' : 'movePrevious',
            onScreenOnly: true, noOpIfOnScreen: true, delay: 500 });
         break;
       }
       case 'scroll':
       case 'resize':
       {
@@ -178,17 +179,17 @@ this.EventManager.prototype = {
             Presentation.
               actionInvoked(aEvent.accessible,
                             event.isEnabled ? 'select' : 'unselect'));
         }
         break;
       }
       case Events.SCROLLING_START:
       {
-        this.contentScope.contentControl.autoMove(aEvent.accessible);
+        this.contentControl.autoMove(aEvent.accessible);
         break;
       }
       case Events.TEXT_CARET_MOVED:
       {
         let acc = aEvent.accessible;
         let characterCount = acc.
           QueryInterface(Ci.nsIAccessibleText).characterCount;
         let caretOffset = aEvent.
@@ -249,17 +250,17 @@ this.EventManager.prototype = {
             break;
           }
           this._queueLiveEvent(Events.HIDE, liveRegion, isPolite);
         } else {
           let vc = Utils.getVirtualCursor(this.contentScope.content.document);
           if (vc.position &&
             (Utils.getState(vc.position).contains(States.DEFUNCT) ||
               Utils.isInSubtree(vc.position, aEvent.accessible))) {
-            this.contentScope.contentControl.autoMove(
+            this.contentControl.autoMove(
               evt.targetPrevSibling || evt.targetParent,
               { moveToFocused: true, delay: 500 });
           }
         }
         break;
       }
       case Events.TEXT_INSERTED:
       case Events.TEXT_REMOVED:
@@ -274,29 +275,29 @@ this.EventManager.prototype = {
         break;
       }
       case Events.FOCUS:
       {
         // Put vc where the focus is at
         let acc = aEvent.accessible;
         let doc = aEvent.accessibleDocument;
         if (acc.role != Roles.DOCUMENT && doc.role != Roles.CHROME_WINDOW) {
-         this.contentScope.contentControl.autoMove(acc);
+         this.contentControl.autoMove(acc);
        }
        break;
       }
       case Events.DOCUMENT_LOAD_COMPLETE:
       {
-        this.contentScope.contentControl.autoMove(
+        this.contentControl.autoMove(
           aEvent.accessible, { delay: 500 });
         break;
       }
       case Events.VALUE_CHANGE:
       {
-        let position = this.contentScope.contentControl.vc.position;
+        let position = this.contentControl.vc.position;
         let target = aEvent.accessible;
         if (position === target ||
             Utils.getEmbeddedControl(position) === target) {
           this.present(Presentation.valueChanged(target));
         }
       }
     }
   },
--- a/accessible/jsat/content-script.js
+++ b/accessible/jsat/content-script.js
@@ -135,26 +135,26 @@ addMessageListener(
     Logger.debug('AccessFu:Start');
     if (m.json.buildApp)
       Utils.MozBuildApp = m.json.buildApp;
 
     addMessageListener('AccessFu:ContextMenu', activateContextMenu);
     addMessageListener('AccessFu:Scroll', scroll);
     addMessageListener('AccessFu:AdjustRange', adjustRange);
 
-    if (!eventManager) {
-      eventManager = new EventManager(this);
-    }
-    eventManager.start();
-
     if (!contentControl) {
       contentControl = new ContentControl(this);
     }
     contentControl.start();
 
+    if (!eventManager) {
+      eventManager = new EventManager(this, contentControl);
+    }
+    eventManager.start();
+
     sendAsyncMessage('AccessFu:ContentStarted');
   });
 
 addMessageListener(
   'AccessFu:Stop',
   function(m) {
     Logger.debug('AccessFu:Stop');
 
--- a/b2g/app/Makefile.in
+++ b/b2g/app/Makefile.in
@@ -119,24 +119,19 @@ endif
 	cp -RL $(srcdir)/b2g.icns $(DIST)/$(APP_NAME).app/Contents/Resources/$(MOZ_APP_NAME).icns
 	printf APPLMOZB > $(DIST)/$(APP_NAME).app/Contents/PkgInfo
 
 else # MOZ_WIDGET_TOOLKIT != cocoa
 
 libs::
 ifdef LIBXUL_SDK
 	cp $(LIBXUL_DIST)/bin/xulrunner-stub$(BIN_SUFFIX) $(DIST)/bin/$(APP_BINARY)
-endif
-ifndef SKIP_COPY_XULRUNNER
-ifdef LIBXUL_SDK
 	$(NSINSTALL) -D $(DIST)/bin/xulrunner
 	(cd $(LIBXUL_SDK)/bin && tar $(TAR_CREATE_FLAGS) - .) | (cd $(DIST)/bin/xulrunner && tar -xf -)
 endif
-endif # SKIP_COPY_XULRUNNER
-
 	$(NSINSTALL) -D $(DIST)/bin/chrome/icons/default
 
 # Copy the app icon for b2g-desktop
 ifeq ($(OS_ARCH),WINNT)
 	cp $(srcdir)/$(APP_ICON).ico $(DIST)/bin/chrome/icons/default/$(APP_ICON).ico
 	$(REDIT_PATH)/redit$(HOST_BIN_SUFFIX) $(DIST)/bin/$(APP_BINARY) $(srcdir)/$(APP_ICON).ico
 	cp $(srcdir)/$(APP_ICON).ico $(DIST)/bin/chrome/icons/default/default.ico
 else ifneq (gonk,$(MOZ_WIDGET_TOOLKIT))
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -468,27 +468,16 @@ pref("services.push.adaptive.lastGoodPin
 pref("services.push.adaptive.lastGoodPingInterval.mobile", 180000);// 3 min
 pref("services.push.adaptive.lastGoodPingInterval.wifi", 180000);// 3 min
 // Valid gap between the biggest good ping and the bad ping
 pref("services.push.adaptive.gap", 60000); // 1 minute
 // We limit the ping to this maximum value
 pref("services.push.adaptive.upperLimit", 1740000); // 29 min
 // enable udp wakeup support
 pref("services.push.udp.wakeupEnabled", true);
-// This value should be the prefix to be added to the current PDP context[1]
-// domain or a full-qualified domain name.
-// If finished with a dot, it will be added as a prefix to the PDP context
-// domain. If not, will be used as the DNS query.
-// If the DNS query is unsuccessful, the push agent will send a null netid and
-// is a server decision what to do with the device. If the MCC-MNC identifies a
-// unique network the server will change to UDP mode. Otherwise, a websocket
-// connection will be maintained.
-// [1] Packet Data Protocol
-//     http://en.wikipedia.org/wiki/GPRS_core_network#PDP_context
-pref("services.push.udp.well-known_netidAddress", "_wakeup_.");
 
 // NetworkStats
 #ifdef MOZ_WIDGET_GONK
 pref("dom.mozNetworkStats.enabled", true);
 pref("dom.webapps.firstRunWithSIM", true);
 #endif
 
 // ResourceStats
--- a/b2g/components/test/mochitest/mochitest.ini
+++ b/b2g/components/test/mochitest/mochitest.ini
@@ -5,9 +5,10 @@ support-files =
   SandboxPromptTest.html
   filepicker_path_handler_chrome.js
   systemapp_helper.js
 
 [test_sandbox_permission.html]
 [test_filepicker_path.html]
 [test_permission_deny.html]
 [test_permission_gum_remember.html]
+skip-if = (toolkit == 'gonk' && debug) # Bug 1019572 - debug-only timeout
 [test_systemapp.html]
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -130,18 +130,16 @@ tools repackage:: $(PROGRAM)
 	$(RM) $(dist_dest)/Contents/MacOS/$(PROGRAM)
 	rsync -aL $(PROGRAM) $(dist_dest)/Contents/MacOS
 	cp -RL $(DIST)/branding/firefox.icns $(dist_dest)/Contents/Resources/firefox.icns
 	cp -RL $(DIST)/branding/document.icns $(dist_dest)/Contents/Resources/document.icns
 	printf APPLMOZB > $(dist_dest)/Contents/PkgInfo
 endif
 
 ifdef LIBXUL_SDK #{
-ifndef SKIP_COPY_XULRUNNER #{
 libs::
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) #{
 	rsync -a --copy-unsafe-links $(LIBXUL_DIST)/XUL.framework $(dist_dest)/Contents/Frameworks
 else
 	$(NSINSTALL) -D $(DIST)/bin/xulrunner
 	(cd $(LIBXUL_SDK)/bin && tar $(TAR_CREATE_FLAGS) - .) | (cd $(DIST)/bin/xulrunner && tar -xf -)
 endif #} cocoa
-endif #} SKIP_COPY_XULRUNNER
 endif #} LIBXUL_SDK
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1514,16 +1514,17 @@ pref("image.mem.max_decoded_image_kb", 2
 // Enable by default on nightly and aurora.
 #ifndef RELEASE_BUILD
 pref("loop.enabled", true);
 #else
 pref("loop.enabled", false);
 #endif
 
 pref("loop.server", "https://loop.services.mozilla.com");
+pref("loop.seenToS", "unseen");
 pref("loop.do_not_disturb", false);
 pref("loop.ringtone", "chrome://browser/content/loop/shared/sounds/Firefox-Long.ogg");
 
 // serverURL to be assigned by services team
 pref("services.push.serverURL", "wss://push.services.mozilla.com/");
 
 // Default social providers
 pref("social.manifest.facebook", "{\"origin\":\"https://www.facebook.com\",\"name\":\"Facebook Share\",\"shareURL\":\"https://www.facebook.com/sharer/sharer.php?u=%{url}\",\"iconURL\":\"data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAX0lEQVQ4jWP4%2F%2F8%2FAyUYTFhHzjgDxP9JxGeQDSBVMxgTbUBCxer%2Fr999%2BQ8DJBuArJksA9A10s8AXIBoA0B%2BR%2FY%2FjD%2BEwoBoA1yT5v3PbdmCE8MAshhID%2FUMoDgzUYIBj0Cgi7ar4coAAAAASUVORK5CYII%3D\",\"icon32URL\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAADbklEQVRYCc1Xv08UQRj99tctexAuCEFjRE0kGBEtLDSGqIWNxkYKbTAxNlY2JhaGWltNtNFeKgsKKxITK43/gCYW+IsoRhA4D47bH7fn9+bcvdm5JR7sefolC3Ozu9978+bNN7PayUv3HN3umdY0Y6IWBtSJ0HSTarXqTOiuTep6Lj+tdxAcA8RAgSmwdd2aCDs0clldYALb/FvgYVhjmfliVA2XpjEgWo0Attn42Z6WH1RFor5ehwo9XQIUZMoVn4qlCoVMSo62EvD8Kh0b3U2Xz43R2PBO6mUCGDlAf65V6MadZzT/rUimoccc2kYA4BfPHqJb105RzjJigKhRq9kEJUBIjgYVuXeL7SAI6eD+Abp5dTwVHOmEHxT50d8WBYJqSOdPj5BjW8gZR8UNqFR2xagx/65XFYaMH+BGWwiYpi4UkBPPLxTp9v1Z+lHc4DWvCQXWmIy6EjITgKowVd5Jjv7N3Hd6y5esigoOwpkJIAmMpZpLJGdiaaC4F0UmAj6bD84GCEwmB/qxMmRilmnwb/mpjAocHh4UEoNAt5NLZB7oy9OJo0PxqkAtePdhiSqunyC1LQUwWMPQaOr6GRre258Ajn4cP7KHcEXhsxpXbj+lT19X2TMNGTLVAcjcalS8gDwsQ2UOMhH4k8FkcrEn5E5ub2sKohxLK2VR77Hl9RUcsrgeRIEiVOT6z+tDbIeLy+vk+kGTCbXxycet6xhl//3f6bJEkdHYhA+mLtDIvoH4ieev5+juoxdk5+pjhALYEdXIpEB5w+NlSKSzqVQ/+H7IO6BLtl3fngGMiqhGJgIwlM6qpyUGFjySdk8m0Zg0ubeD7X9OIDEFajltRQgUJaUKx69tdgaQa0FMADuahZPMFtcEwNPm2hA7ZI5sK4aoE2NvYI+o8hkCIe7CwTv68zS0q9Dk5vpbm/8FXxitSzmMFHpsGj0wyLUheTwD2Y9fVgh1Ae0EPUgD9241ZEnld+v5kgnVZ/8fE0brVh5BK+1oCqKKF72Dk7HwBsssB/pklU1dfChy3S659H5+uelgIb+8WRv1/uGTV9Sdb5wJFlfW6fPCalMhwhSU1j2xKwKbP838GcOwJja4TqO0bjdmXxYTy1EYjFdCWoCEYZhseH/GDL3yJPHnuW6YmT7P1SlIA4768Hke4vOcsX8BE346lLHhDUQAAAAASUVORK5CYII=\", \"icon64URL\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAACNNJREFUeNrtm3tw1NUVxz/399hHHkgCaCBGEFEEREVFYFQcSoOKdkZay4z+4dDpYIsjHWx1WoTMhFi1gzBSpVgVGbU4U1sHfPESKODwEEnRYDFAICEIeZIQshs2u/v73ds/drMsyW7YLEkl2Z6Z32yy+9v7u+fc7znne8+5KzgvAjDunzlv0M13PjDZ6c4cARj0WhEoaZ1tOn3yq9XLf/tNU0O1D5Ad7wq/OpxpaXOL1j5uZAwuaGlVgwNBhULRm0XXBG6HZrlNa9uRrzfM+3DlgjIgGMsA7rl/XDdHOnNf9vosTfVuvTsaQhdkZ4iykh2rHtqydvkxwI58BhjTfv7MmP55E9/1nLNdfU15ACkVvoAaMCRvRPa+re9+DgTaPjMAx+DrJv3M67Mz+6LybWLb4NfTHhxzx31DDhZvOtqGAgNwWbjGICV9XQJB0e/KobcOP1i8qTzaAEYgaDtNU/V5A9hSaUFLuQEt2gVQSgml+j4CUAIppYgK/m0GkCjZ9xGAUNAu0LUhgJRAAAIVzwBSqVRQH4hlAClRKZAFhOgEASoFECBR8QwgUyQGdJT/B8HzCEiBNKhUJzEgBYIgQsTJAkohe9oFZHgHKvQoHtZ9K3tewfiixXABLdoFeuSSEmkF+PH4QTz7+M3o+ENptzvGtS36uSwmjMpAYF10XCllHCYoe84FlLS555Zs5jx6J6ahY+iCl98pJiDNS1hwSZop+cm91zJmxEBefGsPlu1AxKC67V3gf5oGlZSMuz6Dp2fdhWnoAEwaN5T5hsYLb+4hKB1dcgelFDpB8ifk8thDt3DO5+fZxRvxBV0IjQR0EB3KfD1GhJS0GZnnYuGcKTgdF9ZWx4/No/BJjUUrdtJqm4iL+K5SCmSAiWMHMevhcQzNzaa6ron5SzfQ7HeiaSKx+au4m6HupcJKSYZdZVI4dypuV2yo3zoql0VP3cOiFV/Q4jdiGkGhQFqMGpbJL346kbE3DEYIQWNTC39Ysp4Gr4HQtZDyiRhA0NlmSHZbRM7pr1H0m6lckeHqdGXG3jCYoqfupeC17bT49fNRXIFSNrkDTGbNGM9dtw1D10M1DI/Xx3NLP6OqETRdDy1eglPT4rqA7K56gCIrXfHCvHwGZqUnBMtR113FS/N+xHPLtuJpDa1mVobg0emjmX7vqEjsUErhaw1Q8Mo6yk4F0A1HeOW7kIlFx/u7jworRabLpmhuPjmD+iG7YNDrrhnIS09P5cW/buOeO67lkftvJt3tDE06PE7Qsnh++QYOHPOim86wcVUS0+whJug0ghTMmcK1V2eH8m2UHP++nrwhAyIwjiXDcrN5vXAGhqGhFBeMYUvJ0re2sPfgGTTDGUZrEogVopMgmGQWUCgMEWTBE5MZPSLngnGqas/w9j92s31fJfmThvPM7HyMMKRj+qgmOiBHSsnr73/B5r1V6A53KD4k3bFS8dNgckFQoWPxu1kTGDc6N7JqzR4ff/+smE+2H8FSLkx3FluLawhaG3n2iXwcppGoV/Hemt18tK0c3UwLIfUS2nVafBeQJNUXkAF+/dht3H37cKSUBC2bTTv+w98++YazPg1dT0NoIUhruoMd+2sJrtjI7381rQM3iCVrN33N++tL0c30xFNdp0GQeFRYQhcRIO0gv5xxE/fdfSO2bfNVSTmrPtxLZW0A3XSh6VporaLG1XQHu0pOU/TaOhY8+QAuZ3w6vHnnQd74536EkZ50wOsSE0zcugolbWZOG8GM/LGUVdSw6sM97D/UgGa60QxXzMJDZAq6yb7SJgr//CkLn5pOmsvR4Z5dxUdZ9t6XoKfFjNyXkqZjuoBUCpGgCyhp8eDdQ5k++UaWrdrMlr2VSFxoZlpE8YtNWGgGXx9ppnDZpxTMfTCS8gAOlJ5g8ds7kCItTIi6j6FqMVxAC2sV2RB1ekmLCTcNpH+myeyFH7BxT1Voopoe4RKJXQqhmxw45mXh0o/xeH0opThcXs2iv2wmoFyhAnbC4yX+3PgISMDShrA5XHGa3d9UITRniIeTfHASmsGhEz7mL/mI2TPv4sU3t+KzHAnu7JKpCosOkcSIICAB5hZE0OiRCM0Iwb0b6LPQdI5W+Zn/yucoYYayRk+16eK1xqRMDAHtA0r3lep0lNAjO8kfpCpMqpTF4xZEUqA7rIlOCiKpgADVWXc4FQwgEfHPB5AiByTixIDUCYJx+wJoqdIcJV5VOAWygEZcF7BToT2upFDKtuz2BrAtf8v3mju972cBJX2exso6ok6N64BhOtM11xXXPBz6v6340PcuO+DZfaJkzWqgqY3L64Bqaaz0ZV45Mkc308dG2kd97FLSaq4v317gazr5HeCLRoACFTxbfeBw+oDhWYYj4/rw+30H+rb/VMPxXQsbKnbuABqJOi4vogyRiRB5/XNvvz3zytFTDEf61eF9b0dCKTS36c4afymTsgLeQ9Ly13X/aYnzE1Uy6PV7679trNy1xe+tKwPqAH/0Vla0qw65gH7AFeG/Y3Uy9P45o0bm3PTIaplM6lTK9jWf/OBUyQcrpdXaTIyfsXQb9QcLaAn7vJd2vxY5XxBpo8pwDmgFGsLKx1oeh8OVmUUSLXUlrWZPzbdLag9v+BjUqfDzepKAyDDcZbznGHG+1NmqSKHpVlfbadJqLW+o2LHobNX+PUB1WPkfnHwYyTmX6lI7Lehr3F576NM/+T3V3wH17f2w1xkg2ggXuSvga6p8p+bgmpVKWpXAmVh+2AsNEKogdYYAJa0GT03J4obyf60HTgKe6PTTqw0QOpcQ3wXs4LlDZyq2FXrrS4uBmjDxuCw3G5eIgA46yeC5ho11pWsWW35PWTibBC4Xf+9eBLRPg0q2+s5UvHG6bMNqJYPHw7nXutxZYvIIiMoCSgbrPVX/fv7syS+3AKfC5MOmF4iRpP6RjrId8O5vrNhS1NpUWQLUholUr6muXEoatP3emrWNR9e/avk9R8P+HuxNypPkrk93pGdnK0VtXemaN6UdOHo55vdE5b/0NKx+K4AxtAAAAABJRU5ErkJggg==\", \"description\":\"Easily share the web to your Facebook friends.\",\"author\":\"Facebook\",\"homepageURL\":\"https://www.facebook.com\",\"builtin\":\"true\",\"version\":1}");
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -535,17 +535,17 @@ var gPopupBlockerObserver = {
     if (blockedPopups) {
       for (let i = 0; i < blockedPopups.length; i++) {
         let blockedPopup = blockedPopups[i];
 
         // popupWindowURI will be null if the file picker popup is blocked.
         // xxxdz this should make the option say "Show file picker" and do it (Bug 590306)
         if (!blockedPopup.popupWindowURI)
           continue;
-        var popupURIspec = blockedPopup.popupWindowURI;
+        var popupURIspec = blockedPopup.popupWindowURI.spec;
 
         // Sometimes the popup URI that we get back from the blockedPopup
         // isn't useful (for instance, netscape.com's popup URI ends up
         // being "http://www.netscape.com", which isn't really the URI of
         // the popup they're trying to show).  This isn't going to be
         // useful to the user, so we won't create a menu item for it.
         if (popupURIspec == "" || popupURIspec == "about:blank" ||
             popupURIspec == uri.spec)
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1019,17 +1019,17 @@
                 window.removeEventListener("MozAfterPaint", removeSwitchingtabsAttr);
                 forwardButtonContainer.removeAttribute("switchingtabs");
               });
             }
 
             this._appendStatusPanel();
 
             if (updateBlockedPopups)
-              this.mCurrentBrowser.updateBlockedPopups(false);
+              this.mCurrentBrowser.updateBlockedPopups();
 
             // Update the URL bar.
             var loc = this.mCurrentBrowser.currentURI;
 
             // Bug 666809 - SecurityUI support for e10s
             var webProgress = this.mCurrentBrowser.webProgress;
             var securityUI = this.mCurrentBrowser.securityUI;
 
--- a/browser/base/content/test/social/social_crash_content_helper.js
+++ b/browser/base/content/test/social/social_crash_content_helper.js
@@ -8,17 +8,17 @@ let Cu = Components.utils;
 Cu.import("resource://gre/modules/ctypes.jsm");
 let crash = function() { // this will crash when called.
   let zero = new ctypes.intptr_t(8);
   let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
   badptr.contents
 };
 
 
-TestHelper = {
+let TestHelper = {
   init: function() {
     addMessageListener("social-test:crash", this);
   },
 
   receiveMessage: function(msg) {
     switch (msg.name) {
       case "social-test:crash":
         privateNoteIntentionalCrash();
--- a/browser/components/loop/content/js/panel.js
+++ b/browser/components/loop/content/js/panel.js
@@ -108,17 +108,17 @@ loop.panel = (function(_, mozL10n) {
     },
 
     render: function() {
       var tosHTML = __("legal_text_and_links", {
         "terms_of_use_url": "https://accounts.firefox.com/legal/terms",
         "privacy_notice_url": "www.mozilla.org/privacy/"
       });
 
-      if (!this.state.seenToS) {
+      if (this.state.seenToS == "unseen") {
         navigator.mozLoop.setLoopCharPref('seenToS', 'seen');
         return React.DOM.p( {className:"terms-service",
                   dangerouslySetInnerHTML:{__html: tosHTML}});
       } else {
         return React.DOM.div(null );
       }
     }
   });
--- a/browser/components/loop/content/js/panel.jsx
+++ b/browser/components/loop/content/js/panel.jsx
@@ -108,17 +108,17 @@ loop.panel = (function(_, mozL10n) {
     },
 
     render: function() {
       var tosHTML = __("legal_text_and_links", {
         "terms_of_use_url": "https://accounts.firefox.com/legal/terms",
         "privacy_notice_url": "www.mozilla.org/privacy/"
       });
 
-      if (!this.state.seenToS) {
+      if (this.state.seenToS == "unseen") {
         navigator.mozLoop.setLoopCharPref('seenToS', 'seen');
         return <p className="terms-service"
                   dangerouslySetInnerHTML={{__html: tosHTML}}></p>;
       } else {
         return <div />;
       }
     }
   });
--- a/browser/components/loop/content/shared/js/views.js
+++ b/browser/components/loop/content/shared/js/views.js
@@ -215,31 +215,31 @@ loop.shared.views = (function(_, OT, l10
     getInitialState: function() {
       return {
         video: {enabled: false},
         audio: {enabled: false}
       };
     },
 
     componentDidMount: function() {
-      this.props.model.startSession();
-    },
-
-    componentWillMount: function() {
       this.listenTo(this.props.model, "session:connected",
                                       this.startPublishing);
       this.listenTo(this.props.model, "session:stream-created",
                                       this._streamCreated);
       this.listenTo(this.props.model, ["session:peer-hungup",
                                        "session:network-disconnected",
                                        "session:ended"].join(" "),
                                        this.stopPublishing);
+
+      this.props.model.startSession();
     },
 
     componentWillUnmount: function() {
+      // Unregister all local event listeners
+      this.stopListening();
       this.hangup();
     },
 
     hangup: function() {
       this.stopPublishing();
       this.props.model.endSession();
     },
 
@@ -274,30 +274,29 @@ loop.shared.views = (function(_, OT, l10
     startPublishing: function(event) {
       var outgoing = this.getDOMNode().querySelector(".outgoing");
 
       // XXX move this into its StreamingVideo component?
       this.publisher = this.props.sdk.initPublisher(
         outgoing, this.publisherConfig);
 
       // Suppress OT GuM custom dialog, see bug 1018875
-      function preventOpeningAccessDialog(event) {
-        event.preventDefault();
-      }
-      this.publisher.on("accessDialogOpened", preventOpeningAccessDialog);
-      this.publisher.on("accessDenied", preventOpeningAccessDialog);
+      this.listenTo(this.publisher, "accessDialogOpened accessDenied",
+                    function(event) {
+                      event.preventDefault();
+                    });
 
-      this.publisher.on("streamCreated", function(event) {
+      this.listenTo(this.publisher, "streamCreated", function(event) {
         this.setState({
           audio: {enabled: event.stream.hasAudio},
           video: {enabled: event.stream.hasVideo}
         });
       }.bind(this));
 
-      this.publisher.on("streamDestroyed", function() {
+      this.listenTo(this.publisher, "streamDestroyed", function() {
         this.setState({
           audio: {enabled: false},
           video: {enabled: false}
         });
       }.bind(this));
 
       this.props.model.session.publish(this.publisher);
     },
@@ -317,19 +316,18 @@ loop.shared.views = (function(_, OT, l10
         this.setState({video: {enabled: enabled}});
       }
     },
 
     /**
      * Unpublishes local stream.
      */
     stopPublishing: function() {
-      // Unregister access OT GuM custom dialog listeners, see bug 1018875
-      this.publisher.off("accessDialogOpened");
-      this.publisher.off("accessDenied");
+      // Unregister listeners for publisher events
+      this.stopListening(this.publisher);
 
       this.props.model.session.unpublish(this.publisher);
     },
 
     render: function() {
       return (
         React.DOM.div( {className:"conversation"}, 
           ConversationToolbar( {video:this.state.video,
--- a/browser/components/loop/content/shared/js/views.jsx
+++ b/browser/components/loop/content/shared/js/views.jsx
@@ -215,31 +215,31 @@ loop.shared.views = (function(_, OT, l10
     getInitialState: function() {
       return {
         video: {enabled: false},
         audio: {enabled: false}
       };
     },
 
     componentDidMount: function() {
-      this.props.model.startSession();
-    },
-
-    componentWillMount: function() {
       this.listenTo(this.props.model, "session:connected",
                                       this.startPublishing);
       this.listenTo(this.props.model, "session:stream-created",
                                       this._streamCreated);
       this.listenTo(this.props.model, ["session:peer-hungup",
                                        "session:network-disconnected",
                                        "session:ended"].join(" "),
                                        this.stopPublishing);
+
+      this.props.model.startSession();
     },
 
     componentWillUnmount: function() {
+      // Unregister all local event listeners
+      this.stopListening();
       this.hangup();
     },
 
     hangup: function() {
       this.stopPublishing();
       this.props.model.endSession();
     },
 
@@ -274,30 +274,29 @@ loop.shared.views = (function(_, OT, l10
     startPublishing: function(event) {
       var outgoing = this.getDOMNode().querySelector(".outgoing");
 
       // XXX move this into its StreamingVideo component?
       this.publisher = this.props.sdk.initPublisher(
         outgoing, this.publisherConfig);
 
       // Suppress OT GuM custom dialog, see bug 1018875
-      function preventOpeningAccessDialog(event) {
-        event.preventDefault();
-      }
-      this.publisher.on("accessDialogOpened", preventOpeningAccessDialog);
-      this.publisher.on("accessDenied", preventOpeningAccessDialog);
+      this.listenTo(this.publisher, "accessDialogOpened accessDenied",
+                    function(event) {
+                      event.preventDefault();
+                    });
 
-      this.publisher.on("streamCreated", function(event) {
+      this.listenTo(this.publisher, "streamCreated", function(event) {
         this.setState({
           audio: {enabled: event.stream.hasAudio},
           video: {enabled: event.stream.hasVideo}
         });
       }.bind(this));
 
-      this.publisher.on("streamDestroyed", function() {
+      this.listenTo(this.publisher, "streamDestroyed", function() {
         this.setState({
           audio: {enabled: false},
           video: {enabled: false}
         });
       }.bind(this));
 
       this.props.model.session.publish(this.publisher);
     },
@@ -317,19 +316,18 @@ loop.shared.views = (function(_, OT, l10
         this.setState({video: {enabled: enabled}});
       }
     },
 
     /**
      * Unpublishes local stream.
      */
     stopPublishing: function() {
-      // Unregister access OT GuM custom dialog listeners, see bug 1018875
-      this.publisher.off("accessDialogOpened");
-      this.publisher.off("accessDenied");
+      // Unregister listeners for publisher events
+      this.stopListening(this.publisher);
 
       this.props.model.session.unpublish(this.publisher);
     },
 
     render: function() {
       return (
         <div className="conversation">
           <ConversationToolbar video={this.state.video}
new file mode 100755
--- /dev/null
+++ b/browser/components/loop/run-all-loop-tests.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# Run from topsrcdir, no args
+
+set -e
+
+# Main tests
+./mach xpcshell-test browser/components/loop/
+./mach marionette-test browser/components/loop/manifest.ini
+
+# The browser_parsable_css.js can fail if we add some css that isn't parsable.
+./mach mochitest browser/components/loop/test/mochitest browser/base/content/test/general/browser_parsable_css.js
--- a/browser/components/loop/test/desktop-local/panel_test.js
+++ b/browser/components/loop/test/desktop-local/panel_test.js
@@ -43,17 +43,17 @@ describe("loop.panel", function() {
       },
       getStrings: function() {
         return JSON.stringify({textContent: "fakeText"});
       },
       get locale() {
         return "en-US";
       },
       setLoopCharPref: sandbox.stub(),
-      getLoopCharPref: sandbox.stub()
+      getLoopCharPref: sandbox.stub().returns("unseen")
     };
 
     document.mozL10n.initialize(navigator.mozLoop);
   });
 
   afterEach(function() {
     delete navigator.mozLoop;
     sandbox.restore();
--- a/browser/components/loop/test/shared/views_test.js
+++ b/browser/components/loop/test/shared/views_test.js
@@ -189,22 +189,20 @@ describe("loop.shared.views", function()
       fakeSession = _.extend({
         connection: {connectionId: 42},
         connect: sandbox.spy(),
         disconnect: sandbox.spy(),
         publish: sandbox.spy(),
         unpublish: sandbox.spy(),
         subscribe: sandbox.spy()
       }, Backbone.Events);
-      fakePublisher = {
-        on: sandbox.spy(),
-        off: sandbox.spy(),
+      fakePublisher = _.extend({
         publishAudio: sandbox.spy(),
         publishVideo: sandbox.spy()
-      };
+      }, Backbone.Events);
       fakeSDK = {
         initPublisher: sandbox.stub().returns(fakePublisher),
         initSession: sandbox.stub().returns(fakeSession)
       };
       model = new sharedModels.ConversationModel(fakeSessionData, {
         sdk: fakeSDK,
         pendingCallTimeout: 1000
       });
@@ -243,52 +241,56 @@ describe("loop.shared.views", function()
         it("should stop publishing local streams", function() {
           comp.hangup();
 
           sinon.assert.calledOnce(fakeSession.unpublish);
         });
       });
 
       describe("#startPublishing", function() {
+        beforeEach(function() {
+          sandbox.stub(fakePublisher, "on");
+        });
+
         it("should publish local stream", function() {
           comp.startPublishing();
 
           sinon.assert.calledOnce(fakeSDK.initPublisher);
           sinon.assert.calledOnce(fakeSession.publish);
         });
 
         it("should start listening to OT publisher accessDialogOpened and " +
           " accessDenied events",
           function() {
             comp.startPublishing();
 
             sinon.assert.called(fakePublisher.on);
-            sinon.assert.calledWith(fakePublisher.on, "accessDialogOpened");
-            sinon.assert.calledWith(fakePublisher.on, "accessDenied");
+            sinon.assert.calledWith(fakePublisher.on,
+                                    "accessDialogOpened accessDenied");
           });
       });
 
       describe("#stopPublishing", function() {
         beforeEach(function() {
+          sandbox.stub(fakePublisher, "off");
           comp.startPublishing();
         });
 
         it("should stop publish local stream", function() {
           comp.stopPublishing();
 
           sinon.assert.calledOnce(fakeSession.unpublish);
         });
 
-        it("should unsubscribe from accessDialogOpened and accessDenied events",
+        it("should unsubscribe from publisher events",
           function() {
             comp.stopPublishing();
 
-            sinon.assert.calledTwice(fakePublisher.off);
-            sinon.assert.calledWith(fakePublisher.off, "accessDialogOpened");
-            sinon.assert.calledWith(fakePublisher.off, "accessDenied");
+            // Note: Backbone.Events#stopListening calls off() on passed object.
+            sinon.assert.calledOnce(fakePublisher.off);
           });
       });
 
       describe("#publishStream", function() {
         var comp;
 
         beforeEach(function() {
           comp = mountTestComponent({sdk: fakeSDK, model: model});
@@ -362,16 +364,45 @@ describe("loop.shared.views", function()
           function() {
             comp.startPublishing();
 
             model.trigger("session:network-disconnected");
 
             sinon.assert.calledOnce(fakeSession.unpublish);
           });
       });
+
+      describe("Publisher events", function() {
+        beforeEach(function() {
+          comp.startPublishing();
+        });
+
+        it("should set audio state on streamCreated", function() {
+          fakePublisher.trigger("streamCreated", {stream: {hasAudio: true}});
+          expect(comp.state.audio.enabled).eql(true);
+
+          fakePublisher.trigger("streamCreated", {stream: {hasAudio: false}});
+          expect(comp.state.audio.enabled).eql(false);
+        });
+
+        it("should set video state on streamCreated", function() {
+          fakePublisher.trigger("streamCreated", {stream: {hasVideo: true}});
+          expect(comp.state.video.enabled).eql(true);
+
+          fakePublisher.trigger("streamCreated", {stream: {hasVideo: false}});
+          expect(comp.state.video.enabled).eql(false);
+        });
+
+        it("should set media state on streamDestroyed", function() {
+          fakePublisher.trigger("streamDestroyed");
+
+          expect(comp.state.audio.enabled).eql(false);
+          expect(comp.state.video.enabled).eql(false);
+        });
+      });
     });
   });
 
   describe("NotificationView", function() {
     var collection, model, view;
 
     beforeEach(function() {
       $("#fixtures").append('<div id="test-notif"></div>');
--- a/browser/components/sessionstore/test/browser_privatetabs.js
+++ b/browser/components/sessionstore/test/browser_privatetabs.js
@@ -60,17 +60,17 @@ add_task(function() {
     if (tab2) {
       gBrowser.removeTab(tab2);
     }
   }
 });
 
 add_task(function () {
   const FRAME_SCRIPT = "data:," +
-    "docShell.QueryInterface%28Ci.nsILoadContext%29.usePrivateBrowsing%3Dtrue";
+    "docShell.QueryInterface%28Components.interfaces.nsILoadContext%29.usePrivateBrowsing%3Dtrue";
 
   // Clear the list of closed windows.
   while (ss.getClosedWindowCount()) {
     ss.forgetClosedWindow(0);
   }
 
   // Create a new window to attach our frame script to.
   let win = yield promiseNewWindowLoaded();
--- a/browser/components/sessionstore/test/content-forms.js
+++ b/browser/components/sessionstore/test/content-forms.js
@@ -1,14 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
+let {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
 /**
  * This frame script is only loaded for sessionstore mochitests. It contains
  * a bunch of utility functions used to test form data collection and
  * restoration in remote browsers.
  */
 
 function queryElement(data) {
   let frame = content;
--- a/browser/installer/Makefile.in
+++ b/browser/installer/Makefile.in
@@ -11,21 +11,19 @@ MOZ_PKG_REMOVALS = $(srcdir)/removed-fil
 
 MOZ_PKG_MANIFEST_P = $(srcdir)/package-manifest.in
 
 ifdef MOZ_MULET
 MOZ_PKG_MANIFEST_P += $(topsrcdir)/b2g/installer/package-manifest.in
 endif
 
 # Some files have been already bundled with xulrunner
-ifndef SYSTEM_LIBXUL
 ifndef MOZ_MULET
 MOZ_PKG_FATAL_WARNINGS = 1
 endif
-endif
 
 DEFINES += -DAB_CD=$(AB_CD) -DMOZ_APP_NAME=$(MOZ_APP_NAME) -DPREF_DIR=$(PREF_DIR)
 
 ifdef LIBXUL_SDK
 DEFINES += -DLIBXUL_SDK=1
 endif
 
 ifdef MOZ_DEBUG
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -741,18 +741,18 @@
 @BINPATH@/@DLL_PREFIX@softokn3@DLL_SUFFIX@
 #endif
 @BINPATH@/chrome/pippki@JAREXT@
 @BINPATH@/chrome/pippki.manifest
 @BINPATH@/components/pipboot.xpt
 @BINPATH@/components/pipnss.xpt
 @BINPATH@/components/pippki.xpt
 
-; For content sandboxing
-#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
+; For process sandboxing
+#if defined(XP_WIN)
 @BINPATH@/@DLL_PREFIX@sandboxbroker@DLL_SUFFIX@
 #endif
 
 ; for Solaris SPARC
 #ifdef SOLARIS
 bin/libfreebl_32fpu_3.so
 bin/libfreebl_32int_3.so
 bin/libfreebl_32int64_3.so
--- a/browser/installer/windows/nsis/defines.nsi.in
+++ b/browser/installer/windows/nsis/defines.nsi.in
@@ -73,20 +73,16 @@
 #ifdef MOZ_MAINTENANCE_SERVICE
 !define MOZ_MAINTENANCE_SERVICE
 #endif
 
 #ifdef MOZ_METRO
 !define MOZ_METRO
 #endif
 
-#ifdef MOZ_CONTENT_SANDBOX
-!define MOZ_CONTENT_SANDBOX
-#endif
-
 # File details shared by both the installer and uninstaller
 VIProductVersion "1.0.0.0"
 VIAddVersionKey "ProductName"     "${BrandShortName}"
 VIAddVersionKey "CompanyName"     "${CompanyName}"
 #ifdef MOZ_OFFICIAL_BRANDING
 VIAddVersionKey "LegalTrademarks" "${BrandShortName} is a Trademark of The Mozilla Foundation."
 #endif
 VIAddVersionKey "LegalCopyright"  "${CompanyName}"
--- a/browser/installer/windows/nsis/shared.nsh
+++ b/browser/installer/windows/nsis/shared.nsh
@@ -1494,19 +1494,17 @@ FunctionEnd
   ; returns after the first check.
   Push "end"
   Push "AccessibleMarshal.dll"
   Push "freebl3.dll"
   Push "nssckbi.dll"
   Push "nspr4.dll"
   Push "nssdbm3.dll"
   Push "mozsqlite3.dll"
-!ifdef MOZ_CONTENT_SANDBOX
   Push "sandboxbroker.dll"
-!endif
   Push "xpcom.dll"
   Push "crashreporter.exe"
   Push "updater.exe"
   Push "${FileMainEXE}"
 !macroend
 !define PushFilesToCheck "!insertmacro PushFilesToCheck"
 
 ; Sets this installation as the default browser by setting the registry keys
rename from caps/src/DomainPolicy.cpp
rename to caps/DomainPolicy.cpp
rename from caps/include/DomainPolicy.h
rename to caps/DomainPolicy.h
deleted file mode 100644
--- a/caps/idl/moz.build
+++ /dev/null
@@ -1,14 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-XPIDL_SOURCES += [
-    'nsIDomainPolicy.idl',
-    'nsIPrincipal.idl',
-    'nsIScriptSecurityManager.idl',
-]
-
-XPIDL_MODULE = 'caps'
-
deleted file mode 100644
--- a/caps/include/moz.build
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-EXPORTS += [
-    'nsJSPrincipals.h',
-    'nsNullPrincipal.h',
-]
-
--- a/caps/moz.build
+++ b/caps/moz.build
@@ -1,9 +1,40 @@
 # -*- 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/.
 
-DIRS += ['idl', 'include', 'src']
 TEST_DIRS += ['tests/mochitest']
 
+XPIDL_SOURCES += [
+    'nsIDomainPolicy.idl',
+    'nsIPrincipal.idl',
+    'nsIScriptSecurityManager.idl',
+]
+
+XPIDL_MODULE = 'caps'
+
+EXPORTS += [
+    'nsJSPrincipals.h',
+    'nsNullPrincipal.h',
+]
+
+UNIFIED_SOURCES += [
+    'DomainPolicy.cpp',
+    'nsJSPrincipals.cpp',
+    'nsNullPrincipal.cpp',
+    'nsNullPrincipalURI.cpp',
+    'nsPrincipal.cpp',
+    'nsScriptSecurityManager.cpp',
+    'nsSystemPrincipal.cpp',
+]
+
+MSVC_ENABLE_PGO = True
+
+LOCAL_INCLUDES += [
+    '/dom/base',
+    '/js/xpconnect/src',
+]
+
+FINAL_LIBRARY = 'gklayout'
+
rename from caps/idl/nsIDomainPolicy.idl
rename to caps/nsIDomainPolicy.idl
rename from caps/idl/nsIPrincipal.idl
rename to caps/nsIPrincipal.idl
rename from caps/idl/nsIScriptSecurityManager.idl
rename to caps/nsIScriptSecurityManager.idl
rename from caps/src/nsJSPrincipals.cpp
rename to caps/nsJSPrincipals.cpp
rename from caps/include/nsJSPrincipals.h
rename to caps/nsJSPrincipals.h
rename from caps/src/nsNullPrincipal.cpp
rename to caps/nsNullPrincipal.cpp
rename from caps/include/nsNullPrincipal.h
rename to caps/nsNullPrincipal.h
rename from caps/src/nsNullPrincipalURI.cpp
rename to caps/nsNullPrincipalURI.cpp
rename from caps/src/nsNullPrincipalURI.h
rename to caps/nsNullPrincipalURI.h
rename from caps/src/nsPrincipal.cpp
rename to caps/nsPrincipal.cpp
rename from caps/include/nsPrincipal.h
rename to caps/nsPrincipal.h
rename from caps/src/nsScriptSecurityManager.cpp
rename to caps/nsScriptSecurityManager.cpp
rename from caps/include/nsScriptSecurityManager.h
rename to caps/nsScriptSecurityManager.h
rename from caps/src/nsSystemPrincipal.cpp
rename to caps/nsSystemPrincipal.cpp
rename from caps/include/nsSystemPrincipal.h
rename to caps/nsSystemPrincipal.h
deleted file mode 100644
--- a/caps/src/moz.build
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-UNIFIED_SOURCES += [
-    'DomainPolicy.cpp',
-    'nsJSPrincipals.cpp',
-    'nsNullPrincipal.cpp',
-    'nsNullPrincipalURI.cpp',
-    'nsPrincipal.cpp',
-    'nsScriptSecurityManager.cpp',
-    'nsSystemPrincipal.cpp',
-]
-
-MSVC_ENABLE_PGO = True
-
-LOCAL_INCLUDES += [
-    '../include',
-    '/dom/base',
-    '/js/xpconnect/src',
-]
-
-FINAL_LIBRARY = 'gklayout'
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -38,21 +38,16 @@ include $(topsrcdir)/config/makefiles/ma
 ifdef REBUILD_CHECK
 REPORT_BUILD = $(info $(shell $(PYTHON) $(MOZILLA_DIR)/config/rebuild_check.py $@ $^))
 else
 REPORT_BUILD = $(info $(notdir $@))
 endif
 
 EXEC			= exec
 
-# Don't copy xulrunner files at install time, when using system xulrunner
-ifdef SYSTEM_LIBXUL
-  SKIP_COPY_XULRUNNER=1
-endif
-
 # ELOG prints out failed command when building silently (gmake -s). Pymake
 # prints out failed commands anyway, so ELOG just makes things worse by
 # forcing shell invocations.
 ifneq (,$(findstring s, $(filter-out --%, $(MAKEFLAGS))))
   ELOG := $(EXEC) sh $(BUILD_TOOLS)/print-failed-commands.sh
 else
   ELOG :=
 endif # -s
--- a/configure.in
+++ b/configure.in
@@ -2113,16 +2113,21 @@ ia64*-hpux*)
         MKSHLIB_FORCE_ALL=
         MKSHLIB_UNFORCE_ALL=
         DSO_LDOPTS=-SUBSYSTEM:WINDOWS
         _USE_CPP_INCLUDE_FLAG=1
         _DEFINES_CFLAGS='-FI $(DEPTH)/dist/include/mozilla-config.h -DMOZILLA_CLIENT'
         _DEFINES_CXXFLAGS='-FI $(DEPTH)/dist/include/mozilla-config.h -DMOZILLA_CLIENT'
         CFLAGS="$CFLAGS -W3 -Gy"
         CXXFLAGS="$CXXFLAGS -W3 -Gy"
+        if test "$_CC_SUITE" -ge "11"; then
+            dnl VS2012+ defaults to -arch:SSE2.
+            CFLAGS="$CFLAGS -arch:IA32"
+            CXXFLAGS="$CXXFLAGS -arch:IA32"
+        fi
         if test "$_CC_SUITE" -ge "12"; then
             dnl VS2013+ requires -FS when parallel building by make -jN.
             dnl If nothing, compiler sometimes causes C1041 error.
             dnl
             dnl Visual Studio 2013 supports -Gw flags
             dnl http://blogs.msdn.com/b/vcblog/archive/2013/09/11/introducing-gw-compiler-switch.aspx
             CFLAGS="$CFLAGS -FS -Gw"
             CXXFLAGS="$CXXFLAGS -FS -Gw"
@@ -3417,43 +3422,21 @@ dnl ====================================
 dnl =
 dnl = Check for external package dependencies
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(External Packages)
 
 MOZ_ARG_WITH_STRING(libxul-sdk,
 [  --with-libxul-sdk=PFX   Use the libXUL SDK at <PFX>],
-  LIBXUL_SDK_DIR=$withval)
-
-if test "$LIBXUL_SDK_DIR" = "yes"; then
-    AC_MSG_ERROR([--with-libxul-sdk must specify a path])
-elif test -n "$LIBXUL_SDK_DIR" -a "$LIBXUL_SDK_DIR" != "no"; then
-    LIBXUL_SDK=`cd "$LIBXUL_SDK_DIR" && pwd`
-
-    if test ! -f "$LIBXUL_SDK/include/xpcom-config.h"; then
-        AC_MSG_ERROR([$LIBXUL_SDK/include/xpcom-config.h doesn't exist])
-    fi
-
-fi
-AC_SUBST(LIBXUL_SDK)
-
-if test -n "$LIBXUL_SDK"; then
-    LIBXUL_DIST="$LIBXUL_SDK"
-else
-    LIBXUL_DIST="$MOZ_BUILD_ROOT/dist"
-fi
+  AC_MSG_ERROR([--with-libxul-sdk is not supported anymore.]))
+
+LIBXUL_DIST="$MOZ_BUILD_ROOT/dist"
 AC_SUBST(LIBXUL_DIST)
 
-SYSTEM_LIBXUL=
-
-MOZ_ARG_WITH_BOOL(system-libxul,
-[  --with-system-libxul    Use system installed libxul SDK],
-    SYSTEM_LIBXUL=1)
-
 dnl ========================================================
 dnl = If NSPR was not detected in the system,
 dnl = use the one in the source tree (mozilla/nsprpub)
 dnl ========================================================
 MOZ_ARG_WITH_BOOL(system-nspr,
 [  --with-system-nspr      Use system installed NSPR],
     _USE_SYSTEM_NSPR=1 )
 
@@ -3862,24 +3845,25 @@ MOZ_WAVE=1
 MOZ_SAMPLE_TYPE_FLOAT32=
 MOZ_SAMPLE_TYPE_S16=
 MOZ_OPUS=1
 MOZ_WEBM=1
 MOZ_GSTREAMER=
 MOZ_DIRECTSHOW=
 MOZ_WMF=
 MOZ_FMP4=
+MOZ_EME=1
 MOZ_FFMPEG=
 MOZ_WEBRTC=1
 MOZ_PEERCONNECTION=
 MOZ_SRTP=
 MOZ_WEBRTC_SIGNALING=
 MOZ_WEBRTC_ASSERT_ALWAYS=1
 MOZ_SCTP=
-MOZ_MEDIA_PLUGINS=
+MOZ_ANDROID_OMX=
 MOZ_MEDIA_NAVIGATOR=
 MOZ_OMX_PLUGIN=
 MOZ_VPX=
 MOZ_VPX_ERROR_CONCEALMENT=
 MOZ_WEBSPEECH=1
 VPX_AS=
 VPX_ASFLAGS=
 VPX_AS_DASH_C_FLAG=
@@ -5241,32 +5225,44 @@ MOZ_ARG_DISABLE_BOOL(fmp4,
 [  --disable-fmp4  Disable support for in built Fragmented MP4 parsing],
     MOZ_FMP4=,
     MOZ_FMP4=1)
 
 if test -n "$MOZ_FMP4"; then
     AC_DEFINE(MOZ_FMP4)
 fi;
 
+dnl ========================================================
+dnl = EME support
+dnl ========================================================
+
+MOZ_ARG_DISABLE_BOOL(eme,
+[  --disable-eme  Disable support for Encrypted Media Extensions],
+    MOZ_EME=,
+    MOZ_EME=1)
+
+if test -n "$MOZ_EME"; then
+    AC_DEFINE(MOZ_EME)
+fi;
 
 dnl ========================================================
 dnl = Enable media plugin support
 dnl ========================================================
 if test "$OS_TARGET" = Android -a x"$MOZ_WIDGET_TOOLKIT" != x"gonk"; then
   dnl Enable support on android by default
-  MOZ_MEDIA_PLUGINS=1
-fi
-
-MOZ_ARG_ENABLE_BOOL(media-plugins,
-[  --enable-media-plugins  Enable support for media plugins],
-    MOZ_MEDIA_PLUGINS=1,
-    MOZ_MEDIA_PLUGINS=)
-
-if test -n "$MOZ_MEDIA_PLUGINS"; then
-  AC_DEFINE(MOZ_MEDIA_PLUGINS)
+  MOZ_ANDROID_OMX=1
+fi
+
+MOZ_ARG_ENABLE_BOOL(android-omx,
+[  --enable-android-omx  Enable support for Android OMX media backend],
+    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
@@ -8712,17 +8708,16 @@ COMPILE_CXXFLAGS=`echo \
 HOST_CFLAGS=`echo \
     $HOST_CFLAGS \
     $_DEPEND_CFLAGS`
 
 HOST_CXXFLAGS=`echo \
     $HOST_CXXFLAGS \
     $_DEPEND_CFLAGS`
 
-AC_SUBST(SYSTEM_LIBXUL)
 AC_SUBST(MOZ_NATIVE_JPEG)
 AC_SUBST(MOZ_NATIVE_PNG)
 AC_SUBST(MOZ_NATIVE_BZ2)
 
 AC_SUBST(MOZ_JPEG_CFLAGS)
 AC_SUBST(MOZ_JPEG_LIBS)
 AC_SUBST(MOZ_BZ2_CFLAGS)
 AC_SUBST(MOZ_BZ2_LIBS)
@@ -8820,18 +8815,19 @@ AC_SUBST(MOZ_APP_EXTRA_LIBS)
 AC_SUBST(MOZ_WAVE)
 AC_SUBST(MOZ_VORBIS)
 AC_SUBST(MOZ_TREMOR)
 AC_SUBST(MOZ_OPUS)
 AC_SUBST(MOZ_WEBM)
 AC_SUBST(MOZ_WMF)
 AC_SUBST(MOZ_FFMPEG)
 AC_SUBST(MOZ_FMP4)
+AC_SUBST(MOZ_EME)
 AC_SUBST(MOZ_DIRECTSHOW)
-AC_SUBST(MOZ_MEDIA_PLUGINS)
+AC_SUBST(MOZ_ANDROID_OMX)
 AC_SUBST(MOZ_APPLEMEDIA)
 AC_SUBST(MOZ_OMX_PLUGIN)
 AC_SUBST(MOZ_VPX_ERROR_CONCEALMENT)
 AC_SUBST(MOZ_VPX)
 AC_SUBST(VPX_AS)
 AC_SUBST(VPX_ASFLAGS)
 AC_SUBST(VPX_DASH_C_FLAG)
 AC_SUBST(VPX_AS_CONVERSION)
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -74,17 +74,18 @@ class Element;
 class EventHandlerNonNull;
 class OnErrorEventHandlerNonNull;
 template<typename T> class Optional;
 class TextOrElementOrDocument;
 struct DOMPointInit;
 } // namespace dom
 } // namespace mozilla
 
-#define NODE_FLAG_BIT(n_) (1U << (WRAPPER_CACHE_FLAGS_BITS_USED + (n_)))
+#define NODE_FLAG_BIT(n_) \
+  (nsWrapperCache::FlagsType(1U) << (WRAPPER_CACHE_FLAGS_BITS_USED + (n_)))
 
 enum {
   // This bit will be set if the node has a listener manager.
   NODE_HAS_LISTENERMANAGER =              NODE_FLAG_BIT(0),
 
   // Whether this node has had any properties set on it
   NODE_HAS_PROPERTIES =                   NODE_FLAG_BIT(1),
 
--- a/content/base/src/moz.build
+++ b/content/base/src/moz.build
@@ -214,17 +214,17 @@ EXTRA_JS_MODULES += [
 FAIL_ON_WARNINGS = True
 
 MSVC_ENABLE_PGO = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
-    '/caps/include',
+    '/caps',
     '/content/html/content/src',
     '/content/html/document/src',
     '/content/svg/content/src',
     '/content/xml/content/src',
     '/content/xml/document/src',
     '/content/xul/content/src',
     '/content/xul/document/src',
     '/docshell/base',
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -9,16 +9,17 @@
 
 #include "AppProcessChecker.h"
 #include "ContentChild.h"
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
 #include "nsError.h"
 #include "nsIXPConnect.h"
 #include "jsapi.h"
+#include "jsfriendapi.h"
 #include "nsJSUtils.h"
 #include "nsJSPrincipals.h"
 #include "nsNetUtil.h"
 #include "nsScriptLoader.h"
 #include "nsFrameLoader.h"
 #include "nsIXULRuntime.h"
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
@@ -424,19 +425,16 @@ nsFrameMessageManager::RemoveWeakMessage
 
 // nsIFrameScriptLoader
 
 NS_IMETHODIMP
 nsFrameMessageManager::LoadFrameScript(const nsAString& aURL,
                                        bool aAllowDelayedLoad,
                                        bool aRunInGlobalScope)
 {
-  // FIXME: Bug 673569 is currently disabled.
-  aRunInGlobalScope = true;
-
   if (aAllowDelayedLoad) {
     if (IsGlobal() || IsBroadcaster()) {
       // Cache for future windows or frames
       mPendingScripts.AppendElement(aURL);
       mPendingScriptsGlobalStates.AppendElement(aRunInGlobalScope);
     } else if (!mCallback) {
       // We're frame message manager, which isn't connected yet.
       mPendingScripts.AppendElement(aURL);
@@ -1430,59 +1428,56 @@ nsFrameScriptExecutor::LoadFrameScriptIn
                                                bool aRunInGlobalScope)
 {
   if (!mGlobal || !sCachedScripts) {
     return;
   }
 
   AutoSafeJSContext cx;
   JS::Rooted<JSScript*> script(cx);
-  JS::Rooted<JSObject*> funobj(cx);
 
   nsFrameScriptObjectExecutorHolder* holder = sCachedScripts->Get(aURL);
   if (holder && holder->WillRunInGlobalScope() == aRunInGlobalScope) {
     script = holder->mScript;
-    funobj = holder->mFunction;
   } else {
     // Don't put anything in the cache if we already have an entry
     // with a different WillRunInGlobalScope() value.
     bool shouldCache = !holder;
     TryCacheLoadAndCompileScript(aURL, aRunInGlobalScope,
-                                 shouldCache, &script, &funobj);
+                                 shouldCache, &script);
   }
 
   JS::Rooted<JSObject*> global(cx, mGlobal->GetJSObject());
   if (global) {
     JSAutoCompartment ac(cx, global);
     bool ok = true;
-    if (funobj) {
-      JS::Rooted<JSObject*> method(cx, JS_CloneFunctionObject(cx, funobj, global));
-      if (!method) {
-        return;
+    if (script) {
+      if (aRunInGlobalScope) {
+        ok = JS::CloneAndExecuteScript(cx, global, script);
+      } else {
+        JS::Rooted<JSObject*> scope(cx);
+        ok = js::ExecuteInGlobalAndReturnScope(cx, global, script, &scope);
+        if (ok){
+          // Force the scope to stay alive.
+          mAnonymousGlobalScopes.AppendElement(scope);
+        }
       }
-      JS::Rooted<JS::Value> rval(cx);
-      JS::Rooted<JS::Value> methodVal(cx, JS::ObjectValue(*method));
-      ok = JS_CallFunctionValue(cx, global, methodVal,
-                                JS::HandleValueArray::empty(), &rval);
-    } else if (script) {
-      ok = JS::CloneAndExecuteScript(cx, global, script);
     }
 
     if (!ok) {
       nsJSUtils::ReportPendingException(cx);
     }
   }
 }
 
 void
 nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
                                                     bool aRunInGlobalScope,
                                                     bool aShouldCache,
-                                                    JS::MutableHandle<JSScript*> aScriptp,
-                                                    JS::MutableHandle<JSObject*> aFunp)
+                                                    JS::MutableHandle<JSScript*> aScriptp)
 {
   nsCString url = NS_ConvertUTF16toUTF8(aURL);
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), url);
   if (NS_FAILED(rv)) {
     return;
   }
 
@@ -1526,67 +1521,56 @@ nsFrameScriptExecutor::TryCacheLoadAndCo
 
   if (dataStringBuf && dataStringLength > 0) {
     AutoSafeJSContext cx;
     JS::Rooted<JSObject*> global(cx, mGlobal->GetJSObject());
     if (global) {
       JSAutoCompartment ac(cx, global);
       JS::CompileOptions options(cx);
       options.setFileAndLine(url.get(), 1);
+      options.setNoScriptRval(true);
       JS::Rooted<JSScript*> script(cx);
-      JS::Rooted<JSObject*> funobj(cx);
+
       if (aRunInGlobalScope) {
-        options.setNoScriptRval(true);
         if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script)) {
           return;
         }
       } else {
-        JS::Rooted<JSFunction *> fun(cx);
-        if (!JS::CompileFunction(cx, JS::NullPtr(), options,
-                                 nullptr, 0, nullptr, /* name, nargs, args */
-                                 srcBuf, &fun))
-        {
+        // We can't clone compile-and-go scripts.
+        options.setCompileAndGo(false);
+        if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script)) {
           return;
         }
-        funobj = JS_GetFunctionObject(fun);
-      }
-
-      if (!script && !funobj) {
-        return;
       }
 
       aScriptp.set(script);
-      aFunp.set(funobj);
 
       nsAutoCString scheme;
       uri->GetScheme(scheme);
       // We don't cache data: scripts!
       if (aShouldCache && !scheme.EqualsLiteral("data")) {
         nsFrameScriptObjectExecutorHolder* holder;
 
         // Root the object also for caching.
         if (script) {
-          holder = new nsFrameScriptObjectExecutorHolder(cx, script);
-        } else {
-          holder = new nsFrameScriptObjectExecutorHolder(cx, funobj);
+          holder = new nsFrameScriptObjectExecutorHolder(cx, script, aRunInGlobalScope);
         }
         sCachedScripts->Put(aURL, holder);
       }
     }
   }
 }
 
 void
 nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
                                                     bool aRunInGlobalScope)
 {
   AutoSafeJSContext cx;
   JS::Rooted<JSScript*> script(cx);
-  JS::Rooted<JSObject*> funobj(cx);
-  TryCacheLoadAndCompileScript(aURL, aRunInGlobalScope, true, &script, &funobj);
+  TryCacheLoadAndCompileScript(aURL, aRunInGlobalScope, true, &script);
 }
 
 bool
 nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope,
                                                   const nsACString& aID)
 {
 
   nsCOMPtr<nsIJSRuntimeService> runtimeSvc =
--- a/content/base/src/nsFrameMessageManager.h
+++ b/content/base/src/nsFrameMessageManager.h
@@ -355,62 +355,58 @@ private:
   JS::PersistentRooted<JSObject*> mCpows;
   nsCOMPtr<nsIPrincipal> mPrincipal;
 };
 
 class nsScriptCacheCleaner;
 
 struct nsFrameScriptObjectExecutorHolder
 {
-  nsFrameScriptObjectExecutorHolder(JSContext* aCx, JSScript* aScript)
-   : mScript(aCx, aScript), mFunction(aCx, nullptr)
-  { MOZ_COUNT_CTOR(nsFrameScriptObjectExecutorHolder); }
-
-  nsFrameScriptObjectExecutorHolder(JSContext* aCx, JSObject* aFunction)
-   : mScript(aCx, nullptr), mFunction(aCx, aFunction)
+  nsFrameScriptObjectExecutorHolder(JSContext* aCx, JSScript* aScript, bool aRunInGlobalScope)
+   : mScript(aCx, aScript), mRunInGlobalScope(aRunInGlobalScope)
   { MOZ_COUNT_CTOR(nsFrameScriptObjectExecutorHolder); }
 
   ~nsFrameScriptObjectExecutorHolder()
   { MOZ_COUNT_DTOR(nsFrameScriptObjectExecutorHolder); }
 
-  bool WillRunInGlobalScope() { return mScript; }
+  bool WillRunInGlobalScope() { return mRunInGlobalScope; }
 
   JS::PersistentRooted<JSScript*> mScript;
-  JS::PersistentRooted<JSObject*> mFunction;
+  bool mRunInGlobalScope;
 };
 
 class nsFrameScriptObjectExecutorStackHolder;
 
 class nsFrameScriptExecutor
 {
 public:
   static void Shutdown();
   already_AddRefed<nsIXPConnectJSObjectHolder> GetGlobal()
   {
     nsCOMPtr<nsIXPConnectJSObjectHolder> ref = mGlobal;
     return ref.forget();
   }
 protected:
   friend class nsFrameScriptCx;
-  nsFrameScriptExecutor()
-  { MOZ_COUNT_CTOR(nsFrameScriptExecutor); }
-  ~nsFrameScriptExecutor()
-  { MOZ_COUNT_DTOR(nsFrameScriptExecutor); }
+  nsFrameScriptExecutor() { MOZ_COUNT_CTOR(nsFrameScriptExecutor); }
+  ~nsFrameScriptExecutor() { MOZ_COUNT_DTOR(nsFrameScriptExecutor); }
+
   void DidCreateGlobal();
   void LoadFrameScriptInternal(const nsAString& aURL, bool aRunInGlobalScope);
   void TryCacheLoadAndCompileScript(const nsAString& aURL,
                                     bool aRunInGlobalScope,
                                     bool aShouldCache,
-                                    JS::MutableHandle<JSScript*> aScriptp,
-                                    JS::MutableHandle<JSObject*> aFunp);
+                                    JS::MutableHandle<JSScript*> aScriptp);
   void TryCacheLoadAndCompileScript(const nsAString& aURL,
                                     bool aRunInGlobalScope);
   bool InitTabChildGlobalInternal(nsISupports* aScope, const nsACString& aID);
   nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
   nsCOMPtr<nsIPrincipal> mPrincipal;
+  nsAutoTArray<JS::Heap<JSObject*>, 2> mAnonymousGlobalScopes;
+
   static nsDataHashtable<nsStringHashKey, nsFrameScriptObjectExecutorHolder*>* sCachedScripts;
   static nsScriptCacheCleaner* sScriptCacheCleaner;
 };
 
 class nsScriptCacheCleaner MOZ_FINAL : public nsIObserver
 {
   ~nsScriptCacheCleaner() {}
 
--- a/content/base/src/nsInProcessTabChildGlobal.cpp
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -98,30 +98,33 @@ nsInProcessTabChildGlobal::DoSendAsyncMe
 }
 
 nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
                                                      nsIContent* aOwner,
                                                      nsFrameMessageManager* aChrome)
 : mDocShell(aShell), mInitialized(false), mLoadingScript(false),
   mOwner(aOwner), mChromeMessageManager(aChrome)
 {
+  mozilla::HoldJSObjects(this);
 
   // If owner corresponds to an <iframe mozbrowser> or <iframe mozapp>, we'll
   // have to tweak our PreHandleEvent implementation.
   nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwner);
   if (browserFrame) {
     mIsBrowserOrAppFrame = browserFrame->GetReallyIsBrowserOrApp();
   }
   else {
     mIsBrowserOrAppFrame = false;
   }
 }
 
 nsInProcessTabChildGlobal::~nsInProcessTabChildGlobal()
 {
+  mAnonymousGlobalScopes.Clear();
+  mozilla::DropJSObjects(this);
 }
 
 /* [notxpcom] boolean markForCC (); */
 // This method isn't automatically forwarded safely because it's notxpcom, so
 // the IDL binding doesn't know what value to return.
 NS_IMETHODIMP_(bool)
 nsInProcessTabChildGlobal::MarkForCC()
 {
@@ -138,20 +141,38 @@ nsInProcessTabChildGlobal::Init()
   NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
                    "Couldn't initialize nsInProcessTabChildGlobal");
   mMessageManager = new nsFrameMessageManager(this,
                                               nullptr,
                                               dom::ipc::MM_CHILD);
   return NS_OK;
 }
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED(nsInProcessTabChildGlobal,
-                                   DOMEventTargetHelper,
-                                   mMessageManager,
-                                   mGlobal)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsInProcessTabChildGlobal)
+
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsInProcessTabChildGlobal,
+                                                  DOMEventTargetHelper)
+   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
+   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsInProcessTabChildGlobal,
+                                               DOMEventTargetHelper)
+  for (uint32_t i = 0; i < tmp->mAnonymousGlobalScopes.Length(); ++i) {
+    NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAnonymousGlobalScopes[i])
+  }
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsInProcessTabChildGlobal,
+                                                DOMEventTargetHelper)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mAnonymousGlobalScopes)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsInProcessTabChildGlobal)
   NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
   NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
--- a/content/base/src/nsInProcessTabChildGlobal.h
+++ b/content/base/src/nsInProcessTabChildGlobal.h
@@ -34,18 +34,19 @@ class nsInProcessTabChildGlobal : public
                                   public nsIScriptObjectPrincipal,
                                   public nsSupportsWeakReference,
                                   public mozilla::dom::ipc::MessageManagerCallback
 {
 public:
   nsInProcessTabChildGlobal(nsIDocShell* aShell, nsIContent* aOwner,
                             nsFrameMessageManager* aChrome);
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsInProcessTabChildGlobal,
-                                           mozilla::DOMEventTargetHelper)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsInProcessTabChildGlobal,
+                                                         mozilla::DOMEventTargetHelper)
+
   NS_FORWARD_SAFE_NSIMESSAGELISTENERMANAGER(mMessageManager)
   NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
   NS_IMETHOD SendSyncMessage(const nsAString& aMessageName,
                              JS::Handle<JS::Value> aObject,
                              JS::Handle<JS::Value> aRemote,
                              nsIPrincipal* aPrincipal,
                              JSContext* aCx,
                              uint8_t aArgc,
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -1412,17 +1412,17 @@ nsScriptLoader::OnStreamComplete(nsIStre
       UnblockParser(request);
       FireScriptAvailable(rv, request);
       ContinueParserAsync(request);
     } else {
       mPreloads.RemoveElement(request, PreloadRequestComparator());
     }
     rv = NS_OK;
   } else {
-    NS_Free(const_cast<uint8_t *>(aString));
+    moz_free(const_cast<uint8_t *>(aString));
     rv = NS_SUCCESS_ADOPTED_DATA;
   }
 
   // Process our request and/or any pending ones
   ProcessPendingRequests();
 
   return rv;
 }
--- a/content/base/test/chrome/cpows_child.js
+++ b/content/base/test/chrome/cpows_child.js
@@ -120,16 +120,18 @@ function async_test()
 {
   dump('beginning cpow async test\n');
   async_obj = make_object();
   sendAsyncMessage("cpows:async",
     make_json(),
     async_obj);
 }
 
+var rpc_obj;
+
 function rpc_test()
 {
   dump('beginning cpow rpc test\n');
   rpc_obj = make_object();
   rpc_obj.data.reenter = function  () {
     sendRpcMessage("cpows:reenter", { }, { data: { valid: true } });
     return "ok";
   }
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -2168,17 +2168,17 @@ WebGLContext::ReadPixels(GLint x, GLint 
         return rv.Throw(NS_ERROR_OUT_OF_MEMORY);
     }
 
     bool isSourceTypeFloat = false;
     if (mBoundFramebuffer &&
         mBoundFramebuffer->ColorAttachmentCount() &&
         mBoundFramebuffer->ColorAttachment(0).IsDefined())
     {
-        isSourceTypeFloat = mBoundFramebuffer->ColorAttachment(0).IsReadableFloat();
+        isSourceTypeFloat = mBoundFramebuffer->ColorAttachment(0).IsFloatType();
     }
 
     if (isReadTypeFloat != isSourceTypeFloat)
         return ErrorInvalidOperation("readPixels: Invalid type floatness");
 
     // Check the format and type params to assure they are an acceptable pair (as per spec)
     MakeContextCurrent();
 
--- a/content/canvas/src/WebGLFramebuffer.cpp
+++ b/content/canvas/src/WebGLFramebuffer.cpp
@@ -57,36 +57,42 @@ WebGLFramebuffer::Attachment::HasAlpha()
     if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
         format = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).WebGLFormat();
     else if (Renderbuffer())
         format = Renderbuffer()->InternalFormat();
     return FormatHasAlpha(format);
 }
 
 bool
-WebGLFramebuffer::Attachment::IsReadableFloat() const
+WebGLFramebuffer::Attachment::IsFloatType(FloatType floatType) const
 {
     if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel)) {
         GLenum type = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).WebGLType();
         switch (type) {
         case LOCAL_GL_FLOAT:
+            return floatType == FloatType::Full ||
+                   floatType == FloatType::Any;
         case LOCAL_GL_HALF_FLOAT_OES:
-            return true;
+            return floatType == FloatType::Half ||
+                   floatType == FloatType::Any;
         }
         return false;
     }
 
     if (Renderbuffer()) {
         GLenum format = Renderbuffer()->InternalFormat();
         switch (format) {
         case LOCAL_GL_RGB16F:
         case LOCAL_GL_RGBA16F:
+            return floatType == FloatType::Half ||
+                   floatType == FloatType::Any;
         case LOCAL_GL_RGB32F:
         case LOCAL_GL_RGBA32F:
-            return true;
+            return floatType == FloatType::Full ||
+                   floatType == FloatType::Any;
         }
         return false;
     }
 
     MOZ_ASSERT(false, "Should not get here.");
     return false;
 }
 
@@ -625,16 +631,36 @@ IsIncomplete(const WebGLFramebuffer::Att
 bool
 WebGLFramebuffer::HasIncompleteAttachments() const
 {
     bool hasIncomplete = false;
 
     size_t count = mColorAttachments.Length();
     for (size_t i = 0; i < count; i++) {
         hasIncomplete |= IsIncomplete(mColorAttachments[i]);
+
+        if (mColorAttachments[i].IsDefined()) {
+            // Excerpt from http://www.khronos.org/registry/webgl/extensions/OES_texture_float/
+            // New implementations should not implicitly support float rendering and
+            // applications should be modified to explicitly enable WEBGL_color_buffer_float.
+            if (mColorAttachments[i].IsFloatType(Attachment::FloatType::Full) &&
+                !Context()->IsExtensionEnabled(WebGLExtensionID::WEBGL_color_buffer_float))
+            {
+                hasIncomplete |= true;
+            }
+
+            // Excerpt from http://www.khronos.org/registry/webgl/extensions/OES_texture_half_float/
+            // New implementations should not implicitly support float rendering and
+            // applications should be modified to explicitly enable OES_color_buffer_half_float.
+            if (mColorAttachments[i].IsFloatType(Attachment::FloatType::Half) &&
+                !Context()->IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_half_float))
+            {
+                hasIncomplete |= true;
+            }
+        }
     }
 
     hasIncomplete |= IsIncomplete(mDepthAttachment);
     hasIncomplete |= IsIncomplete(mStencilAttachment);
     hasIncomplete |= IsIncomplete(mDepthStencilAttachment);
 
     return hasIncomplete;
 }
--- a/content/canvas/src/WebGLFramebuffer.h
+++ b/content/canvas/src/WebGLFramebuffer.h
@@ -6,16 +6,17 @@
 #ifndef WEBGLFRAMEBUFFER_H_
 #define WEBGLFRAMEBUFFER_H_
 
 #include "WebGLObjectModel.h"
 
 #include "nsWrapperCache.h"
 
 #include "mozilla/LinkedList.h"
+#include "mozilla/TypedEnum.h"
 
 namespace mozilla {
 
 class WebGLFramebufferAttachable;
 class WebGLTexture;
 class WebGLRenderbuffer;
 namespace gl {
     class GLContext;
@@ -47,17 +48,25 @@ public:
 
         bool IsDefined() const {
             return Texture() || Renderbuffer();
         }
 
         bool IsDeleteRequested() const;
 
         bool HasAlpha() const;
-        bool IsReadableFloat() const;
+
+        // For IsFloatType()
+        MOZ_BEGIN_NESTED_ENUM_CLASS(FloatType)
+            Any = 0,
+            Half,
+            Full
+        MOZ_END_NESTED_ENUM_CLASS(FloatType)
+
+        bool IsFloatType(FloatType floatType = FloatType::Any) const;
 
         void SetTexImage(WebGLTexture* tex, GLenum target, GLint level);
         void SetRenderbuffer(WebGLRenderbuffer* rb);
 
         const WebGLTexture* Texture() const {
             return mTexturePtr;
         }
         WebGLTexture* Texture() {
@@ -191,11 +200,13 @@ private:
     // we only store pointers to attached renderbuffers, not to attached textures, because
     // we will only need to initialize renderbuffers. Textures are already initialized.
     nsTArray<Attachment> mColorAttachments;
     Attachment mDepthAttachment,
                mStencilAttachment,
                mDepthStencilAttachment;
 };
 
+MOZ_FINISH_NESTED_ENUM_CLASS(WebGLFramebuffer::Attachment::FloatType)
+
 } // namespace mozilla
 
 #endif
--- a/content/canvas/test/webgl-conformance/conformance/extensions/oes-texture-float.html
+++ b/content/canvas/test/webgl-conformance/conformance/extensions/oes-texture-float.html
@@ -151,24 +151,20 @@ function runRenderTargetTest(testProgram
     gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.FLOAT, null);
     glErrorShouldBe(gl, gl.NO_ERROR, "floating-point texture allocation should succeed if OES_texture_float is enabled");
 
     // Use this texture as a render target.
     var fbo = gl.createFramebuffer();
     gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
     gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
     gl.bindTexture(gl.TEXTURE_2D, null);
-    shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
-    // While strictly speaking it is probably legal for a WebGL implementation to support
-    // floating-point textures but not as attachments to framebuffer objects, any such
-    // implementation is so poor that it arguably should not advertise support for the
-    // OES_texture_float extension. For this reason the conformance test requires that the
-    // framebuffer is complete here.
-    if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)
+    if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
+        debug("floating-point " + formatString + " render target not supported -- this is legal");
         return;
+    }
 
     var renderProgram =
         wtu.setupProgram(gl,
                          ["positionVertexShader", "floatingPointFragmentShader"],
                          ['vPosition'],
                          [0]);
     wtu.drawQuad(gl);
     glErrorShouldBe(gl, gl.NO_ERROR, "rendering to floating-point texture should succeed");
--- a/content/canvas/test/webgl-conformance/failing_tests_android.txt
+++ b/content/canvas/test/webgl-conformance/failing_tests_android.txt
@@ -1,9 +1,8 @@
-conformance/extensions/oes-texture-float.html
 conformance/extensions/oes-vertex-array-object.html
 conformance/glsl/functions/glsl-function-abs.html
 conformance/glsl/functions/glsl-function-faceforward.html
 conformance/glsl/functions/glsl-function-sign.html
 conformance/glsl/functions/glsl-function-smoothstep-float.html
 conformance/glsl/functions/glsl-function-step-float.html
 conformance/glsl/functions/glsl-function-step-gentype.html
 conformance/limits/gl-max-texture-dimensions.html
--- a/content/canvas/test/webgl-conformance/failing_tests_android_x86.txt
+++ b/content/canvas/test/webgl-conformance/failing_tests_android_x86.txt
@@ -1,5 +1,4 @@
 # Failures for our android x86 and arm emulator test environments.
 
-conformance/extensions/oes-texture-float.html
 conformance/programs/get-active-test.html
 conformance/textures/texture-npot.html
--- a/content/canvas/test/webgl-conformance/failing_tests_linux_mesa.txt
+++ b/content/canvas/test/webgl-conformance/failing_tests_linux_mesa.txt
@@ -1,3 +1,2 @@
 conformance/textures/texture-size-cube-maps.html
-conformance/extensions/oes-texture-float.html
 conformance/glsl/functions/glsl-function-sin.html
--- a/content/canvas/test/webgl-conformance/skipped_tests_android_x86.txt
+++ b/content/canvas/test/webgl-conformance/skipped_tests_android_x86.txt
@@ -1,8 +1,15 @@
+# OES-texture-float is failing on Android 2.3, but not Android 4.0 when
+# there is a way to differentiate these two slaves this should be removed
+# and updated as appropriately. The Android 2.3 slave is returning red
+# when it should be green. This is believed to be a driver bug and not
+# FF bug at the moment.
+conformance/extensions/oes-texture-float.html
+
 conformance/extensions/oes-vertex-array-object.html
 conformance/glsl/functions/glsl-function-abs.html
 conformance/glsl/functions/glsl-function-faceforward.html
 conformance/glsl/functions/glsl-function-sign.html
 conformance/glsl/functions/glsl-function-sin.html
 conformance/glsl/functions/glsl-function-step-float.html
 conformance/glsl/functions/glsl-function-step-gentype.html
 conformance/glsl/functions/glsl-function-smoothstep-float.html
--- a/content/html/content/public/HTMLMediaElement.h
+++ b/content/html/content/public/HTMLMediaElement.h
@@ -13,19 +13,22 @@
 #include "nsIObserver.h"
 #include "mozilla/CORSMode.h"
 #include "DOMMediaStream.h"
 #include "AudioChannelCommon.h"
 #include "DecoderTraits.h"
 #include "nsIAudioChannelAgent.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/AudioChannelBinding.h"
+#include "mozilla/dom/Promise.h"
 #include "mozilla/dom/TextTrackManager.h"
 #include "MediaDecoder.h"
+#ifdef MOZ_EME
 #include "mozilla/dom/MediaKeys.h"
+#endif
 
 // Something on Linux #defines None, which is an entry in the
 // MediaWaitingFor enum, so undef it here before including the binfing,
 // so that the build doesn't fail...
 #ifdef None
 #undef None
 #endif
 
@@ -516,31 +519,33 @@ public:
 
   bool MozPreservesPitch() const
   {
     return mPreservesPitch;
   }
 
   // XPCOM MozPreservesPitch() is OK
 
+#ifdef MOZ_EME
   MediaKeys* GetMediaKeys() const;
 
   already_AddRefed<Promise> SetMediaKeys(MediaKeys* mediaKeys,
                                          ErrorResult& aRv);
   
   MediaWaitingFor WaitingFor() const;
 
   mozilla::dom::EventHandlerNonNull* GetOnneedkey();
   void SetOnneedkey(mozilla::dom::EventHandlerNonNull* listener);
 
   void DispatchNeedKey(const nsTArray<uint8_t>& aInitData,
                        const nsAString& aInitDataType);
 
 
   bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
+#endif // MOZ_EME
 
   bool MozAutoplayEnabled() const
   {
     return mAutoplayEnabled;
   }
 
   already_AddRefed<DOMMediaStream> MozCaptureStream(ErrorResult& aRv);
 
@@ -1071,18 +1076,20 @@ protected:
 
   // Reference to the source element last returned by GetNextSource().
   // This is the child source element which we're trying to load from.
   nsCOMPtr<nsIContent> mSourceLoadCandidate;
 
   // Range of time played.
   nsRefPtr<TimeRanges> mPlayed;
 
+#ifdef MOZ_EME
   // Encrypted Media Extension media keys.
   nsRefPtr<MediaKeys> mMediaKeys;
+#endif
 
   // Stores the time at the start of the current 'played' range.
   double mCurrentPlayRangeStart;
 
   // If true then we have begun downloading the media content.
   // Set to false when completed, or not yet started.
   bool mBegun;
 
--- a/content/html/content/src/HTMLFormControlsCollection.cpp
+++ b/content/html/content/src/HTMLFormControlsCollection.cpp
@@ -12,16 +12,17 @@
 #include "mozilla/dom/HTMLFormControlsCollectionBinding.h"
 #include "mozilla/dom/HTMLFormElement.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "nsGenericHTMLElement.h" // nsGenericHTMLFormElement
 #include "nsIDocument.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsIFormControl.h"
+#include "RadioNodeList.h"
 #include "jsfriendapi.h"
 
 namespace mozilla {
 namespace dom {
 
 /* static */ bool
 HTMLFormControlsCollection::ShouldBeInElements(nsIFormControl* aFormControl)
 {
@@ -342,51 +343,51 @@ HTMLFormControlsCollection::GetElementAt
 HTMLFormControlsCollection::GetParentObject()
 {
   return mForm;
 }
 
 /* virtual */ Element*
 HTMLFormControlsCollection::GetFirstNamedElement(const nsAString& aName, bool& aFound)
 {
-  Nullable<OwningNodeListOrElement> maybeResult;
+  Nullable<OwningRadioNodeListOrElement> maybeResult;
   NamedGetter(aName, aFound, maybeResult);
   if (!aFound) {
     return nullptr;
   }
   MOZ_ASSERT(!maybeResult.IsNull());
-  const OwningNodeListOrElement& result = maybeResult.Value();
+  const OwningRadioNodeListOrElement& result = maybeResult.Value();
   if (result.IsElement()) {
     return result.GetAsElement().get();
   }
-  if (result.IsNodeList()) {
-    nsINodeList& nodelist = result.GetAsNodeList();
+  if (result.IsRadioNodeList()) {
+    RadioNodeList& nodelist = result.GetAsRadioNodeList();
     return nodelist.Item(0)->AsElement();
   }
   MOZ_ASSERT_UNREACHABLE("Should only have Elements and NodeLists here.");
   return nullptr;
 }
 
 void
 HTMLFormControlsCollection::NamedGetter(const nsAString& aName,
                                         bool& aFound,
-                                        Nullable<OwningNodeListOrElement>& aResult)
+                                        Nullable<OwningRadioNodeListOrElement>& aResult)
 {
   nsISupports* item = NamedItemInternal(aName, true);
   if (!item) {
     aFound = false;
     return;
   }
   aFound = true;
   if (nsCOMPtr<Element> element = do_QueryInterface(item)) {
     aResult.SetValue().SetAsElement() = element;
     return;
   }
-  if (nsCOMPtr<nsINodeList> nodelist = do_QueryInterface(item)) {
-    aResult.SetValue().SetAsNodeList() = nodelist;
+  if (nsCOMPtr<RadioNodeList> nodelist = do_QueryInterface(item)) {
+    aResult.SetValue().SetAsRadioNodeList() = nodelist;
     return;
   }
   MOZ_ASSERT_UNREACHABLE("Should only have Elements and NodeLists here.");
 }
 
 static PLDHashOperator
 CollectNames(const nsAString& aName,
              nsISupports* /* unused */,
--- a/content/html/content/src/HTMLFormControlsCollection.h
+++ b/content/html/content/src/HTMLFormControlsCollection.h
@@ -15,17 +15,17 @@
 
 class nsGenericHTMLFormElement;
 class nsIFormControl;
 
 namespace mozilla {
 namespace dom {
 class HTMLFormElement;
 class HTMLImageElement;
-class OwningNodeListOrElement;
+class OwningRadioNodeListOrElement;
 template<typename> struct Nullable;
 
 class HTMLFormControlsCollection : public nsIHTMLCollection
                                  , public nsWrapperCache
 {
 public:
   HTMLFormControlsCollection(HTMLFormElement* aForm);
 
@@ -40,20 +40,20 @@ public:
   virtual nsINode* GetParentObject() MOZ_OVERRIDE;
 
   virtual Element*
   GetFirstNamedElement(const nsAString& aName, bool& aFound) MOZ_OVERRIDE;
 
   void
   NamedGetter(const nsAString& aName,
               bool& aFound,
-              Nullable<OwningNodeListOrElement>& aResult);
+              Nullable<OwningRadioNodeListOrElement>& aResult);
   void
   NamedItem(const nsAString& aName,
-            Nullable<OwningNodeListOrElement>& aResult)
+            Nullable<OwningRadioNodeListOrElement>& aResult)
   {
     bool dummy;
     NamedGetter(aName, dummy, aResult);
   }
   virtual void GetSupportedNames(unsigned aFlags,
                                  nsTArray<nsString>& aNames) MOZ_OVERRIDE;
 
   nsresult AddElementToTable(nsGenericHTMLFormElement* aChild,
--- a/content/html/content/src/HTMLFormElement.cpp
+++ b/content/html/content/src/HTMLFormElement.cpp
@@ -43,16 +43,17 @@
 #include "nsIWebProgress.h"
 #include "nsIDocShell.h"
 #include "nsFormData.h"
 #include "nsFormSubmissionConstants.h"
 
 // radio buttons
 #include "mozilla/dom/HTMLInputElement.h"
 #include "nsIRadioVisitor.h"
+#include "RadioNodeList.h"
 
 #include "nsLayoutUtils.h"
 
 #include "mozAutoDocUpdate.h"
 #include "nsIHTMLCollection.h"
 
 #include "nsIConstraintValidation.h"
 
@@ -2277,17 +2278,17 @@ HTMLFormElement::AddElementToTableIntern
       // happen if a form control has both a name and an id with the same
       // value
       if (content == aChild) {
         return NS_OK;
       }
 
       // Found an element, create a list, add the element to the list and put
       // the list in the hash
-      nsSimpleContentList *list = new nsSimpleContentList(this);
+      RadioNodeList *list = new RadioNodeList(this);
 
       // If an element has a @form, we can assume it *might* be able to not have
       // a parent and still be in the form.
       NS_ASSERTION(content->HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
                    content->GetParent(), "Item in list without parent");
 
       // Determine the ordering between the new and old element.
       bool newFirst = nsContentUtils::PositionIsBefore(aChild, content);
@@ -2301,18 +2302,18 @@ HTMLFormElement::AddElementToTableIntern
       // Replace the element with the list.
       aTable.Put(aName, listSupports);
     } else {
       // There's already a list in the hash, add the child to the list
       nsCOMPtr<nsIDOMNodeList> nodeList = do_QueryInterface(supports);
       NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE);
 
       // Upcast, uggly, but it works!
-      nsSimpleContentList *list =
-        static_cast<nsSimpleContentList*>(nodeList.get());
+      RadioNodeList *list =
+        static_cast<RadioNodeList*>(nodeList.get());
 
       NS_ASSERTION(list->Length() > 1,
                    "List should have been converted back to a single element");
 
       // Fast-path appends; this check is ok even if the child is
       // already in the list, since if it tests true the child would
       // have come at the end of the list, and the PositionIsBefore
       // will test false.
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -5,18 +5,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/HTMLMediaElementBinding.h"
 #include "mozilla/dom/HTMLSourceElement.h"
 #include "mozilla/dom/ElementInlines.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/MathAlgorithms.h"
+#include "mozilla/AsyncEventDispatcher.h"
+#ifdef MOZ_EME
 #include "mozilla/dom/MediaKeyNeededEvent.h"
-#include "mozilla/AsyncEventDispatcher.h"
+#endif
 
 #include "base/basictypes.h"
 #include "nsIDOMHTMLMediaElement.h"
 #include "nsIDOMHTMLSourceElement.h"
 #include "TimeRanges.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValueInlines.h"
 #include "nsPresContext.h"
@@ -425,17 +427,19 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
   for (uint32_t i = 0; i < tmp->mOutputStreams.Length(); ++i) {
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputStreams[i].mStream);
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlayed);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextTrackManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioTrackList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVideoTrackList)
+#ifdef MOZ_EME
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeys)
+#endif
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
   if (tmp->mSrcStream) {
     // Need to EndMediaStreamPlayback to clear mSrcStream and make sure everything
     // gets unhooked correctly.
     tmp->EndSrcMediaStreamPlayback();
   }
@@ -448,17 +452,19 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mError)
   for (uint32_t i = 0; i < tmp->mOutputStreams.Length(); ++i) {
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputStreams[i].mStream)
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlayed)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextTrackManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioTrackList)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mVideoTrackList)
+#ifdef MOZ_EME
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaKeys)
+#endif
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLMediaElement)
   NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLMediaElement)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
   NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgentCallback)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
 
@@ -3938,16 +3944,17 @@ NS_IMETHODIMP HTMLMediaElement::CanPlayC
 
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
 
   UpdateChannelMuteState(static_cast<AudioChannelState>(canPlay));
   mPaused.SetCanPlay(canPlay != AUDIO_CHANNEL_STATE_MUTED);
   return NS_OK;
 }
 
+#ifdef MOZ_EME
 MediaKeys*
 HTMLMediaElement::GetMediaKeys() const
 {
   return mMediaKeys;
 }
 
 already_AddRefed<Promise>
 HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys,
@@ -4003,16 +4010,17 @@ HTMLMediaElement::DispatchNeedKey(const 
 }
 
 bool
 HTMLMediaElement::IsEventAttributeName(nsIAtom* aName)
 {
   return aName == nsGkAtoms::onneedkey ||
          nsGenericHTMLElement::IsEventAttributeName(aName);
 }
+#endif // MOZ_EME
 
 NS_IMETHODIMP HTMLMediaElement::WindowVolumeChanged()
 {
   SetVolumeInternal();
   return NS_OK;
 }
 
 AudioTrackList*
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/RadioNodeList.cpp
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/RadioNodeList.h"
+
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/RadioNodeListBinding.h"
+#include "js/TypeDecls.h"
+
+#include "HTMLInputElement.h"
+
+namespace mozilla {
+namespace dom {
+
+/* virtual */ JSObject*
+RadioNodeList::WrapObject(JSContext* aCx)
+{
+  return RadioNodeListBinding::Wrap(aCx, this);
+}
+
+HTMLInputElement*
+GetAsRadio(nsIContent* node)
+{
+  HTMLInputElement* el = HTMLInputElement::FromContent(node);
+  if (el && el->GetType() == NS_FORM_INPUT_RADIO) {
+    return el;
+  }
+  return nullptr;
+}
+
+void
+RadioNodeList::GetValue(nsString& retval)
+{
+  for (uint32_t i = 0; i < Length(); i++) {
+    HTMLInputElement* maybeRadio = GetAsRadio(Item(i));
+    if (maybeRadio && maybeRadio->Checked()) {
+      maybeRadio->GetValue(retval);
+      return;
+    }
+  }
+  retval.Truncate();
+}
+
+void
+RadioNodeList::SetValue(const nsAString& value)
+{
+  for (uint32_t i = 0; i < Length(); i++) {
+
+    HTMLInputElement* maybeRadio = GetAsRadio(Item(i));
+    if (!maybeRadio) {
+      continue;
+    }
+
+    nsString curval = nsString();
+    maybeRadio->GetValue(curval);
+    if (curval.Equals(value)) {
+      maybeRadio->SetChecked(true);
+      return;
+    }
+
+  }
+}
+
+NS_IMPL_ISUPPORTS_INHERITED(RadioNodeList, nsSimpleContentList, RadioNodeList)
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/RadioNodeList.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_RadioNodeList_h
+#define mozilla_dom_RadioNodeList_h
+
+#include "nsContentList.h"
+#include "nsCOMPtr.h"
+#include "HTMLFormElement.h"
+
+#define MOZILLA_DOM_RADIONODELIST_IMPLEMENTATION_IID \
+  { 0xbba7f3e8, 0xf3b5, 0x42e5, \
+  { 0x82, 0x08, 0xa6, 0x8b, 0xe0, 0xbc, 0x22, 0x19 } }
+
+namespace mozilla {
+namespace dom {
+
+class RadioNodeList : public nsSimpleContentList
+{
+public:
+  RadioNodeList(HTMLFormElement* aForm) : nsSimpleContentList(aForm) { }
+
+  virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
+  void GetValue(nsString& retval);
+  void SetValue(const nsAString& value);
+
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOM_RADIONODELIST_IMPLEMENTATION_IID)
+private:
+  ~RadioNodeList() { }
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(RadioNodeList, MOZILLA_DOM_RADIONODELIST_IMPLEMENTATION_IID)
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_RadioNodeList_h
--- a/content/html/content/src/moz.build
+++ b/content/html/content/src/moz.build
@@ -67,16 +67,17 @@ EXPORTS.mozilla.dom += [
     'HTMLTableSectionElement.h',
     'HTMLTemplateElement.h',
     'HTMLTextAreaElement.h',
     'HTMLTimeElement.h',
     'HTMLTitleElement.h',
     'HTMLTrackElement.h',
     'HTMLUnknownElement.h',
     'MediaError.h',
+    'RadioNodeList.h',
     'TextTrackManager.h',
     'TimeRanges.h',
     'UndoManager.h',
     'ValidityState.h',
 ]
 
 UNIFIED_SOURCES += [
     'HTMLAnchorElement.cpp',
@@ -149,16 +150,17 @@ UNIFIED_SOURCES += [
     'nsDOMStringMap.cpp',
     'nsFormSubmission.cpp',
     'nsGenericHTMLElement.cpp',
     'nsGenericHTMLFrameElement.cpp',
     'nsHTMLDNSPrefetch.cpp',
     'nsIConstraintValidation.cpp',
     'nsRadioVisitor.cpp',
     'nsTextEditorState.cpp',
+    'RadioNodeList.cpp',
     'TextTrackManager.cpp',
     'TimeRanges.cpp',
     'UndoManager.cpp',
     'ValidityState.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
--- a/content/html/content/test/forms/mochitest.ini
+++ b/content/html/content/test/forms/mochitest.ini
@@ -67,16 +67,17 @@ skip-if = e10s
 [test_mozistextfield.html]
 [test_novalidate_attribute.html]
 [test_option_disabled.html]
 [test_option_index_attribute.html]
 [test_option_text.html]
 [test_output_element.html]
 [test_pattern_attribute.html]
 [test_progress_element.html]
+[test_radio_radionodelist.html]
 [test_required_attribute.html]
 skip-if = e10s
 [test_restore_form_elements.html]
 [test_save_restore_radio_groups.html]
 [test_select_selectedOptions.html]
 [test_select_validation.html]
 [test_set_range_text.html]
 [test_step_attribute.html]
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/forms/test_radio_radionodelist.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=779723
+-->
+<head>
+  <title>Test for Bug 779723</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=779723">Mozilla Bug 779723</a>
+<p id="display"></p>
+<form>
+  <input type="checkbox" name="rdo" value="0" id="r0" checked="checked">
+  <input type="radio" name="rdo" id="r1">
+  <input type="radio" name="rdo" id="r2" value="2">
+</form>
+<script class="testbody" type="text/javascript">
+/** Test for Bug 779723 **/
+
+var rdoList = document.forms[0].elements.namedItem('rdo');
+ise(rdoList.value, "", "The value attribute should be empty");
+
+document.getElementById('r2').checked = true;
+ok(rdoList.value, "2", "The value attribute should be 2");
+
+document.getElementById('r1').checked = true;
+ok(rdoList.value, "on", "The value attribute should be on");
+
+document.getElementById('r1').value = 1;
+ok(rdoList.value, "1", "The value attribute should be 1");
+
+ise(rdoList.value, document.getElementById('r1').value,
+   "The value attribute should be equal to the first checked radio input element's value");
+ok(!document.getElementById('r2').checked,
+   "The second radio input element should not be checked");
+
+rdoList.value = '2';
+ise(rdoList.value, document.getElementById('r2').value,
+   "The value attribute should be equal to the second radio input element's value");
+ok(document.getElementById('r2').checked,
+   "The second radio input element should be checked");
+
+rdoList.value = '3';
+ise(rdoList.value, document.getElementById('r2').value,
+   "The value attribute should be the second radio input element's value");
+ok(document.getElementById('r2').checked,
+   "The second radio input element should be checked");
+
+</script>
+</pre>
+</body>
+</html>
+
--- a/content/html/document/src/moz.build
+++ b/content/html/document/src/moz.build
@@ -28,16 +28,16 @@ SOURCES += [
 ]
 
 FAIL_ON_WARNINGS = True
 
 MSVC_ENABLE_PGO = True
 
 LOCAL_INCLUDES += [
     '../../content/src',
-    '/caps/include',
+    '/caps',
     '/content/base/src',
     '/docshell/base',
     '/dom/base',
     '/layout/style',
 ]
 
 FINAL_LIBRARY = 'gklayout'
--- a/content/media/DecoderTraits.cpp
+++ b/content/media/DecoderTraits.cpp
@@ -4,18 +4,18 @@
  * 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 "DecoderTraits.h"
 #include "MediaDecoder.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "mozilla/Preferences.h"
 
-#ifdef MOZ_MEDIA_PLUGINS
-#include "MediaPluginHost.h"
+#ifdef MOZ_ANDROID_OMX
+#include "AndroidMediaPluginHost.h"
 #endif
 
 #include "OggDecoder.h"
 #include "OggReader.h"
 #ifdef MOZ_WAVE
 #include "WaveDecoder.h"
 #include "WaveReader.h"
 #endif
@@ -26,21 +26,21 @@
 #ifdef MOZ_RAW
 #include "RawDecoder.h"
 #include "RawReader.h"
 #endif
 #ifdef MOZ_GSTREAMER
 #include "GStreamerDecoder.h"
 #include "GStreamerReader.h"
 #endif
-#ifdef MOZ_MEDIA_PLUGINS
-#include "MediaPluginHost.h"
-#include "MediaPluginDecoder.h"
-#include "MediaPluginReader.h"
-#include "MediaPluginHost.h"
+#ifdef MOZ_ANDROID_OMX
+#include "AndroidMediaPluginHost.h"
+#include "AndroidMediaDecoder.h"
+#include "AndroidMediaReader.h"
+#include "AndroidMediaPluginHost.h"
 #endif
 #ifdef MOZ_OMX_DECODER
 #include "MediaOmxDecoder.h"
 #include "MediaOmxReader.h"
 #include "nsIPrincipal.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #endif
 #ifdef NECKO_PROTOCOL_rtsp
@@ -278,21 +278,21 @@ IsRtspSupportedType(const nsACString& aM
 bool DecoderTraits::DecoderWaitsForOnConnected(const nsACString& aMimeType) {
 #ifdef NECKO_PROTOCOL_rtsp
   return CodecListContains(gRtspTypes, aMimeType);
 #else
   return false;
 #endif
 }
 
-#ifdef MOZ_MEDIA_PLUGINS
+#ifdef MOZ_ANDROID_OMX
 static bool
-IsMediaPluginsType(const nsACString& aType)
+IsAndroidMediaType(const nsACString& aType)
 {
-  if (!MediaDecoder::IsMediaPluginsEnabled()) {
+  if (!MediaDecoder::IsAndroidMediaEnabled()) {
     return false;
   }
 
   static const char* supportedTypes[] = {
     "audio/mpeg", "audio/mp4", "video/mp4", nullptr
   };
   return CodecListContains(supportedTypes, aType);
 }
@@ -446,19 +446,19 @@ DecoderTraits::CanHandleMediaType(const 
            ? CANPLAY_YES : CANPLAY_NO;
   }
 #endif
 #ifdef MOZ_APPLEMEDIA
   if (IsAppleMediaSupportedType(nsDependentCString(aMIMEType), &codecList)) {
     result = CANPLAY_MAYBE;
   }
 #endif
-#ifdef MOZ_MEDIA_PLUGINS
-  if (MediaDecoder::IsMediaPluginsEnabled() &&
-      GetMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), &codecList))
+#ifdef MOZ_ANDROID_OMX
+  if (MediaDecoder::IsAndroidMediaEnabled() &&
+      GetAndroidMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), &codecList))
     result = CANPLAY_MAYBE;
 #endif
 #ifdef NECKO_PROTOCOL_rtsp
   if (IsRtspSupportedType(nsDependentCString(aMIMEType))) {
     result = CANPLAY_MAYBE;
   }
 #endif
   if (result == CANPLAY_NO || !aHaveRequestedCodecs || !codecList) {
@@ -542,20 +542,20 @@ InstantiateDecoder(const nsACString& aTy
   }
 #endif
 #ifdef NECKO_PROTOCOL_rtsp
   if (IsRtspSupportedType(aType)) {
     decoder = new RtspOmxDecoder();
     return decoder.forget();
   }
 #endif
-#ifdef MOZ_MEDIA_PLUGINS
-  if (MediaDecoder::IsMediaPluginsEnabled() &&
-      GetMediaPluginHost()->FindDecoder(aType, nullptr)) {
-    decoder = new MediaPluginDecoder(aType);
+#ifdef MOZ_ANDROID_OMX
+  if (MediaDecoder::IsAndroidMediaEnabled() &&
+      GetAndroidMediaPluginHost()->FindDecoder(aType, nullptr)) {
+    decoder = new AndroidMediaDecoder(aType);
     return decoder.forget();
   }
 #endif
 #ifdef MOZ_WEBM
   if (IsWebMType(aType)) {
     decoder = new WebMDecoder();
     return decoder.forget();
   }
@@ -625,20 +625,20 @@ MediaDecoderReader* DecoderTraits::Creat
     decoderReader = new WaveReader(aDecoder);
   } else
 #endif
 #ifdef MOZ_OMX_DECODER
   if (IsOmxSupportedType(aType)) {
     decoderReader = new MediaOmxReader(aDecoder);
   } else
 #endif
-#ifdef MOZ_MEDIA_PLUGINS
-  if (MediaDecoder::IsMediaPluginsEnabled() &&
-      GetMediaPluginHost()->FindDecoder(aType, nullptr)) {
-    decoderReader = new MediaPluginReader(aDecoder, aType);
+#ifdef MOZ_ANDROID_OMX
+  if (MediaDecoder::IsAndroidMediaEnabled() &&
+      GetAndroidMediaPluginHost()->FindDecoder(aType, nullptr)) {
+    decoderReader = new AndroidMediaReader(aDecoder, aType);
   } else
 #endif
 #ifdef MOZ_WEBM
   if (IsWebMType(aType)) {
     decoderReader = new WebMReader(aDecoder);
   } else
 #endif
 #ifdef MOZ_DIRECTSHOW
@@ -674,18 +674,18 @@ bool DecoderTraits::IsSupportedInVideoDo
     (IsOmxSupportedType(aType) && !aType.EqualsASCII("audio/amr")) ||
 #endif
 #ifdef MOZ_WEBM
     IsWebMType(aType) ||
 #endif
 #ifdef MOZ_GSTREAMER
     IsGStreamerSupportedType(aType) ||
 #endif
-#ifdef MOZ_MEDIA_PLUGINS
-    (MediaDecoder::IsMediaPluginsEnabled() && IsMediaPluginsType(aType)) ||
+#ifdef MOZ_ANDROID_OMX
+    (MediaDecoder::IsAndroidMediaEnabled() && IsAndroidMediaType(aType)) ||
 #endif
 #ifdef MOZ_FMP4
     IsMP4SupportedType(aType) ||
 #endif
 #ifdef MOZ_WMF
     (IsWMFSupportedType(aType) &&
      Preferences::GetBool("media.windows-media-foundation.play-stand-alone", true)) ||
 #endif
--- a/content/media/MediaDecoder.cpp
+++ b/content/media/MediaDecoder.cpp
@@ -1714,19 +1714,19 @@ MediaDecoder::IsGStreamerEnabled()
 #ifdef MOZ_OMX_DECODER
 bool
 MediaDecoder::IsOmxEnabled()
 {
   return Preferences::GetBool("media.omx.enabled", false);
 }
 #endif
 
-#ifdef MOZ_MEDIA_PLUGINS
+#ifdef MOZ_ANDROID_OMX
 bool
-MediaDecoder::IsMediaPluginsEnabled()
+MediaDecoder::IsAndroidMediaEnabled()
 {
   return Preferences::GetBool("media.plugins.enabled");
 }
 #endif
 
 #ifdef MOZ_WMF
 bool
 MediaDecoder::IsWMFEnabled()
--- a/content/media/MediaDecoder.h
+++ b/content/media/MediaDecoder.h
@@ -870,18 +870,18 @@ public:
 #ifdef MOZ_GSTREAMER
   static bool IsGStreamerEnabled();
 #endif
 
 #ifdef MOZ_OMX_DECODER
   static bool IsOmxEnabled();
 #endif
 
-#ifdef MOZ_MEDIA_PLUGINS
-  static bool IsMediaPluginsEnabled();
+#ifdef MOZ_ANDROID_OMX
+  static bool IsAndroidMediaEnabled();
 #endif
 
 #ifdef MOZ_WMF
   static bool IsWMFEnabled();
 #endif
 
 #ifdef MOZ_APPLEMEDIA
   static bool IsAppleMP3Enabled();
--- a/content/media/SharedThreadPool.h
+++ b/content/media/SharedThreadPool.h
@@ -44,21 +44,17 @@ public:
   // are implemented using locking, so it's not recommended that you use them
   // in a tight loop.
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
   NS_IMETHOD_(MozExternalRefCountType) AddRef(void);
   NS_IMETHOD_(MozExternalRefCountType) Release(void);
 
   // Forward behaviour to wrapped thread pool implementation.
   NS_FORWARD_SAFE_NSITHREADPOOL(mPool);
-  NS_FORWARD_SAFE_NSIEVENTTARGET(GetEventTarget());
-
-  nsIEventTarget* GetEventTarget() {
-    return mEventTarget;
-  }
+  NS_FORWARD_SAFE_NSIEVENTTARGET(mEventTarget);
 
 private:
 
   // Creates necessary statics.
   // Main thread only.
   static void EnsureInitialized();
 
   // Creates a singleton SharedThreadPool wrapper around aPool.
rename from content/media/plugins/MediaPluginDecoder.cpp
rename to content/media/android/AndroidMediaDecoder.cpp
--- a/content/media/plugins/MediaPluginDecoder.cpp
+++ b/content/media/android/AndroidMediaDecoder.cpp
@@ -1,23 +1,23 @@
 /* -*- 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 "MediaDecoderStateMachine.h"
-#include "MediaPluginDecoder.h"
-#include "MediaPluginReader.h"
+#include "AndroidMediaDecoder.h"
+#include "AndroidMediaReader.h"
 
 namespace mozilla {
 
-MediaPluginDecoder::MediaPluginDecoder(const nsACString& aType) : mType(aType)
+AndroidMediaDecoder::AndroidMediaDecoder(const nsACString& aType) : mType(aType)
 {
 }
 
-MediaDecoderStateMachine* MediaPluginDecoder::CreateStateMachine()
+MediaDecoderStateMachine* AndroidMediaDecoder::CreateStateMachine()
 {
-  return new MediaDecoderStateMachine(this, new MediaPluginReader(this, mType));
+  return new MediaDecoderStateMachine(this, new AndroidMediaReader(this, mType));
 }
 
 } // namespace mozilla
 
rename from content/media/plugins/MediaPluginDecoder.h
rename to content/media/android/AndroidMediaDecoder.h
--- a/content/media/plugins/MediaPluginDecoder.h
+++ b/content/media/android/AndroidMediaDecoder.h
@@ -1,31 +1,31 @@
 /* -*- 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/. */
-#if !defined(MediaPluginDecoder_h_)
-#define MediaPluginDecoder_h_
+#if !defined(AndroidMediaDecoder_h_)
+#define AndroidMediaDecoder_h_
 
 #include "MediaDecoder.h"
-#include "MediaPluginDecoder.h"
+#include "AndroidMediaDecoder.h"
 
 namespace mozilla {
 
-class MediaPluginDecoder : public MediaDecoder
+class AndroidMediaDecoder : public MediaDecoder
 {
   nsCString mType;
 public:
-  MediaPluginDecoder(const nsACString& aType);
+  AndroidMediaDecoder(const nsACString& aType);
 
   const nsresult GetContentType(nsACString& aType) const {
     aType = mType;
     return NS_OK;
   }
 
-  virtual MediaDecoder* Clone() { return new MediaPluginDecoder(mType); }
+  virtual MediaDecoder* Clone() { return new AndroidMediaDecoder(mType); }
   virtual MediaDecoderStateMachine* CreateStateMachine();
 };
 
 } // namespace mozilla
 
 #endif
rename from content/media/plugins/MediaPluginHost.cpp
rename to content/media/android/AndroidMediaPluginHost.cpp
--- a/content/media/plugins/MediaPluginHost.cpp
+++ b/content/media/android/AndroidMediaPluginHost.cpp
@@ -2,34 +2,34 @@
 /* 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 "mozilla/Preferences.h"
 #include "mozilla/dom/TimeRanges.h"
 #include "MediaResource.h"
 #include "mozilla/dom/HTMLMediaElement.h"
-#include "MediaPluginHost.h"
+#include "AndroidMediaPluginHost.h"
 #include "nsXPCOMStrings.h"
 #include "nsISeekableStream.h"
-#include "MediaPluginReader.h"
+#include "AndroidMediaReader.h"
 #include "nsIGfxInfo.h"
 #include "gfxCrashReporterUtils.h"
 #include "prmem.h"
 #include "prlink.h"
-#include "MediaResourceServer.h"
+#include "AndroidMediaResourceServer.h"
 #include "nsServiceManagerUtils.h"
 
 #include "MPAPI.h"
 
 #include "nsIPropertyBag2.h"
 
 #if defined(ANDROID) || defined(MOZ_WIDGET_GONK)
 #include "android/log.h"
-#define ALOG(args...)  __android_log_print(ANDROID_LOG_INFO, "MediaPluginHost" , ## args)
+#define ALOG(args...)  __android_log_print(ANDROID_LOG_INFO, "AndroidMediaPluginHost" , ## args)
 #else
 #define ALOG(args...) /* do nothing */
 #endif
 
 using namespace MPAPI;
 
 Decoder::Decoder() :
   mResource(nullptr), mPrivate(nullptr)
@@ -208,20 +208,20 @@ static const char* GetOmxLibraryName()
 
 #elif defined(ANDROID) && defined(MOZ_WIDGET_GONK)
   return "libomxplugin.so";
 #else
   return nullptr;
 #endif
 }
 
-MediaPluginHost::MediaPluginHost() {
-  MOZ_COUNT_CTOR(MediaPluginHost);
+AndroidMediaPluginHost::AndroidMediaPluginHost() {
+  MOZ_COUNT_CTOR(AndroidMediaPluginHost);
 
-  mResourceServer = MediaResourceServer::Start();
+  mResourceServer = AndroidMediaResourceServer::Start();
 
   const char* name = GetOmxLibraryName();
   ALOG("Loading OMX Plugin: %s", name ? name : "nullptr");
   if (name) {
     char *path = PR_GetLibraryFilePathname("libxul.so", (PRFuncPtr) GetOmxLibraryName);
     PRLibrary *lib = nullptr;
     if (path) {
       nsAutoCString libpath(path);
@@ -241,38 +241,38 @@ MediaPluginHost::MediaPluginHost() {
       if (manifest) {
         mPlugins.AppendElement(manifest);
         ALOG("OMX plugin successfully loaded");
      }
     }
   }
 }
 
-MediaPluginHost::~MediaPluginHost() {
+AndroidMediaPluginHost::~AndroidMediaPluginHost() {
   mResourceServer->Stop();
-  MOZ_COUNT_DTOR(MediaPluginHost);
+  MOZ_COUNT_DTOR(AndroidMediaPluginHost);
 }
 
-bool MediaPluginHost::FindDecoder(const nsACString& aMimeType, const char* const** aCodecs)
+bool AndroidMediaPluginHost::FindDecoder(const nsACString& aMimeType, const char* const** aCodecs)
 {
   const char *chars;
   size_t len = NS_CStringGetData(aMimeType, &chars, nullptr);
   for (size_t n = 0; n < mPlugins.Length(); ++n) {
     Manifest *plugin = mPlugins[n];
     const char* const *codecs;
     if (plugin->CanDecode(chars, len, &codecs)) {
       if (aCodecs)
         *aCodecs = codecs;
       return true;
     }
   }
   return false;
 }
 
-MPAPI::Decoder *MediaPluginHost::CreateDecoder(MediaResource *aResource, const nsACString& aMimeType)
+MPAPI::Decoder *AndroidMediaPluginHost::CreateDecoder(MediaResource *aResource, const nsACString& aMimeType)
 {
   NS_ENSURE_TRUE(aResource, nullptr);
 
   nsAutoPtr<Decoder> decoder(new Decoder());
   if (!decoder) {
     return nullptr;
   }
 
@@ -294,37 +294,37 @@ MPAPI::Decoder *MediaPluginHost::CreateD
       aResource->AddRef();
       return decoder.forget();
     }
   }
 
   return nullptr;
 }
 
-void MediaPluginHost::DestroyDecoder(Decoder *aDecoder)
+void AndroidMediaPluginHost::DestroyDecoder(Decoder *aDecoder)
 {
   aDecoder->DestroyDecoder(aDecoder);
   char* resource = GetResource(aDecoder);
   if (resource) {
     // resource *shouldn't* be null, but check anyway just in case the plugin
     // decoder does something stupid.
     mResourceServer->RemoveResource(nsCString(resource));
     free(resource);
   }
   delete aDecoder;
 }
 
-MediaPluginHost *sMediaPluginHost = nullptr;
-MediaPluginHost *GetMediaPluginHost()
+AndroidMediaPluginHost *sAndroidMediaPluginHost = nullptr;
+AndroidMediaPluginHost *GetAndroidMediaPluginHost()
 {
-  if (!sMediaPluginHost) {
-    sMediaPluginHost = new MediaPluginHost();
+  if (!sAndroidMediaPluginHost) {
+    sAndroidMediaPluginHost = new AndroidMediaPluginHost();
   }
-  return sMediaPluginHost;
+  return sAndroidMediaPluginHost;
 }
 
-void MediaPluginHost::Shutdown()
+void AndroidMediaPluginHost::Shutdown()
 {
-  delete sMediaPluginHost;
-  sMediaPluginHost = nullptr;
+  delete sAndroidMediaPluginHost;
+  sAndroidMediaPluginHost = nullptr;
 }
 
 } // namespace mozilla
rename from content/media/plugins/MediaPluginHost.h
rename to content/media/android/AndroidMediaPluginHost.h
--- a/content/media/plugins/MediaPluginHost.h
+++ b/content/media/android/AndroidMediaPluginHost.h
@@ -1,38 +1,38 @@
 /* -*- 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/. */
-#if !defined(MediaPluginHost_h_)
-#define MediaPluginHost_h_
+#if !defined(AndroidMediaPluginHost_h_)
+#define AndroidMediaPluginHost_h_
 
 #include "nsTArray.h"
 #include "MediaResource.h"
 #include "MPAPI.h"
-#include "MediaResourceServer.h"
+#include "AndroidMediaResourceServer.h"
 
 namespace mozilla {
 
-class MediaPluginReader;
+class AndroidMediaReader;
 
-class MediaPluginHost {
-  nsRefPtr<MediaResourceServer> mResourceServer;
+class AndroidMediaPluginHost {
+  nsRefPtr<AndroidMediaResourceServer> mResourceServer;
   nsTArray<MPAPI::Manifest *> mPlugins;
 
   MPAPI::Manifest *FindPlugin(const nsACString& aMimeType);
 public:
-  MediaPluginHost();
-  ~MediaPluginHost();
+  AndroidMediaPluginHost();
+  ~AndroidMediaPluginHost();
 
   static void Shutdown();
 
   bool FindDecoder(const nsACString& aMimeType, const char* const** aCodecs);
   MPAPI::Decoder *CreateDecoder(mozilla::MediaResource *aResource, const nsACString& aMimeType);
   void DestroyDecoder(MPAPI::Decoder *aDecoder);
 };
 
-MediaPluginHost *GetMediaPluginHost();
+AndroidMediaPluginHost *GetAndroidMediaPluginHost();
 
 } // namespace mozilla
 
 #endif
rename from content/media/plugins/MediaPluginReader.cpp
rename to content/media/android/AndroidMediaReader.cpp
--- a/content/media/plugins/MediaPluginReader.cpp
+++ b/content/media/android/AndroidMediaReader.cpp
@@ -1,57 +1,57 @@
 /* -*- 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 "MediaPluginReader.h"
+#include "AndroidMediaReader.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/dom/TimeRanges.h"
 #include "mozilla/gfx/Point.h"
 #include "MediaResource.h"
 #include "VideoUtils.h"
-#include "MediaPluginDecoder.h"
-#include "MediaPluginHost.h"
+#include "AndroidMediaDecoder.h"
+#include "AndroidMediaPluginHost.h"
 #include "MediaDecoderStateMachine.h"
 #include "ImageContainer.h"
 #include "AbstractMediaDecoder.h"
 #include "gfx2DGlue.h"
 
 namespace mozilla {
 
 using namespace mozilla::gfx;
 
 typedef mozilla::layers::Image Image;
 typedef mozilla::layers::PlanarYCbCrImage PlanarYCbCrImage;
 
-MediaPluginReader::MediaPluginReader(AbstractMediaDecoder *aDecoder,
-                                     const nsACString& aContentType) :
+AndroidMediaReader::AndroidMediaReader(AbstractMediaDecoder *aDecoder,
+                                       const nsACString& aContentType) :
   MediaDecoderReader(aDecoder),
   mType(aContentType),
   mPlugin(nullptr),
   mHasAudio(false),
   mHasVideo(false),
   mVideoSeekTimeUs(-1),
   mAudioSeekTimeUs(-1)
 {
 }
 
-nsresult MediaPluginReader::Init(MediaDecoderReader* aCloneDonor)
+nsresult AndroidMediaReader::Init(MediaDecoderReader* aCloneDonor)
 {
   return NS_OK;
 }
 
-nsresult MediaPluginReader::ReadMetadata(MediaInfo* aInfo,
-                                         MetadataTags** aTags)
+nsresult AndroidMediaReader::ReadMetadata(MediaInfo* aInfo,
+                                          MetadataTags** aTags)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
 
   if (!mPlugin) {
-    mPlugin = GetMediaPluginHost()->CreateDecoder(mDecoder->GetResource(), mType);
+    mPlugin = GetAndroidMediaPluginHost()->CreateDecoder(mDecoder->GetResource(), mType);
     if (!mPlugin) {
       return NS_ERROR_FAILURE;
     }
   }
 
   // Set the total duration (the max of the audio and video track).
   int64_t durationUs;
   mPlugin->GetDuration(mPlugin, &durationUs);
@@ -94,36 +94,36 @@ nsresult MediaPluginReader::ReadMetadata
     mInfo.mAudio.mRate = sampleRate;
   }
 
  *aInfo = mInfo;
  *aTags = nullptr;
   return NS_OK;
 }
 
-void MediaPluginReader::Shutdown()
+void AndroidMediaReader::Shutdown()
 {
   ResetDecode();
   if (mPlugin) {
-    GetMediaPluginHost()->DestroyDecoder(mPlugin);
+    GetAndroidMediaPluginHost()->DestroyDecoder(mPlugin);
     mPlugin = nullptr;
   }
 }
 
 // Resets all state related to decoding, emptying all buffers etc.
-nsresult MediaPluginReader::ResetDecode()
+nsresult AndroidMediaReader::ResetDecode()
 {
   if (mLastVideoFrame) {
     mLastVideoFrame = nullptr;
   }
   return MediaDecoderReader::ResetDecode();
 }
 
-bool MediaPluginReader::DecodeVideoFrame(bool &aKeyframeSkip,
-                                         int64_t aTimeThreshold)
+bool AndroidMediaReader::DecodeVideoFrame(bool &aKeyframeSkip,
+                                          int64_t aTimeThreshold)
 {
   // Record number of frames decoded and parsed. Automatically update the
   // stats counters using the AutoNotifyDecoded stack-based class.
   uint32_t parsed = 0, decoded = 0;
   AbstractMediaDecoder::AutoNotifyDecoded autoNotify(mDecoder, parsed, decoded);
 
   // Throw away the currently buffered frame if we are seeking.
   if (mLastVideoFrame && mVideoSeekTimeUs != -1) {
@@ -243,20 +243,20 @@ bool MediaPluginReader::DecodeVideoFrame
                             picture);
     }
  
     if (!v) {
       return false;
     }
     parsed++;
     decoded++;
-    NS_ASSERTION(decoded <= parsed, "Expect to decode fewer frames than parsed in MediaPlugin...");
+    NS_ASSERTION(decoded <= parsed, "Expect to decode fewer frames than parsed in AndroidMedia...");
 
     // Since MPAPI doesn't give us the end time of frames, we keep one frame
-    // buffered in MediaPluginReader and push it into the queue as soon
+    // buffered in AndroidMediaReader and push it into the queue as soon
     // we read the following frame so we can use that frame's start time as
     // the end time of the buffered frame.
     if (!mLastVideoFrame) {
       mLastVideoFrame = v;
       continue;
     }
 
     // Calculate the duration as the timestamp of the current frame minus the
@@ -279,17 +279,17 @@ bool MediaPluginReader::DecodeVideoFrame
     mLastVideoFrame = v;
 
     break;
   }
 
   return true;
 }
 
-bool MediaPluginReader::DecodeAudioData()
+bool AndroidMediaReader::DecodeAudioData()
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
 
   // This is the approximate byte position in the stream.
   int64_t pos = mDecoder->GetResource()->Tell();
 
   // Read next frame
   MPAPI::AudioFrame source;
@@ -311,17 +311,17 @@ bool MediaPluginReader::DecodeAudioData(
                               source.mAudioSampleRate,
                               frames,
                               source.mAudioChannels,
                               MPCopy(static_cast<uint8_t *>(source.mData),
                                      source.mSize,
                                      source.mAudioChannels));
 }
 
-nsresult MediaPluginReader::Seek(int64_t aTarget, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime)
+nsresult AndroidMediaReader::Seek(int64_t aTarget, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
 
   if (mHasAudio && mHasVideo) {
     // The decoder seeks/demuxes audio and video streams separately. So if
     // we seek both audio and video to aTarget, the audio stream can typically
     // seek closer to the seek target, since typically every audio block is
     // a sync point, whereas for video there are only keyframes once every few
@@ -334,24 +334,24 @@ nsresult MediaPluginReader::Seek(int64_t
     mAudioSeekTimeUs = v ? v->mTime : aTarget;
   } else {
     mAudioSeekTimeUs = mVideoSeekTimeUs = aTarget;
   }
 
   return NS_OK;
 }
 
-MediaPluginReader::ImageBufferCallback::ImageBufferCallback(mozilla::layers::ImageContainer *aImageContainer) :
+AndroidMediaReader::ImageBufferCallback::ImageBufferCallback(mozilla::layers::ImageContainer *aImageContainer) :
   mImageContainer(aImageContainer)
 {
 }
 
 void *
-MediaPluginReader::ImageBufferCallback::operator()(size_t aWidth, size_t aHeight,
-                                                   MPAPI::ColorFormat aColorFormat)
+AndroidMediaReader::ImageBufferCallback::operator()(size_t aWidth, size_t aHeight,
+                                                    MPAPI::ColorFormat aColorFormat)
 {
   if (!mImageContainer) {
     NS_WARNING("No image container to construct an image");
     return nullptr;
   }
 
   nsRefPtr<Image> image;
   switch(aColorFormat) {
@@ -370,18 +370,18 @@ MediaPluginReader::ImageBufferCallback::
       return CreateI420Image(aWidth, aHeight);
     default:
       NS_NOTREACHED("Color format not supported");
       return nullptr;
   }
 }
 
 uint8_t *
-MediaPluginReader::ImageBufferCallback::CreateI420Image(size_t aWidth,
-                                                        size_t aHeight)
+AndroidMediaReader::ImageBufferCallback::CreateI420Image(size_t aWidth,
+                                                         size_t aHeight)
 {
   mImage = mImageContainer->CreateImage(ImageFormat::PLANAR_YCBCR);
   PlanarYCbCrImage *yuvImage = static_cast<PlanarYCbCrImage *>(mImage.get());
 
   if (!yuvImage) {
     NS_WARNING("Could not create I420 image");
     return nullptr;
   }
@@ -413,14 +413,14 @@ MediaPluginReader::ImageBufferCallback::
   frameDesc.mPicSize = IntSize(aWidth, aHeight);
 
   yuvImage->SetDataNoCopy(frameDesc);
 
   return buffer;
 }
 
 already_AddRefed<Image>
-MediaPluginReader::ImageBufferCallback::GetImage()
+AndroidMediaReader::ImageBufferCallback::GetImage()
 {
   return mImage.forget();
 }
 
 } // namespace mozilla
rename from content/media/plugins/MediaPluginReader.h
rename to content/media/android/AndroidMediaReader.h
--- a/content/media/plugins/MediaPluginReader.h
+++ b/content/media/android/AndroidMediaReader.h
@@ -1,15 +1,15 @@
 /* -*- 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/. */
-#if !defined(MediaPluginReader_h_)
-#define MediaPluginReader_h_
+#if !defined(AndroidMediaReader_h_)
+#define AndroidMediaReader_h_
 
 #include "mozilla/Attributes.h"
 #include "MediaResource.h"
 #include "MediaDecoderReader.h"
 #include "ImageContainer.h"
 #include "nsAutoPtr.h"
 #include "mozilla/layers/SharedRGBImage.h"
  
@@ -24,30 +24,30 @@ class AbstractMediaDecoder;
 namespace layers {
 class ImageContainer;
 }
 
 namespace dom {
 class TimeRanges;
 }
  
-class MediaPluginReader : public MediaDecoderReader
+class AndroidMediaReader : public MediaDecoderReader
 {
   nsCString mType;
   MPAPI::Decoder *mPlugin;
   bool mHasAudio;
   bool mHasVideo;
   nsIntRect mPicture;
   nsIntSize mInitialFrame;
   int64_t mVideoSeekTimeUs;
   int64_t mAudioSeekTimeUs;
   nsAutoPtr<VideoData> mLastVideoFrame;
 public:
-  MediaPluginReader(AbstractMediaDecoder* aDecoder,
-                    const nsACString& aContentType);
+  AndroidMediaReader(AbstractMediaDecoder* aDecoder,
+                     const nsACString& aContentType);
 
   virtual nsresult Init(MediaDecoderReader* aCloneDonor);
   virtual nsresult ResetDecode();
 
   virtual bool DecodeAudioData();
   virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
                                 int64_t aTimeThreshold);
 
rename from content/media/plugins/MediaResourceServer.cpp
rename to content/media/android/AndroidMediaResourceServer.cpp
--- a/content/media/plugins/MediaResourceServer.cpp
+++ b/content/media/android/AndroidMediaResourceServer.cpp
@@ -11,17 +11,17 @@
 #include "nsISocketTransport.h"
 #include "nsIOutputStream.h"
 #include "nsIInputStream.h"
 #include "nsIRandomGenerator.h"
 #include "nsReadLine.h"
 #include "nsNetCID.h"
 #include "VideoUtils.h"
 #include "MediaResource.h"
-#include "MediaResourceServer.h"
+#include "AndroidMediaResourceServer.h"
 
 #if defined(_MSC_VER)
 #define strtoll _strtoi64
 #define snprintf _snprintf_s
 #endif
 
 using namespace mozilla;
 
@@ -106,29 +106,29 @@ ReadCRLF (StreamType* aStream, nsLineBuf
 class ServeResourceEvent : public nsRunnable {
 private:
   // Reading from this reads the data sent from the client.
   nsCOMPtr<nsIInputStream> mInput;
 
   // Writing to this sends data to the client.
   nsCOMPtr<nsIOutputStream> mOutput;
 
-  // The MediaResourceServer that owns the MediaResource instances
+  // The AndroidMediaResourceServer that owns the MediaResource instances
   // served. This is used to lookup the MediaResource from the URL.
-  nsRefPtr<MediaResourceServer> mServer;
+  nsRefPtr<AndroidMediaResourceServer> mServer;
 
   // Write 'aBufferLength' bytes from 'aBuffer' to 'mOutput'. This
   // method ensures all the data is written by checking the number
   // of bytes returned from the output streams 'Write' method and
   // looping until done.
   nsresult WriteAll(char const* aBuffer, int32_t aBufferLength);
 
 public:
   ServeResourceEvent(nsIInputStream* aInput, nsIOutputStream* aOutput,
-                     MediaResourceServer* aServer)
+                     AndroidMediaResourceServer* aServer)
     : mInput(aInput), mOutput(aOutput), mServer(aServer) {}
 
   // This method runs on the thread and exits when it has completed the
   // HTTP request.
   NS_IMETHOD Run();
 
   // Given the first line of an HTTP request, parse the URL requested and
   // return the MediaResource for that URL.
@@ -331,30 +331,30 @@ ServeResourceEvent::Shutdown()
   This is the listener attached to the server socket. When an HTTP
   request is made by the client the OnSocketAccepted method is
   called. This method will spawn a thread to process the request.
   The thread receives a single event which does the parsing of
   the HTTP request and forwarding the data from the MediaResource
   to the output stream of the request.
 
   The MediaResource used for providing the request data is obtained
-  from the MediaResourceServer that created this listener, using the
+  from the AndroidMediaResourceServer that created this listener, using the
   URL the client requested.
 */
 class ResourceSocketListener : public nsIServerSocketListener
 {
 public:
-  // The MediaResourceServer used to look up the MediaResource
+  // The AndroidMediaResourceServer used to look up the MediaResource
   // on requests.
-  nsRefPtr<MediaResourceServer> mServer;
+  nsRefPtr<AndroidMediaResourceServer> mServer;
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSISERVERSOCKETLISTENER
 
-  ResourceSocketListener(MediaResourceServer* aServer) :
+  ResourceSocketListener(AndroidMediaResourceServer* aServer) :
     mServer(aServer)
   {
   }
 
 private:
   virtual ~ResourceSocketListener() { }
 };
 
@@ -383,23 +383,23 @@ ResourceSocketListener::OnSocketAccepted
 }
 
 NS_IMETHODIMP
 ResourceSocketListener::OnStopListening(nsIServerSocket* aServ, nsresult aStatus)
 {
   return NS_OK;
 }
 
-MediaResourceServer::MediaResourceServer() :
-  mMutex("MediaResourceServer")
+AndroidMediaResourceServer::AndroidMediaResourceServer() :
+  mMutex("AndroidMediaResourceServer")
 {
 }
 
 NS_IMETHODIMP
-MediaResourceServer::Run()
+AndroidMediaResourceServer::Run()
 {
   MutexAutoLock lock(mMutex);
 
   nsresult rv;
   mSocket = do_CreateInstance(NS_SERVERSOCKET_CONTRACTID, &rv);
   if (NS_FAILED(rv)) return rv;
 
   rv = mSocket->InitSpecialConnection(-1,
@@ -410,34 +410,34 @@ MediaResourceServer::Run()
 
   rv = mSocket->AsyncListen(new ResourceSocketListener(this));
   if (NS_FAILED(rv)) return rv;
 
   return NS_OK;
 }
 
 /* static */
-already_AddRefed<MediaResourceServer>
-MediaResourceServer::Start()
+already_AddRefed<AndroidMediaResourceServer>
+AndroidMediaResourceServer::Start()
 {
-  nsRefPtr<MediaResourceServer> server = new MediaResourceServer();
+  nsRefPtr<AndroidMediaResourceServer> server = new AndroidMediaResourceServer();
   NS_DispatchToMainThread(server, NS_DISPATCH_SYNC);
   return server.forget();
 }
 
 void
-MediaResourceServer::Stop()
+AndroidMediaResourceServer::Stop()
 {
   MutexAutoLock lock(mMutex);
   mSocket->Close();
   mSocket = nullptr;
 }
 
 nsresult
-MediaResourceServer::AppendRandomPath(nsCString& aUrl)
+AndroidMediaResourceServer::AppendRandomPath(nsCString& aUrl)
 {
   // Use a cryptographic quality PRNG to generate raw random bytes
   // and convert that to a base64 string for use as an URL path. This
   // is based on code from nsExternalAppHandler::SetUpTempFile.
   nsresult rv;
   nsCOMPtr<nsIRandomGenerator> rg =
     do_GetService("@mozilla.org/security/random-generator;1", &rv);
   if (NS_FAILED(rv)) return rv;
@@ -469,17 +469,17 @@ MediaResourceServer::AppendRandomPath(ns
 
   aUrl += "/";
   aUrl += tempLeafName;
 
   return NS_OK;
 }
 
 nsresult
-MediaResourceServer::AddResource(mozilla::MediaResource* aResource, nsCString& aUrl)
+AndroidMediaResourceServer::AddResource(mozilla::MediaResource* aResource, nsCString& aUrl)
 {
   nsCString url = GetURLPrefix();
   nsresult rv = AppendRandomPath(url);
   if (NS_FAILED (rv)) return rv;
 
   {
     MutexAutoLock lock(mMutex);
 
@@ -489,40 +489,40 @@ MediaResourceServer::AddResource(mozilla
   }
 
   aUrl = url;
 
   return NS_OK;
 }
 
 void
-MediaResourceServer::RemoveResource(nsCString const& aUrl)
+AndroidMediaResourceServer::RemoveResource(nsCString const& aUrl)
 {
   MutexAutoLock lock(mMutex);
   mResources.erase(aUrl);
 }
 
 nsCString
-MediaResourceServer::GetURLPrefix()
+AndroidMediaResourceServer::GetURLPrefix()
 {
   MutexAutoLock lock(mMutex);
 
   int32_t port = 0;
   nsresult rv = mSocket->GetPort(&port);
   if (NS_FAILED (rv) || port < 0) {
     return nsCString("");
   }
 
   char buffer[256];
   snprintf(buffer, sizeof(buffer), "http://127.0.0.1:%d", port >= 0 ? port : 0);
   return nsCString(buffer);
 }
 
 already_AddRefed<MediaResource>
-MediaResourceServer::GetResource(nsCString const& aUrl)
+AndroidMediaResourceServer::GetResource(nsCString const& aUrl)
 {
   MutexAutoLock lock(mMutex);
   ResourceMap::const_iterator it = mResources.find(aUrl);
   if (it == mResources.end()) return nullptr;
 
   nsRefPtr<MediaResource> resource = it->second;
   return resource.forget();
 }
rename from content/media/plugins/MediaResourceServer.h
rename to content/media/android/AndroidMediaResourceServer.h
--- a/content/media/plugins/MediaResourceServer.h
+++ b/content/media/android/AndroidMediaResourceServer.h
@@ -1,80 +1,80 @@
 /* -*- 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/. */
-#if !defined(MediaResourceServer_h_)
-#define MediaResourceServer_h_
+#if !defined(AndroidMediaResourceServer_h_)
+#define AndroidMediaResourceServer_h_
 
 #include <map>
 #include "nsIServerSocket.h"
 #include "MediaResource.h"
 
 namespace mozilla {
 
 class MediaResource;
 
 /*
-  MediaResourceServer instantiates a socket server that understands
+  AndroidMediaResourceServer instantiates a socket server that understands
   HTTP requests for MediaResource instances. The server runs on an
   automatically selected port and MediaResource instances are registered.
   The registration returns a string URL than can be used to fetch the
   resource. That URL contains a randomly generated path to make it
   difficult for other local applications on the device to guess it.
 
   The HTTP protocol is limited in that it supports only what the
   Android DataSource implementation uses to fetch media. It
   understands HTTP GET and byte range requests.
 
   The intent of this class is to be used in Media backends that
   have a system component that does its own network requests. These
   requests are made against this server which then uses standard
   Gecko network requests and media cache usage.
 
-  The MediaResourceServer can be instantiated on any thread and
+  The AndroidMediaResourceServer can be instantiated on any thread and
   its methods are threadsafe - they can be called on any thread.
   The server socket itself is always run on the main thread and
   this is done by the Start() static method by synchronously
   dispatching to the main thread.
 */
-class MediaResourceServer : public nsRunnable
+class AndroidMediaResourceServer : public nsRunnable
 {
 private:
-  // Mutex protecting private members of MediaResourceServer.
+  // Mutex protecting private members of AndroidMediaResourceServer.
   // All member variables below this point in the class definition
   // must acquire the mutex before access.
   mozilla::Mutex mMutex;
 
   // Server socket used to listen for incoming connections
   nsCOMPtr<nsIServerSocket> mSocket;
 
   // Mapping between MediaResource URL's to the MediaResource
   // object served at that URL.
   typedef std::map<nsCString,
                   nsRefPtr<mozilla::MediaResource> > ResourceMap;
   ResourceMap mResources;
 
-  // Create a MediaResourceServer that will listen on an automatically
+  // Create a AndroidMediaResourceServer that will listen on an automatically
   // selected port when started. This is private as it should only be
   // called internally from the public 'Start' method.
-  MediaResourceServer();
+  AndroidMediaResourceServer();
   NS_IMETHOD Run();
 
   // Append a random URL path to a string. This is used for creating a
   // unique URl for a resource which helps prevent malicious software
   // running on the same machine as the server from guessing the URL
   // and accessing video data.
   nsresult AppendRandomPath(nsCString& aURL);
 
 public:
-  // Create a MediaResourceServer and start it listening. This call will
+  // Create a AndroidMediaResourceServer and start it listening. This call will
   // perform a synchronous request on the main thread.
-  static already_AddRefed<MediaResourceServer> Start();
+  static already_AddRefed<AndroidMediaResourceServer> Start();
 
   // Stops the server from listening and accepting further connections.
   void Stop();
 
   // Add a MediaResource to be served by this server. Stores the
   // absolute URL that can be used to access the resource in 'aUrl'.
   nsresult AddResource(mozilla::MediaResource* aResource, nsCString& aUrl);
 
rename from content/media/plugins/MPAPI.h
rename to content/media/android/MPAPI.h
rename from content/media/plugins/moz.build
rename to content/media/android/moz.build
--- a/content/media/plugins/moz.build
+++ b/content/media/android/moz.build
@@ -1,27 +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/.
 
 EXPORTS += [
-    'MediaPluginDecoder.h',
-    'MediaPluginHost.h',
-    'MediaPluginReader.h',
-    'MediaResourceServer.h',
+    'AndroidMediaDecoder.h',
+    'AndroidMediaPluginHost.h',
+    'AndroidMediaReader.h',
+    'AndroidMediaResourceServer.h',
     'MPAPI.h',
 ]
 
 UNIFIED_SOURCES += [
-    'MediaPluginDecoder.cpp',
-    'MediaPluginHost.cpp',
-    'MediaPluginReader.cpp',
-    'MediaResourceServer.cpp',
+    'AndroidMediaDecoder.cpp',
+    'AndroidMediaPluginHost.cpp',
+    'AndroidMediaReader.cpp',
+    'AndroidMediaResourceServer.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/content/base/src',
     '/content/html/content/src',
     ]
 
 FINAL_LIBRARY = 'gklayout'
--- a/content/media/fmp4/MP4Reader.cpp
+++ b/content/media/fmp4/MP4Reader.cpp
@@ -34,17 +34,17 @@ PRLogModuleInfo* GetDemuxerLog() {
 
 using namespace mp4_demuxer;
 
 namespace mozilla {
 
 // Uncomment to enable verbose per-sample logging.
 //#define LOG_SAMPLE_DECODE 1
 
-#ifdef LOG_SAMPLE_DECODE
+#ifdef PR_LOGGING
 static const char*
 TrackTypeToStr(TrackType aTrack)
 {
   MOZ_ASSERT(aTrack == kAudio || aTrack == kVideo);
   switch (aTrack) {
   case kAudio:
     return "Audio";
   case kVideo:
@@ -346,19 +346,18 @@ MP4Reader::Decode(TrackType aTrack)
            (data.mInputExhausted ||
            (data.mNumSamplesInput - data.mNumSamplesOutput) < data.mDecodeAhead)) {
       data.mMonitor.AssertCurrentThreadOwns();
       data.mMonitor.Unlock();
       nsAutoPtr<MP4Sample> compressed(PopSample(aTrack));
       if (!compressed) {
         // EOS, or error. Let the state machine know there are no more
         // frames coming.
-#ifdef LOG_SAMPLE_DECODE
-        LOG("PopSample %s nullptr", TrackTypeToStr(aTrack));
-#endif
+        LOG("Draining %s", TrackTypeToStr(aTrack));
+        data.mDecoder->Drain();
         return false;
       } else {
 #ifdef LOG_SAMPLE_DECODE
         LOG("PopSample %s time=%lld dur=%lld", TrackTypeToStr(aTrack),
             compressed->composition_timestamp, compressed->duration);
 #endif
       }
       data.mMonitor.Lock();
--- a/content/media/fmp4/PlatformDecoderModule.h
+++ b/content/media/fmp4/PlatformDecoderModule.h
@@ -174,16 +174,18 @@ public:
   virtual nsresult Flush() = 0;
 
   // Causes all complete samples in the pipeline that can be decoded to be
   // output. If the decoder can't produce samples from the current output,
   // it drops the input samples. The decoder may be holding onto samples
   // that are required to decode samples that it expects to get in future.
   // This is called when the demuxer reaches end of stream.
   // The MP4Reader will not call Input() while it's calling Drain().
+  // This function is synchronous. Once it's returned, all samples to be
+  // output should have been returned via callback to the MP4Reader.
   virtual nsresult Drain() = 0;
 
   // Cancels all init/input/drain operations, and shuts down the
   // decoder. The platform decoder should clean up any resources it's using
   // and release memory etc. Shutdown() must block until the decoder has
   // completed shutdown. The reader calls Flush() before calling Shutdown().
   // The reader will delete the decoder once Shutdown() returns.
   // The MediaDataDecoderCallback *must* not be called after Shutdown() has
--- a/content/media/fmp4/wmf/WMFMediaDataDecoder.cpp
+++ b/content/media/fmp4/wmf/WMFMediaDataDecoder.cpp
@@ -115,17 +115,17 @@ WMFMediaDataDecoder::Flush()
   return NS_OK;
 }
 
 void
 WMFMediaDataDecoder::ProcessDrain()
 {
   // Order the decoder to drain...
   if (FAILED(mDecoder->SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN, 0))) {
-    NS_WARNING("Failed to send DRAIN command to audio MFT");
+    NS_WARNING("Failed to send DRAIN command to MFT");
   }
   // Then extract all available output.
   ProcessOutput();
 }
 
 nsresult
 WMFMediaDataDecoder::Drain()
 {
--- a/content/media/fmp4/wmf/WMFVideoMFTManager.cpp
+++ b/content/media/fmp4/wmf/WMFVideoMFTManager.cpp
@@ -200,17 +200,17 @@ WMFVideoMFTManager::ConfigureVideoFrameG
   // Success! Save state.
   mVideoInfo.mDisplay = displaySize;
   mVideoInfo.mHasVideo = true;
   GetDefaultStride(mediaType, &mVideoStride);
   mVideoWidth = width;
   mVideoHeight = height;
   mPictureRegion = pictureRegion;
 
-  LOG("WMFReader frame geometry frame=(%u,%u) stride=%u picture=(%d, %d, %d, %d) display=(%d,%d) PAR=%d:%d",
+  LOG("WMFVideoMFTManager frame geometry frame=(%u,%u) stride=%u picture=(%d, %d, %d, %d) display=(%d,%d) PAR=%d:%d",
       width, height,
       mVideoStride,
       mPictureRegion.x, mPictureRegion.y, mPictureRegion.width, mPictureRegion.height,
       displaySize.width, displaySize.height,
       aspectNum, aspectDenom);
 
   return S_OK;
 }
--- a/content/media/gmp/GMPChild.cpp
+++ b/content/media/gmp/GMPChild.cpp
@@ -14,16 +14,21 @@
 #include "GMPPlatform.h"
 
 #ifdef XP_WIN
 #include <stdlib.h> // for _exit()
 #else
 #include <unistd.h> // for _exit()
 #endif
 
+#if defined(XP_WIN)
+#define TARGET_SANDBOX_EXPORTS
+#include "mozilla/sandboxTarget.h"
+#endif
+
 namespace mozilla {
 namespace gmp {
 
 GMPChild::GMPChild()
   : mLib(nullptr)
   , mGetAPIFunc(nullptr)
   , mGMPMessageLoop(MessageLoop::current())
 {
@@ -34,16 +39,19 @@ GMPChild::~GMPChild()
 }
 
 bool
 GMPChild::Init(const std::string& aPluginPath,
                base::ProcessHandle aParentProcessHandle,
                MessageLoop* aIOLoop,
                IPC::Channel* aChannel)
 {
+#if defined(XP_WIN)
+  mozilla::SandboxTarget::Instance()->StartSandbox();
+#endif
   return LoadPluginLibrary(aPluginPath) &&
          Open(aChannel, aParentProcessHandle, aIOLoop);
 }
 
 bool
 GMPChild::LoadPluginLibrary(const std::string& aPluginPath)
 {
   nsDependentCString pluginPath(aPluginPath.c_str());
--- a/content/media/gmp/GMPProcessParent.cpp
+++ b/content/media/gmp/GMPProcessParent.cpp
@@ -46,16 +46,17 @@ GMPProcessParent::Launch(int32_t aTimeou
 
 void
 GMPProcessParent::Delete()
 {
   MessageLoop* currentLoop = MessageLoop::current();
   MessageLoop* ioLoop = XRE_GetIOMessageLoop();
 
   if (currentLoop == ioLoop) {
+    Join();
     delete this;
     return;
   }
 
   ioLoop->PostTask(FROM_HERE, NewRunnableMethod(this, &GMPProcessParent::Delete));
 }
 
 } // namespace gmp
--- a/content/media/gmp/GMPService.cpp
+++ b/content/media/gmp/GMPService.cpp
@@ -9,16 +9,17 @@
 #include "nsIObserverService.h"
 #include "GeckoChildProcessHost.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/SyncRunnable.h"
 #include "nsXPCOMPrivate.h"
 #include "mozilla/Services.h"
 #include "nsNativeCharsetUtils.h"
 #include "nsIConsoleService.h"
+#include "mozilla/unused.h"
 
 namespace mozilla {
 namespace gmp {
 
 static StaticRefPtr<GeckoMediaPluginService> sSingletonService;
 
 class GMPServiceCreateHelper MOZ_FINAL : public nsRunnable
 {
@@ -108,16 +109,20 @@ void
 GeckoMediaPluginService::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService();
   MOZ_ASSERT(obsService);
   MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false)));
   MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false)));
+
+  // Kick off scanning for plugins
+  nsCOMPtr<nsIThread> thread;
+  unused << GetThread(getter_AddRefs(thread));
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginService::Observe(nsISupports* aSubject,
                                  const char* aTopic,
                                  const char16_t* aSomeData)
 {
   if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic)) {
@@ -250,16 +255,17 @@ GeckoMediaPluginService::GetGMPVideoEnco
 void
 GeckoMediaPluginService::UnloadPlugins()
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
 
   MOZ_ASSERT(!mShuttingDownOnGMPThread);
   mShuttingDownOnGMPThread = true;
 
+  MutexAutoLock lock(mMutex);
   for (uint32_t i = 0; i < mPlugins.Length(); i++) {
     mPlugins[i]->UnloadProcess();
   }
   mPlugins.Clear();
 }
 
 void
 GeckoMediaPluginService::LoadFromEnvironment()
@@ -325,23 +331,38 @@ GeckoMediaPluginService::RemovePluginDir
   if (NS_FAILED(rv)) {
     return rv;
   }
   nsCOMPtr<nsIRunnable> r = new PathRunnable(this, aDirectory, false);
   thread->Dispatch(r, NS_DISPATCH_NORMAL);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+GeckoMediaPluginService::HasPluginForAPI(const nsAString& aOrigin,
+                                         const nsACString& aAPI,
+                                         nsTArray<nsCString>* aTags,
+                                         bool* aResult)
+{
+  NS_ENSURE_ARG(aTags && aTags->Length() > 0);
+  NS_ENSURE_ARG(aResult);
+
+  nsCString temp(aAPI);
+  GMPParent *parent = SelectPluginForAPI(aOrigin, temp, *aTags);
+  *aResult = !!parent;
+
+  return NS_OK;
+}
+
 GMPParent*
 GeckoMediaPluginService::SelectPluginForAPI(const nsAString& aOrigin,
                                             const nsCString& aAPI,
                                             const nsTArray<nsCString>& aTags)
 {
-  MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
-
+  MutexAutoLock lock(mMutex);
   for (uint32_t i = 0; i < mPlugins.Length(); i++) {
     GMPParent* gmp = mPlugins[i];
     bool supportsAllTags = true;
     for (uint32_t t = 0; t < aTags.Length(); t++) {
       const nsCString& tag = aTags[t];
       if (!gmp->SupportsAPI(aAPI, tag)) {
         supportsAllTags = false;
         break;
@@ -397,30 +418,32 @@ GeckoMediaPluginService::AddOnGMPThread(
   mozilla::SyncRunnable::DispatchToThread(mainThread, task);
   nsRefPtr<GMPParent> gmp = task->GetParent();
   rv = gmp->Init(directory);
   if (NS_FAILED(rv)) {
     NS_WARNING("Can't Create GMPParent");
     return;
   }
 
+  MutexAutoLock lock(mMutex);
   mPlugins.AppendElement(gmp);
 }
 
 void
 GeckoMediaPluginService::RemoveOnGMPThread(const nsAString& aDirectory)
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
+  MutexAutoLock lock(mMutex);
   for (uint32_t i = 0; i < mPlugins.Length(); ++i) {
     nsCOMPtr<nsIFile> pluginpath = mPlugins[i]->GetDirectory();
     bool equals;
     if (NS_SUCCEEDED(directory->Equals(pluginpath, &equals)) && equals) {
       mPlugins[i]->UnloadProcess();
       mPlugins.RemoveElementAt(i);
       return;
     }
--- a/content/media/gmp/GMPService.h
+++ b/content/media/gmp/GMPService.h
@@ -64,18 +64,18 @@ private:
     NS_DECL_NSIRUNNABLE
 
   private:
     nsRefPtr<GeckoMediaPluginService> mService;
     nsString mPath;
     bool mAdd;
   };
 
+  Mutex mMutex; // Protects mGMPThread and mShuttingDown and mPlugins
   nsTArray<nsRefPtr<GMPParent>> mPlugins;
-  Mutex mMutex; // Protects mGMPThread and mShuttingDown
   nsCOMPtr<nsIThread> mGMPThread;
   bool mShuttingDown;
   bool mShuttingDownOnGMPThread;
 };
 
 } // namespace gmp
 } // namespace mozilla
 
--- a/content/media/gmp/mozIGeckoMediaPluginService.idl
+++ b/content/media/gmp/mozIGeckoMediaPluginService.idl
@@ -16,25 +16,34 @@ class GMPVideoHost;
 %}
 
 [ptr] native GMPVideoDecoderProxy(GMPVideoDecoderProxy);
 [ptr] native GMPVideoEncoderProxy(GMPVideoEncoderProxy);
 [ptr] native GMPVideoHost(GMPVideoHost);
 [ptr] native MessageLoop(MessageLoop);
 [ptr] native TagArray(nsTArray<nsCString>);
 
-[scriptable, uuid(7cef50ca-7a0f-41f2-9560-47abf709f0d7)]
+[scriptable, uuid(a9b826da-725a-4b81-814f-b715445188f2)]
 interface mozIGeckoMediaPluginService : nsISupports
 {
   /**
    * The GMP thread. Callable from any thread.
    */
   readonly attribute nsIThread thread;
 
   /**
+   * Get a plugin that supports the specified tags.
+   * Callable on any thread
+   */
+  [noscript]
+  boolean hasPluginForAPI([optional] in AString origin,
+                          in ACString api,
+                          in TagArray tags);
+
+  /**
    * Get a video decoder that supports the specified tags.
    * The array of tags should at least contain a codec tag, and optionally
    * other tags such as for EME keysystem.
    * Callable only on GMP thread.
    */
   [noscript]
   GMPVideoDecoderProxy getGMPVideoDecoder(in TagArray tags,
                                           [optional] in AString origin,
--- a/content/media/moz.build
+++ b/content/media/moz.build
@@ -25,18 +25,18 @@ if CONFIG['MOZ_WEBM']:
     PARALLEL_DIRS += ['webm']
 
 if CONFIG['MOZ_GSTREAMER']:
     PARALLEL_DIRS += ['gstreamer']
 
 if CONFIG['MOZ_DIRECTSHOW']:
     PARALLEL_DIRS += ['directshow']
 
-if CONFIG['MOZ_MEDIA_PLUGINS']:
-    PARALLEL_DIRS += ['plugins']
+if CONFIG['MOZ_ANDROID_OMX']:
+    PARALLEL_DIRS += ['android']
 
 if CONFIG['MOZ_WMF']:
     PARALLEL_DIRS += ['wmf']
 
 if CONFIG['MOZ_FMP4']:
     PARALLEL_DIRS += ['fmp4']
 
 if CONFIG['MOZ_APPLEMEDIA']:
@@ -45,17 +45,18 @@ if CONFIG['MOZ_APPLEMEDIA']:
 PARALLEL_DIRS += ['webrtc']
 
 if CONFIG['MOZ_OMX_DECODER']:
     PARALLEL_DIRS += ['omx']
     PARALLEL_DIRS += ['omx/mediaresourcemanager']
 
 PARALLEL_DIRS += ['webspeech']
 
-PARALLEL_DIRS += ['eme']
+if CONFIG['MOZ_EME']:
+    PARALLEL_DIRS += ['eme']
 
 TEST_DIRS += [
     'test',
     'gtest',
 ]
 
 EXPORTS += [
     'AbstractMediaDecoder.h',
new file mode 100644
--- /dev/null
+++ b/content/media/omx/I420ColorConverterHelper.cpp
@@ -0,0 +1,229 @@
+/* -*- 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 "I420ColorConverterHelper.h"
+
+#include <dlfcn.h>
+
+#include "prlog.h"
+
+#ifdef PR_LOGGING
+PRLogModuleInfo *gI420ColorConverterHelperLog;
+#define LOG(msg...) PR_LOG(gI420ColorConverterHelperLog, PR_LOG_WARNING, (msg))
+#else
+#define LOG(x...)
+#endif
+
+namespace android {
+
+I420ColorConverterHelper::I420ColorConverterHelper()
+  : mHandle(nullptr)
+  , mConverter({nullptr, nullptr, nullptr, nullptr, nullptr})
+{
+#ifdef PR_LOGGING
+  if (!gI420ColorConverterHelperLog) {
+    gI420ColorConverterHelperLog = PR_NewLogModule("I420ColorConverterHelper");
+  }
+#endif
+}
+
+I420ColorConverterHelper::~I420ColorConverterHelper()
+{
+  RWLock::AutoWLock awl(mLock);
+  unloadLocked();
+}
+
+// Prerequisite: a writer-lock should be held
+bool
+I420ColorConverterHelper::loadLocked()
+{
+  if (loadedLocked()) {
+    return true;
+  }
+  unloadLocked();
+
+  // Open the shared library
+  mHandle = dlopen("libI420colorconvert.so", RTLD_NOW);
+  if (mHandle == nullptr) {
+    LOG("libI420colorconvert.so not found");
+    return false;
+  }
+
+  // Find the entry point
+  // Pointer to function with signature
+  // void getI420ColorConverter(II420ColorConverter *converter)
+  typedef int (* getConverterFn)(II420ColorConverter *converter);
+  getConverterFn getI420ColorConverter =
+      (getConverterFn) dlsym(mHandle, "getI420ColorConverter");
+  if (getI420ColorConverter == nullptr) {
+    LOG("Cannot load getI420ColorConverter from libI420colorconvert.so");
+    unloadLocked();
+    return false;
+  }
+
+  // Fill the function pointers.
+  getI420ColorConverter(&mConverter);
+  if (mConverter.getDecoderOutputFormat == nullptr ||
+      mConverter.convertDecoderOutputToI420 == nullptr ||
+      mConverter.getEncoderInputFormat == nullptr ||
+      mConverter.convertI420ToEncoderInput == nullptr ||
+      mConverter.getEncoderInputBufferInfo == nullptr) {
+    LOG("Failed to initialize I420 color converter");
+    unloadLocked();
+    return false;
+  }
+
+  return true;
+}
+
+// Prerequisite: a reader-lock or a writer-lock should be held
+bool
+I420ColorConverterHelper::loadedLocked() const
+{
+  if (mHandle == nullptr ||
+      mConverter.getDecoderOutputFormat == nullptr ||
+      mConverter.convertDecoderOutputToI420 == nullptr ||
+      mConverter.getEncoderInputFormat == nullptr ||
+      mConverter.convertI420ToEncoderInput == nullptr ||
+      mConverter.getEncoderInputBufferInfo == nullptr) {
+    return false;
+  }
+  return true;
+}
+
+// Prerequisite: a writer-lock should be held
+void
+I420ColorConverterHelper::unloadLocked()
+{
+  if (mHandle != nullptr) {
+    dlclose(mHandle);
+  }
+  mHandle = nullptr;
+  mConverter.getDecoderOutputFormat = nullptr;
+  mConverter.convertDecoderOutputToI420 = nullptr;
+  mConverter.getEncoderInputFormat = nullptr;
+  mConverter.convertI420ToEncoderInput = nullptr;
+  mConverter.getEncoderInputBufferInfo = nullptr;
+}
+
+bool
+I420ColorConverterHelper::ensureLoaded()
+{
+  {
+    RWLock::AutoRLock arl(mLock);
+    // Check whether the library has been loaded or not.
+    if (loadedLocked()) {
+      return true;
+    }
+  }
+
+  {
+    RWLock::AutoWLock awl(mLock);
+    // Check whether the library has been loaded or not on other threads.
+    if (loadedLocked()) {
+      return true;
+    }
+
+    // Reload the library
+    unloadLocked();
+    if (loadLocked()) {
+      return true;
+    }
+
+    // Reset the library
+    unloadLocked();
+  }
+
+  return false;
+}
+
+int
+I420ColorConverterHelper::getDecoderOutputFormat()
+{
+  if (!ensureLoaded()) {
+    return -1;
+  }
+
+  RWLock::AutoRLock arl(mLock);
+  if (mConverter.getDecoderOutputFormat != nullptr) {
+    return mConverter.getDecoderOutputFormat();
+  }
+  return -1;
+}
+
+int
+I420ColorConverterHelper::convertDecoderOutputToI420(
+    void* decoderBits, int decoderWidth, int decoderHeight,
+    ARect decoderRect, void* dstBits)
+{
+  if (!ensureLoaded()) {
+    return -1;
+  }
+
+  RWLock::AutoRLock arl(mLock);
+  if (mConverter.convertDecoderOutputToI420 != nullptr) {
+    return mConverter.convertDecoderOutputToI420(decoderBits,
+        decoderWidth, decoderHeight, decoderRect, dstBits);
+  }
+  return -1;
+}
+
+int
+I420ColorConverterHelper::getEncoderInputFormat()
+{
+  if (!ensureLoaded()) {
+    return -1;
+  }
+
+  RWLock::AutoRLock arl(mLock);
+  if (mConverter.getEncoderInputFormat != nullptr) {
+    return mConverter.getEncoderInputFormat();
+  }
+  return -1;
+}
+
+int
+I420ColorConverterHelper::convertI420ToEncoderInput(void* aSrcBits,
+                                                    int aSrcWidth,
+                                                    int aSrcHeight,
+                                                    int aEncoderWidth,
+                                                    int aEncoderHeight,
+                                                    ARect aEncoderRect,
+                                                    void* aEncoderBits)
+{
+  if (!ensureLoaded()) {
+    return -1;
+  }
+
+  RWLock::AutoRLock arl(mLock);
+  if (mConverter.convertI420ToEncoderInput != nullptr) {
+    return mConverter.convertI420ToEncoderInput(aSrcBits, aSrcWidth, aSrcHeight,
+        aEncoderWidth, aEncoderHeight, aEncoderRect, aEncoderBits);
+  }
+  return -1;
+}
+
+int
+I420ColorConverterHelper::getEncoderInputBufferInfo(int aSrcWidth,
+                                                    int aSrcHeight,
+                                                    int* aEncoderWidth,
+                                                    int* aEncoderHeight,
+                                                    ARect* aEncoderRect,
+                                                    int* aEncoderBufferSize)
+{
+  if (!ensureLoaded()) {
+    return -1;
+  }
+
+  RWLock::AutoRLock arl(mLock);
+  if (mConverter.getEncoderInputBufferInfo != nullptr) {
+    return mConverter.getEncoderInputBufferInfo(aSrcWidth, aSrcHeight,
+        aEncoderWidth, aEncoderHeight, aEncoderRect, aEncoderBufferSize);
+  }
+  return -1;
+}
+
+} // namespace android
new file mode 100644
--- /dev/null
+++ b/content/media/omx/I420ColorConverterHelper.h
@@ -0,0 +1,64 @@
+/* -*- 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 I420_COLOR_CONVERTER_HELPER_H
+#define I420_COLOR_CONVERTER_HELPER_H
+
+#include <utils/RWLock.h>
+#include <media/editor/II420ColorConverter.h>
+
+#include <mozilla/Attributes.h>
+
+namespace android {
+
+class I420ColorConverterHelper {
+public:
+  I420ColorConverterHelper();
+  ~I420ColorConverterHelper();
+
+  int getDecoderOutputFormat();
+
+  int convertDecoderOutputToI420(void* aDecoderBits,
+                                 int aDecoderWidth,
+                                 int aDecoderHeight,
+                                 ARect aDecoderRect,
+                                 void* aDstBits);
+
+  int getEncoderInputFormat();
+
+  int convertI420ToEncoderInput(void* aSrcBits,
+                                int aSrcWidth,
+                                int aSrcHeight,
+                                int aEncoderWidth,
+                                int aEncoderHeight,
+                                ARect aEncoderRect,
+                                void* aEncoderBits);
+
+  int getEncoderInputBufferInfo(int aSrcWidth,
+                                int aSrcHeight,
+                                int* aEncoderWidth,
+                                int* aEncoderHeight,
+                                ARect* aEncoderRect,
+                                int* aEncoderBufferSize);
+
+private:
+  mutable RWLock mLock;
+  void *mHandle;
+  II420ColorConverter mConverter;
+
+  bool loadLocked();
+  bool loadedLocked() const;
+  void unloadLocked();
+
+  bool ensureLoaded();
+
+  I420ColorConverterHelper(const I420ColorConverterHelper &) MOZ_DELETE;
+  const I420ColorConverterHelper &operator=(const I420ColorConverterHelper &) MOZ_DELETE;
+};
+
+} // namespace android
+
+#endif // I420_COLOR_CONVERTER_HELPER_H
new file mode 100644
--- /dev/null
+++ b/content/media/omx/MediaCodecDecoder.cpp
@@ -0,0 +1,25 @@
+/* -*- 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 "MediaCodecDecoder.h"
+#include "MediaCodecReader.h"
+#include "MediaDecoderStateMachine.h"
+
+namespace mozilla {
+
+MediaDecoder*
+MediaCodecDecoder::Clone()
+{
+  return new MediaCodecDecoder();
+}
+
+MediaDecoderStateMachine*
+MediaCodecDecoder::CreateStateMachine()
+{
+  return new MediaDecoderStateMachine(this, new MediaCodecReader(this));
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/omx/MediaCodecDecoder.h
@@ -0,0 +1,26 @@
+/* -*- 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 MEDIA_CODEC_DECODER_H
+#define MEDIA_CODEC_DECODER_H
+
+#include "MediaDecoder.h"
+
+namespace mozilla {
+
+// MediaDecoder that uses MediaCodecReader.
+class MediaCodecDecoder : public MediaDecoder
+{
+public:
+
+  virtual MediaDecoder* Clone();
+
+  virtual MediaDecoderStateMachine* CreateStateMachine();
+};
+
+} // namespace mozilla
+
+#endif // MEDIA_CODEC_DECODER_H
new file mode 100644
--- /dev/null
+++ b/content/media/omx/MediaCodecReader.cpp
@@ -0,0 +1,1218 @@
+/* -*- 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 "MediaCodecReader.h"
+
+#include <OMX_IVCommon.h>
+
+#include <gui/Surface.h>
+#include <ICrypto.h>
+
+#include <stagefright/foundation/ABuffer.h>
+#include <stagefright/foundation/ADebug.h>
+#include <stagefright/foundation/ALooper.h>
+#include <stagefright/foundation/AMessage.h>
+#include <stagefright/MediaBuffer.h>
+#include <stagefright/MediaCodec.h>
+#include <stagefright/MediaExtractor.h>
+#include <stagefright/MediaSource.h>
+#include <stagefright/MetaData.h>
+#include <stagefright/Utils.h>
+
+#include "mozilla/TimeStamp.h"
+
+#include "gfx2DGlue.h"
+
+#include "MediaStreamSource.h"
+#include "ImageContainer.h"
+#include "VideoFrameContainer.h"
+
+using namespace android;
+
+namespace mozilla {
+
+enum {
+  kNotifyCodecReserved = 'core',
+  kNotifyCodecCanceled = 'coca',
+};
+
+static const int64_t sInvalidDurationUs = INT64_C(-1);
+static const int64_t sInvalidTimestampUs = INT64_C(-1);
+
+// Try not to spend more than this much time (in seconds) in a single call to DecodeAudioData.
+static const double sMaxAudioDecodeDurationS = 0.1;
+// Try not to spend more than this much time (in seconds) in a single call to DecodeVideoFrame.
+static const double sMaxVideoDecodeDurationS = 0.1;
+
+static CheckedUint32 sInvalidInputIndex = INT32_C(-1);
+
+inline bool
+IsValidDurationUs(int64_t aDuration)
+{
+  return aDuration >= INT64_C(0);
+}
+
+inline bool
+IsValidTimestampUs(int64_t aTimestamp)
+{
+  return aTimestamp >= INT64_C(0);
+}
+
+MediaCodecReader::MessageHandler::MessageHandler(MediaCodecReader *aReader)
+  : mReader(aReader)
+{
+}
+
+MediaCodecReader::MessageHandler::~MessageHandler()
+{
+  mReader = nullptr;
+}
+
+void
+MediaCodecReader::MessageHandler::onMessageReceived(const android::sp<android::AMessage> &aMessage)
+{
+  if (mReader != nullptr) {
+    mReader->onMessageReceived(aMessage);
+  }
+}
+
+MediaCodecReader::VideoResourceListener::VideoResourceListener(MediaCodecReader *aReader)
+  : mReader(aReader)
+{
+}
+
+MediaCodecReader::VideoResourceListener::~VideoResourceListener()
+{
+  mReader = nullptr;
+}
+
+void
+MediaCodecReader::VideoResourceListener::codecReserved()
+{
+  if (mReader != nullptr) {
+    mReader->codecReserved(mReader->mVideoTrack);
+  }
+}
+
+void
+MediaCodecReader::VideoResourceListener::codecCanceled()
+{
+  if (mReader != nullptr) {
+    mReader->codecCanceled(mReader->mVideoTrack);
+  }
+}
+
+MediaCodecReader::Track::Track()
+  : mDurationUs(INT64_C(0))
+  , mInputIndex(sInvalidInputIndex)
+  , mEndOfStream(false)
+  , mSeekTimeUs(sInvalidTimestampUs)
+  , mFlushed(false)
+{
+}
+
+MediaCodecReader::AudioTrack::AudioTrack()
+{
+}
+
+MediaCodecReader::VideoTrack::VideoTrack()
+  : mWidth(0)
+  , mHeight(0)
+  , mStride(0)
+  , mSliceHeight(0)
+  , mColorFormat(0)
+  , mRotation(0)
+{
+}
+
+MediaCodecReader::CodecBufferInfo::CodecBufferInfo()
+  : mIndex(0)
+  , mOffset(0)
+  , mSize(0)
+  , mTimeUs(0)
+  , mFlags(0)
+{
+}
+
+MediaCodecReader::MediaCodecReader(AbstractMediaDecoder* aDecoder)
+  : MediaDecoderReader(aDecoder)
+  , mColorConverterBufferSize(0)
+{
+  mHandler = new MessageHandler(this);
+  mVideoListener = new VideoResourceListener(this);
+}
+
+MediaCodecReader::~MediaCodecReader()
+{
+  MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
+}
+
+nsresult
+MediaCodecReader::Init(MediaDecoderReader* aCloneDonor)
+{
+  return NS_OK;
+}
+
+bool
+MediaCodecReader::IsWaitingMediaResources()
+{
+  return mVideoTrack.mCodec != nullptr && !mVideoTrack.mCodec->allocated();
+}
+
+bool
+MediaCodecReader::IsDormantNeeded()
+{
+  return mVideoTrack.mCodec != nullptr;
+}
+
+void
+MediaCodecReader::ReleaseMediaResources()
+{
+  ReleaseCriticalResources();
+}
+
+void
+MediaCodecReader::Shutdown()
+{
+  ReleaseResources();
+}
+
+bool
+MediaCodecReader::DecodeAudioData()
+{
+  MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread.");
+
+  if (mAudioTrack.mCodec == nullptr || !mAudioTrack.mCodec->allocated()) {
+    return false;
+  }
+
+  // Get one audio output data from MediaCodec
+  CodecBufferInfo bufferInfo;
+  TimeStamp timeout = TimeStamp::Now() + TimeDuration::FromSeconds(sMaxAudioDecodeDurationS);
+  while (true) {
+    if (timeout < TimeStamp::Now()) {
+      return true; // Try it again later.
+    }
+    status_t status = GetCodecOutputData(mAudioTrack, bufferInfo, sInvalidTimestampUs, timeout);
+    if (status == OK) {
+      break;
+    } else if (status == -EAGAIN) {
+      return true; // Try it again later.
+    } else if (status == INFO_FORMAT_CHANGED) {
+      if (UpdateAudioInfo()) {
+        continue; // Try it again now.
+      } else {
+        return false;
+      }
+    } else {
+      return false;
+    }
+  }
+
+  bool result = true;
+
+  if (bufferInfo.mBuffer != nullptr && bufferInfo.mSize > 0 && bufferInfo.mBuffer->data() != nullptr) {
+    // This is the approximate byte position in the stream.
+    int64_t pos = mDecoder->GetResource()->Tell();
+
+    uint32_t frames = bufferInfo.mSize / (mInfo.mAudio.mChannels * sizeof(AudioDataValue));
+
+    result = mAudioCompactor.Push(
+        pos,
+        bufferInfo.mTimeUs,
+        mInfo.mAudio.mRate,
+        frames,
+        mInfo.mAudio.mChannels,
+        AudioCompactor::NativeCopy(
+            bufferInfo.mBuffer->data() + bufferInfo.mOffset,
+            bufferInfo.mSize,
+            mInfo.mAudio.mChannels));
+  }
+
+  mAudioTrack.mCodec->releaseOutputBuffer(bufferInfo.mIndex);
+
+  return result;
+}
+
+bool
+MediaCodecReader::DecodeVideoFrame(bool &aKeyframeSkip, int64_t aTimeThreshold)
+{
+  MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread.");
+
+  if (mVideoTrack.mCodec == nullptr || !mVideoTrack.mCodec->allocated()) {
+    return false;
+  }
+
+  int64_t threshold = sInvalidTimestampUs;
+  if (aKeyframeSkip && IsValidTimestampUs(aTimeThreshold)) {
+    threshold = aTimeThreshold;
+  }
+
+  // Get one video output data from MediaCodec
+  CodecBufferInfo bufferInfo;
+  TimeStamp timeout = TimeStamp::Now() + TimeDuration::FromSeconds(sMaxVideoDecodeDurationS);
+  while (true) {
+    if (timeout < TimeStamp::Now()) {
+      return true; // Try it again later.
+    }
+    status_t status = GetCodecOutputData(mVideoTrack, bufferInfo, threshold, timeout);
+    if (status == OK) {
+      break;
+    } else if (status == -EAGAIN) {
+      return true; // Try it again later.
+    } else if (status == INFO_FORMAT_CHANGED) {
+      if (UpdateVideoInfo()) {
+        continue; // Try it again now.
+      } else {
+        return false;
+      }
+    } else {
+      return false;
+    }
+  }
+
+  bool result = true;
+
+  if (bufferInfo.mBuffer != nullptr && bufferInfo.mSize > 0 && bufferInfo.mBuffer->data() != nullptr) {
+    uint8_t *yuv420p_buffer = bufferInfo.mBuffer->data();
+    int32_t stride = mVideoTrack.mStride;
+    int32_t slice_height = mVideoTrack.mSliceHeight;
+
+    // Converts to OMX_COLOR_FormatYUV420Planar
+    if (mVideoTrack.mColorFormat != OMX_COLOR_FormatYUV420Planar) {
+      ARect crop;
+      crop.top = 0;
+      crop.bottom = mVideoTrack.mHeight;
+      crop.left = 0;
+      crop.right = mVideoTrack.mWidth;
+
+      yuv420p_buffer = GetColorConverterBuffer(mVideoTrack.mWidth, mVideoTrack.mHeight);
+      if (mColorConverter.convertDecoderOutputToI420(
+          bufferInfo.mBuffer->data(), mVideoTrack.mWidth, mVideoTrack.mHeight, crop, yuv420p_buffer) != OK) {
+        mVideoTrack.mCodec->releaseOutputBuffer(bufferInfo.mIndex);
+        NS_WARNING("Unable to convert color format");
+        return false;
+      }
+
+      stride = mVideoTrack.mWidth;
+      slice_height = mVideoTrack.mHeight;
+    }
+
+    size_t yuv420p_y_size = stride * slice_height;
+    size_t yuv420p_u_size = ((stride + 1) / 2) * ((slice_height + 1) / 2);
+    uint8_t *yuv420p_y = yuv420p_buffer;
+    uint8_t *yuv420p_u = yuv420p_y + yuv420p_y_size;
+    uint8_t *yuv420p_v = yuv420p_u + yuv420p_u_size;
+
+    // This is the approximate byte position in the stream.
+    int64_t pos = mDecoder->GetResource()->Tell();
+
+    VideoData::YCbCrBuffer b;
+    b.mPlanes[0].mData = yuv420p_y;
+    b.mPlanes[0].mWidth = mVideoTrack.mWidth;
+    b.mPlanes[0].mHeight = mVideoTrack.mHeight;
+    b.mPlanes[0].mStride = stride;
+    b.mPlanes[0].mOffset = 0;
+    b.mPlanes[0].mSkip = 0;
+
+    b.mPlanes[1].mData = yuv420p_u;
+    b.mPlanes[1].mWidth = (mVideoTrack.mWidth + 1) / 2;
+    b.mPlanes[1].mHeight = (mVideoTrack.mHeight + 1) / 2;
+    b.mPlanes[1].mStride = (stride + 1) / 2;
+    b.mPlanes[1].mOffset = 0;
+    b.mPlanes[1].mSkip = 0;
+
+    b.mPlanes[2].mData = yuv420p_v;
+    b.mPlanes[2].mWidth =(mVideoTrack.mWidth + 1) / 2;
+    b.mPlanes[2].mHeight = (mVideoTrack.mHeight + 1) / 2;
+    b.mPlanes[2].mStride = (stride + 1) / 2;
+    b.mPlanes[2].mOffset = 0;
+    b.mPlanes[2].mSkip = 0;
+
+    VideoData *v = VideoData::Create(
+        mInfo.mVideo,
+        mDecoder->GetImageContainer(),
+        pos,
+        bufferInfo.mTimeUs,
+        1, // We don't know the duration.
+        b,
+        bufferInfo.mFlags & MediaCodec::BUFFER_FLAG_SYNCFRAME,
+        -1,
+        mVideoTrack.mRelativePictureRect);
+
+    if (v != nullptr) {
+      result = true;
+      mVideoQueue.Push(v);
+      aKeyframeSkip = false;
+    } else {
+      NS_WARNING("Unable to create VideoData");
+    }
+  }
+
+  mVideoTrack.mCodec->releaseOutputBuffer(bufferInfo.mIndex);
+
+  return result;
+}
+
+bool
+MediaCodecReader::HasAudio()
+{
+  return mInfo.mAudio.mHasAudio;
+}
+
+bool
+MediaCodecReader::HasVideo()
+{
+  return mInfo.mVideo.mHasVideo;
+}
+
+nsresult
+MediaCodecReader::ReadMetadata(MediaInfo* aInfo,
+                               MetadataTags** aTags)
+{
+  MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread.");
+
+  if (!ReallocateResources()) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (IsWaitingMediaResources()) {
+    return NS_OK;
+  }
+
+  // TODO: start streaming
+
+  if (!UpdateDuration()) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (!UpdateAudioInfo()) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (!UpdateVideoInfo()) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // Set the total duration (the max of the audio and video track).
+  int64_t duration = mAudioTrack.mDurationUs > mVideoTrack.mDurationUs
+      ? mAudioTrack.mDurationUs
+      : mVideoTrack.mDurationUs;
+  if (duration >= 0LL) {
+    ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
+    mDecoder->SetMediaDuration(duration);
+  }
+
+  // Video track's frame sizes will not overflow. Activate the video track.
+  VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
+  if (container) {
+    container->SetCurrentFrame(
+        gfxIntSize(mInfo.mVideo.mDisplay.width, mInfo.mVideo.mDisplay.height),
+        nullptr,
+        mozilla::TimeStamp::Now());
+  }
+
+  *aInfo = mInfo;
+  *aTags = nullptr;
+
+  return NS_OK;
+}
+
+nsresult
+MediaCodecReader::Seek(int64_t aTime,
+                       int64_t aStartTime,
+                       int64_t aEndTime,
+                       int64_t aCurrentTime)
+{
+  MOZ_ASSERT(mDecoder->OnDecodeThread(), "Should be on decode thread.");
+
+  VideoFrameContainer* videoframe = mDecoder->GetVideoFrameContainer();
+  if (videoframe != nullptr) {
+    mozilla::layers::ImageContainer *image = videoframe->GetImageContainer();
+    if (image != nullptr) {
+      image->ClearAllImagesExceptFront();
+    }
+  }
+
+  mAudioTrack.mEndOfStream = false;
+  mVideoTrack.mEndOfStream = false;
+
+  mAudioTrack.mSeekTimeUs = aTime;
+  mVideoTrack.mSeekTimeUs = aTime;
+
+  mAudioTrack.mFlushed = false;
+  mVideoTrack.mFlushed = false;
+
+  // Regulate the seek time to the closest sync point of video data.
+  if (HasVideo() && mVideoTrack.mSource != nullptr) {
+    MediaBuffer *source_buffer = nullptr;
+    MediaSource::ReadOptions options;
+    options.setSeekTo(aTime, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
+    if (mVideoTrack.mSource->read(&source_buffer, &options) != OK || source_buffer == nullptr) {
+      return NS_ERROR_FAILURE;
+    }
+    sp<MetaData> format = source_buffer->meta_data();
+    if (format != nullptr) {
+      int64_t timestamp = sInvalidTimestampUs;
+      if (format->findInt64(kKeyTime, &timestamp) && IsValidTimestampUs(timestamp)) {
+        mAudioTrack.mSeekTimeUs = timestamp;
+        mVideoTrack.mSeekTimeUs = timestamp;
+      }
+      format = nullptr;
+    }
+    source_buffer->release();
+  }
+
+  return NS_OK;
+}
+
+bool
+MediaCodecReader::IsMediaSeekable()
+{
+  // Check the MediaExtract flag if the source is seekable.
+  return (mExtractor != nullptr) && (mExtractor->flags() & MediaExtractor::CAN_SEEK);
+}
+
+bool
+MediaCodecReader::ReallocateResources()
+{
+  if (CreateLooper() &&
+      CreateExtractor() &&
+      CreateMediaSources() &&
+      CreateMediaCodecs()) {
+    return true;
+  }
+
+  ReleaseResources();
+  return false;
+}
+
+void
+MediaCodecReader::ReleaseCriticalResources()
+{
+  ResetDecode();
+  // Before freeing a video codec, all video buffers needed to be released
+  // even from graphics pipeline.
+  VideoFrameContainer* videoframe = mDecoder->GetVideoFrameContainer();
+  if (videoframe != nullptr) {
+    videoframe->ClearCurrentFrame();
+  }
+
+  DestroyMediaCodecs();
+
+  ClearColorConverterBuffer();
+}
+
+void
+MediaCodecReader::ReleaseResources()
+{
+  ReleaseCriticalResources();
+  DestroyMediaSources();
+  DestroyExtractor();
+  DestroyLooper();
+}
+
+bool
+MediaCodecReader::CreateLooper()
+{
+  if (mLooper != nullptr) {
+    return true;
+  }
+
+  // Create ALooper
+  mLooper = new ALooper;
+  mLooper->setName("MediaCodecReader");
+
+  // Register AMessage handler to ALooper.
+  mLooper->registerHandler(mHandler);
+
+  // Start ALooper thread.
+  if (mLooper->start() != OK) {
+    return false;
+  }
+
+  return true;
+}
+
+void
+MediaCodecReader::DestroyLooper()
+{
+  if (mLooper == nullptr) {
+    return;
+  }
+
+  // Unregister AMessage handler from ALooper.
+  if (mHandler != nullptr) {
+    mLooper->unregisterHandler(mHandler->id());
+  }
+
+  // Stop ALooper thread.
+  mLooper->stop();
+
+  // Clear ALooper
+  mLooper = nullptr;
+}
+
+bool
+MediaCodecReader::CreateExtractor()
+{
+  if (mExtractor != nullptr) {
+    return true;
+  }
+
+  //register sniffers, if they are not registered in this process.
+  DataSource::RegisterDefaultSniffers();
+
+  if (mExtractor == nullptr) {
+    sp<DataSource> dataSource = new MediaStreamSource(mDecoder->GetResource());
+
+    if (dataSource->initCheck() != OK) {
+      return false;
+    }
+
+    mExtractor = MediaExtractor::Create(dataSource);
+  }
+
+  return mExtractor != nullptr;
+}
+
+void
+MediaCodecReader::DestroyExtractor()
+{
+  mExtractor = nullptr;
+}
+
+bool
+MediaCodecReader::CreateMediaSources()
+{
+  if (mExtractor == nullptr) {
+    return false;
+  }
+
+  sp<MetaData> extractorMetaData = mExtractor->getMetaData();
+  // TODO: Check MP3 file format
+
+  const ssize_t invalidTrackIndex = -1;
+  ssize_t audioTrackIndex = invalidTrackIndex;
+  ssize_t videoTrackIndex = invalidTrackIndex;
+
+  for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
+    sp<MetaData> trackFormat = mExtractor->getTrackMetaData(i);
+
+    const char *mime;
+    if (!trackFormat->findCString(kKeyMIMEType, &mime)) {
+      continue;
+    }
+
+    if (audioTrackIndex == invalidTrackIndex &&
+        !strncasecmp(mime, "audio/", 6)) {
+      audioTrackIndex = i;
+    } else if (videoTrackIndex == invalidTrackIndex &&
+               !strncasecmp(mime, "video/", 6)) {
+      videoTrackIndex = i;
+    }
+  }
+
+  if (audioTrackIndex == invalidTrackIndex &&
+      videoTrackIndex == invalidTrackIndex) {
+    NS_WARNING("OMX decoder could not find audio or video tracks");
+    return false;
+  }
+
+  if (audioTrackIndex != invalidTrackIndex && mAudioTrack.mSource == nullptr) {
+    sp<MediaSource> audioSource = mExtractor->getTrack(audioTrackIndex);
+    if (audioSource != nullptr && audioSource->start() == OK) {
+      mAudioTrack.mSource = audioSource;
+    }
+  }
+
+  if (videoTrackIndex != invalidTrackIndex && mVideoTrack.mSource == nullptr) {
+    sp<MediaSource> videoSource = mExtractor->getTrack(videoTrackIndex);
+    if (videoSource != nullptr && videoSource->start() == OK) {
+      mVideoTrack.mSource = videoSource;
+    }
+  }
+
+  return
+      (audioTrackIndex == invalidTrackIndex || mAudioTrack.mSource != nullptr) &&
+      (videoTrackIndex == invalidTrackIndex || mVideoTrack.mSource != nullptr);
+}
+
+void
+MediaCodecReader::DestroyMediaSources()
+{
+  mAudioTrack.mSource = nullptr;
+  mVideoTrack.mSource = nullptr;
+}
+
+bool
+MediaCodecReader::CreateMediaCodecs()
+{
+  if (CreateMediaCodec(mLooper, mAudioTrack, false, nullptr) &&
+      CreateMediaCodec(mLooper, mVideoTrack, true, mVideoListener)) {
+    return true;
+  }
+
+  return false;
+}
+
+bool
+MediaCodecReader::CreateMediaCodec(sp<ALooper> &aLooper,
+                                   Track &aTrack,
+                                   bool aAsync,
+                                   wp<MediaCodecProxy::CodecResourceListener> aListener)
+{
+  if (aTrack.mSource != nullptr && aTrack.mCodec == nullptr) {
+    sp<MetaData> sourceFormat = aTrack.mSource->getFormat();
+
+    const char *mime;
+    if (sourceFormat->findCString(kKeyMIMEType, &mime)) {
+      aTrack.mCodec = MediaCodecProxy::CreateByType(aLooper, mime, false, aAsync, aListener);
+    }
+
+    if (aTrack.mCodec == nullptr) {
+      NS_WARNING("Couldn't create MediaCodecProxy");
+      return false;
+    }
+
+    if (!aAsync) {
+      // Pending configure() and start() to codecReserved() if the creation
+      // should be asynchronous.
+      if (!aTrack.mCodec->allocated() || !ConfigureMediaCodec(aTrack)){
+        NS_WARNING("Couldn't create and configure MediaCodec synchronously");
+        aTrack.mCodec = nullptr;
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
+bool
+MediaCodecReader::ConfigureMediaCodec(Track &aTrack)
+{
+
+  if (aTrack.mSource != nullptr && aTrack.mCodec != nullptr) {
+    if (!aTrack.mCodec->allocated()) {
+      return false;
+    }
+
+    sp<MetaData> sourceFormat = aTrack.mSource->getFormat();
+    sp<AMessage> codecFormat;
+    convertMetaDataToMessage(sourceFormat, &codecFormat);
+
+    bool allpass = true;
+    if (allpass && aTrack.mCodec->configure(codecFormat, nullptr, nullptr, 0) != OK) {
+      NS_WARNING("Couldn't configure MediaCodec");
+      allpass = false;
+    }
+    if (allpass && aTrack.mCodec->start() != OK) {
+      NS_WARNING("Couldn't start MediaCodec");
+      allpass = false;
+    }
+    if (allpass && aTrack.mCodec->getInputBuffers(&aTrack.mInputBuffers) != OK) {
+      NS_WARNING("Couldn't get input buffers from MediaCodec");
+      allpass = false;
+    }
+    if (allpass && aTrack.mCodec->getOutputBuffers(&aTrack.mOutputBuffers) != OK) {
+      NS_WARNING("Couldn't get output buffers from MediaCodec");
+      allpass = false;
+    }
+    if (!allpass) {
+      aTrack.mCodec = nullptr;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void
+MediaCodecReader::DestroyMediaCodecs()
+{
+  DestroyMediaCodecs(mAudioTrack);
+  DestroyMediaCodecs(mVideoTrack);
+}
+
+void
+MediaCodecReader::DestroyMediaCodecs(Track &aTrack)
+{
+  aTrack.mCodec = nullptr;
+}
+
+bool
+MediaCodecReader::UpdateDuration()
+{
+  // read audio duration
+  if (mAudioTrack.mSource != nullptr) {
+    sp<MetaData> audioFormat = mAudioTrack.mSource->getFormat();
+    if (audioFormat != nullptr) {
+      int64_t audioDurationUs = 0LL;
+      if (audioFormat->findInt64(kKeyDuration, &audioDurationUs) &&
+          audioDurationUs > mAudioTrack.mDurationUs) {
+        mAudioTrack.mDurationUs = audioDurationUs;
+      }
+    }
+  }
+  // TODO: MP3 file duration
+
+  // read video duration
+  if (mVideoTrack.mSource != nullptr) {
+    sp<MetaData> videoFormat = mVideoTrack.mSource->getFormat();
+    if (videoFormat != nullptr) {
+      int64_t videoDurationUs = 0LL;
+      if (videoFormat->findInt64(kKeyDuration, &videoDurationUs) &&
+          videoDurationUs > mVideoTrack.mDurationUs) {
+        mVideoTrack.mDurationUs = videoDurationUs;
+      }
+    }
+  }
+
+  return true;
+}
+
+bool
+MediaCodecReader::UpdateAudioInfo()
+{
+  if (mAudioTrack.mSource == nullptr && mAudioTrack.mCodec == nullptr) {
+    // No needs to update AudioInfo if no audio streams.
+    return true;
+  }
+
+  if (mAudioTrack.mSource == nullptr || mAudioTrack.mCodec == nullptr || !mAudioTrack.mCodec->allocated()) {
+    // Something wrong.
+    MOZ_ASSERT(mAudioTrack.mSource != nullptr, "mAudioTrack.mSource should not be nullptr");
+    MOZ_ASSERT(mAudioTrack.mCodec != nullptr, "mAudioTrack.mCodec should not be nullptr");
+    MOZ_ASSERT(mAudioTrack.mCodec->allocated(), "mAudioTrack.mCodec->allocated() should not be false");
+    return false;
+  }
+
+  // read audio metadata from MediaSource
+  sp<MetaData> audioSourceFormat = mAudioTrack.mSource->getFormat();
+  if (audioSourceFormat == nullptr) {
+    return false;
+  }
+
+  // ensure audio metadata from MediaCodec has been parsed
+  if (!EnsureCodecFormatParsed(mAudioTrack)){
+    return false;
+  }
+
+  // read audio metadata from MediaCodec
+  sp<AMessage> audioCodecFormat;
+  if (mAudioTrack.mCodec->getOutputFormat(&audioCodecFormat) != OK || audioCodecFormat == nullptr) {
+    return false;
+  }
+
+  AString codec_mime;
+  int32_t codec_channel_count = 0;
+  int32_t codec_sample_rate = 0;
+  if (!audioCodecFormat->findString("mime", &codec_mime) ||
+      !audioCodecFormat->findInt32("channel-count", &codec_channel_count) ||
+      !audioCodecFormat->findInt32("sample-rate", &codec_sample_rate)) {
+    return false;
+  }
+
+  // Update AudioInfo
+  mInfo.mAudio.mHasAudio = true;
+  mInfo.mAudio.mChannels = codec_channel_count;
+  mInfo.mAudio.mRate = codec_sample_rate;
+
+  return true;
+}
+
+bool
+MediaCodecReader::UpdateVideoInfo()
+{
+  if (mVideoTrack.mSource == nullptr && mVideoTrack.mCodec == nullptr) {
+    // No needs to update VideoInfo if no video streams.
+    return true;
+  }
+
+  if (mVideoTrack.mSource == nullptr || mVideoTrack.mCodec == nullptr || !mVideoTrack.mCodec->allocated()) {
+    // Something wrong.
+    MOZ_ASSERT(mVideoTrack.mSource != nullptr, "mVideoTrack.mSource should not be nullptr");
+    MOZ_ASSERT(mVideoTrack.mCodec != nullptr, "mVideoTrack.mCodec should not be nullptr");
+    MOZ_ASSERT(mVideoTrack.mCodec->allocated(), "mVideoTrack.mCodec->allocated() should not be false");
+    return false;
+  }
+
+  // read video metadata from MediaSource
+  sp<MetaData> videoSourceFormat = mVideoTrack.mSource->getFormat();
+  if (videoSourceFormat == nullptr) {
+    return false;
+  }
+  int32_t container_width = 0;
+  int32_t container_height = 0;
+  int32_t container_rotation = 0;
+  if (!videoSourceFormat->findInt32(kKeyWidth, &container_width) ||
+      !videoSourceFormat->findInt32(kKeyHeight, &container_height)) {
+    return false;
+  }
+  mVideoTrack.mFrameSize = nsIntSize(container_width, container_height);
+  if (videoSourceFormat->findInt32(kKeyRotation, &container_rotation)) {
+    mVideoTrack.mRotation = container_rotation;
+  }
+
+  // ensure video metadata from MediaCodec has been parsed
+  if (!EnsureCodecFormatParsed(mVideoTrack)){
+    return false;
+  }
+
+  // read video metadata from MediaCodec
+  sp<AMessage> videoCodecFormat;
+  if (mVideoTrack.mCodec->getOutputFormat(&videoCodecFormat) != OK || videoCodecFormat == nullptr) {
+    return false;
+  }
+  AString codec_mime;
+  int32_t codec_width = 0;
+  int32_t codec_height = 0;
+  int32_t codec_stride = 0;
+  int32_t codec_slice_height = 0;
+  int32_t codec_color_format = 0;
+  int32_t codec_crop_left = 0;
+  int32_t codec_crop_top = 0;
+  int32_t codec_crop_right = 0;
+  int32_t codec_crop_bottom = 0;
+  if (!videoCodecFormat->findString("mime", &codec_mime) ||
+      !videoCodecFormat->findInt32("width", &codec_width) ||
+      !videoCodecFormat->findInt32("height", &codec_height) ||
+      !videoCodecFormat->findInt32("stride", &codec_stride) ||
+      !videoCodecFormat->findInt32("slice-height", &codec_slice_height) ||
+      !videoCodecFormat->findInt32("color-format", &codec_color_format) ||
+      !videoCodecFormat->findRect("crop", &codec_crop_left, &codec_crop_top, &codec_crop_right, &codec_crop_bottom)) {
+    return false;
+  }
+
+  mVideoTrack.mWidth = codec_width;
+  mVideoTrack.mHeight = codec_height;
+  mVideoTrack.mStride = codec_stride;
+  mVideoTrack.mSliceHeight = codec_slice_height;
+  mVideoTrack.mColorFormat = codec_color_format;
+
+  // Validate the container-reported frame and pictureRect sizes. This ensures
+  // that our video frame creation code doesn't overflow.
+  int32_t display_width = codec_crop_right - codec_crop_left + 1;
+  int32_t display_height = codec_crop_bottom - codec_crop_top + 1;
+  nsIntRect picture_rect(0, 0, mVideoTrack.mWidth, mVideoTrack.mHeight);
+  nsIntSize display_size(display_width, display_height);
+  if (!IsValidVideoRegion(mVideoTrack.mFrameSize, picture_rect, display_size)) {
+    return false;
+  }
+
+  // Relative picture size
+  gfx::IntRect relative_picture_rect = gfx::ToIntRect(picture_rect);
+  if (mVideoTrack.mWidth != mVideoTrack.mFrameSize.width ||
+      mVideoTrack.mHeight != mVideoTrack.mFrameSize.height) {
+    // Frame size is different from what the container reports. This is legal,
+    // and we will preserve the ratio of the crop rectangle as it
+    // was reported relative to the picture size reported by the container.
+    relative_picture_rect.x = (picture_rect.x * mVideoTrack.mWidth) / mVideoTrack.mFrameSize.width;
+    relative_picture_rect.y = (picture_rect.y * mVideoTrack.mHeight) / mVideoTrack.mFrameSize.height;
+    relative_picture_rect.width = (picture_rect.width * mVideoTrack.mWidth) / mVideoTrack.mFrameSize.width;
+    relative_picture_rect.height = (picture_rect.height * mVideoTrack.mHeight) / mVideoTrack.mFrameSize.height;
+  }
+
+  // Update VideoInfo
+  mInfo.mVideo.mHasVideo = true;
+  mVideoTrack.mPictureRect = picture_rect;
+  mInfo.mVideo.mDisplay = display_size;
+  mVideoTrack.mRelativePictureRect = relative_picture_rect;
+
+  return true;
+}
+
+status_t
+MediaCodecReader::FlushCodecData(Track &aTrack)
+{
+  if (aTrack.mSource == nullptr || aTrack.mCodec == nullptr || !aTrack.mCodec->allocated()) {
+    return UNKNOWN_ERROR;
+  }
+
+  status_t status = aTrack.mCodec->flush();
+  aTrack.mFlushed = (status == OK);
+  if (aTrack.mFlushed) {
+    aTrack.mInputIndex = sInvalidInputIndex;
+  }
+
+  return status;
+}
+
+// Keep filling data if there are available buffers.
+// FIXME: change to non-blocking read
+status_t
+MediaCodecReader::FillCodecInputData(Track &aTrack)
+{
+  if (aTrack.mSource == nullptr || aTrack.mCodec == nullptr || !aTrack.mCodec->allocated()) {
+    return UNKNOWN_ERROR;
+  }
+
+  if (aTrack.mEndOfStream) {
+    return ERROR_END_OF_STREAM;
+  }
+
+  if (IsValidTimestampUs(aTrack.mSeekTimeUs) && !aTrack.mFlushed) {
+    FlushCodecData(aTrack);
+  }
+
+  size_t index = 0;
+  while (aTrack.mInputIndex.isValid() || aTrack.mCodec->dequeueInputBuffer(&index) == OK) {
+    if (!aTrack.mInputIndex.isValid()) {
+      aTrack.mInputIndex = index;
+    }
+    MOZ_ASSERT(aTrack.mInputIndex.isValid(), "aElement.mInputIndex should be valid");
+
+    MediaBuffer *source_buffer = nullptr;
+    status_t status = OK;
+    if (IsValidTimestampUs(aTrack.mSeekTimeUs)) {
+      MediaSource::ReadOptions options;
+      options.setSeekTo(aTrack.mSeekTimeUs);
+      status = aTrack.mSource->read(&source_buffer, &options);
+    } else {
+      status = aTrack.mSource->read(&source_buffer);
+    }
+
+    // read() fails
+    if (status == INFO_FORMAT_CHANGED) {
+      return INFO_FORMAT_CHANGED;
+    } else if (status == ERROR_END_OF_STREAM) {
+      aTrack.mEndOfStream = true;
+      aTrack.mCodec->signalEndOfInputStream();
+      return ERROR_END_OF_STREAM;
+    } else if (status == -ETIMEDOUT) {
+      return OK; // try it later
+    } else if (status != OK) {
+      return status;
+    } else if (source_buffer == nullptr) {
+      return UNKNOWN_ERROR;
+    }
+
+    // read() successes
+    aTrack.mEndOfStream = false;
+    aTrack.mSeekTimeUs = sInvalidTimestampUs;
+
+    sp<ABuffer> input_buffer = nullptr;
+    if (aTrack.mInputIndex.value() < aTrack.mInputBuffers.size()) {
+      input_buffer = aTrack.mInputBuffers[aTrack.mInputIndex.value()];
+    }
+    if (input_buffer != nullptr && input_buffer->capacity() >= source_buffer->range_length()) {
+      input_buffer->setRange(0, source_buffer->range_length());
+      memcpy((uint8_t *)input_buffer->data() + input_buffer->offset(),
+          (uint8_t *)source_buffer->data() + source_buffer->range_offset(),
+          source_buffer->range_length());
+
+      int64_t timestamp = sInvalidTimestampUs;
+      sp<MetaData> codec_format = source_buffer->meta_data();
+      if (codec_format != nullptr) {
+        codec_format->findInt64(kKeyTime, &timestamp);
+      }
+
+      status = aTrack.mCodec->queueInputBuffer(
+          aTrack.mInputIndex.value(), input_buffer->offset(), input_buffer->size(), timestamp, 0);
+      if (status == OK) {
+        aTrack.mInputIndex = sInvalidInputIndex;
+      }
+    }
+    source_buffer->release();
+
+    if (status != OK) {
+      return status;
+    }
+  }
+
+  return OK;
+}
+
+status_t
+MediaCodecReader::GetCodecOutputData(Track &aTrack,
+                                     CodecBufferInfo &aBuffer,
+                                     int64_t aThreshold,
+                                     const TimeStamp &aTimeout)
+{
+  // Read next frame.
+  CodecBufferInfo info;
+
+  // Try to fill more input buffers and then get one output buffer.
+  // FIXME: use callback from MediaCodec
+  status_t status = FillCodecInputData(aTrack);
+  int64_t duration = (int64_t)(aTimeout - TimeStamp::Now()).ToMicroseconds();
+  if (!IsValidDurationUs(duration)) {
+    return -EAGAIN;
+  }
+  if (status == OK) {
+    status = aTrack.mCodec->dequeueOutputBuffer(
+        &info.mIndex, &info.mOffset, &info.mSize, &info.mTimeUs, &info.mFlags, duration);
+  }
+
+  while (status == OK || status == INFO_OUTPUT_BUFFERS_CHANGED || status == -EAGAIN) {
+    if (status == OK) {
+      if (!IsValidTimestampUs(aThreshold) || info.mTimeUs >= aThreshold) {
+        // Get a valid output buffer.
+        break;
+      } else {
+        aTrack.mCodec->releaseOutputBuffer(info.mIndex);
+      }
+    } else if (status == INFO_OUTPUT_BUFFERS_CHANGED) {
+      // Update output buffers of MediaCodec.
+      if (aTrack.mCodec->getOutputBuffers(&aTrack.mOutputBuffers) != OK) {
+        NS_WARNING("Couldn't get output buffers from MediaCodec");
+        aTrack.mCodec = nullptr;
+        return UNKNOWN_ERROR;
+      }
+    }
+
+    if (TimeStamp::Now() > aTimeout) {
+      // Don't let this loop run for too long. Try it again later.
+      return -EAGAIN;
+    }
+
+    // FIXME: use callback from MediaCodec
+    status = FillCodecInputData(aTrack);
+    if (status == INFO_OUTPUT_BUFFERS_CHANGED) {
+      continue;
+    } else if (status != OK) {
+      return status;
+    }
+
+    duration = (int64_t)(aTimeout - TimeStamp::Now()).ToMicroseconds();
+    if (!IsValidDurationUs(duration)) {
+      return -EAGAIN;
+    }
+    status = aTrack.mCodec->dequeueOutputBuffer(
+        &info.mIndex, &info.mOffset, &info.mSize, &info.mTimeUs, &info.mFlags, duration);
+  }
+
+  if (status != OK) {
+    // Something wrong.
+    return status;
+  }
+
+  if (info.mIndex >= aTrack.mOutputBuffers.size()) {
+    NS_WARNING("Couldn't get proper index of output buffers from MediaCodec");
+    aTrack.mCodec->releaseOutputBuffer(info.mIndex);
+    return UNKNOWN_ERROR;
+  }
+
+  aBuffer = info;
+  aBuffer.mBuffer = aTrack.mOutputBuffers[info.mIndex];
+
+  return OK;
+}
+
+bool
+MediaCodecReader::EnsureCodecFormatParsed(Track &aTrack)
+{
+  if (aTrack.mSource == nullptr || aTrack.mCodec == nullptr || !aTrack.mCodec->allocated()) {
+    return false;
+  }
+
+  sp<AMessage> format;
+  if (aTrack.mCodec->getOutputFormat(&format) == OK) {
+    return true;
+  }
+
+  status_t status = OK;
+  size_t index = 0;
+  size_t offset = 0;
+  size_t size = 0;
+  int64_t timeUs = 0LL;
+  uint32_t flags = 0;
+  while ((status = aTrack.mCodec->dequeueOutputBuffer(&index, &offset, &size, &timeUs, &flags)) != INFO_FORMAT_CHANGED) {
+    if (status == OK) {
+      aTrack.mCodec->releaseOutputBuffer(index);
+    }
+    status = FillCodecInputData(aTrack);
+    if (status == INFO_FORMAT_CHANGED) {
+      break;
+    } else if (status != OK) {
+      return false;
+    }
+  }
+  return aTrack.mCodec->getOutputFormat(&format) == OK;
+}
+
+uint8_t *
+MediaCodecReader::GetColorConverterBuffer(int32_t aWidth, int32_t aHeight)
+{
+  // Allocate a temporary YUV420Planer buffer.
+  size_t yuv420p_y_size = aWidth * aHeight;
+  size_t yuv420p_u_size = ((aWidth + 1) / 2) * ((aHeight + 1) / 2);
+  size_t yuv420p_v_size = yuv420p_u_size;
+  size_t yuv420p_size = yuv420p_y_size + yuv420p_u_size + yuv420p_v_size;
+  if (mColorConverterBufferSize != yuv420p_size) {
+    mColorConverterBuffer = nullptr; // release the previous buffer first
+    mColorConverterBuffer = new uint8_t[yuv420p_size];
+    mColorConverterBufferSize = yuv420p_size;
+  }
+  return mColorConverterBuffer.get();
+}
+
+void
+MediaCodecReader::ClearColorConverterBuffer()
+{
+  mColorConverterBuffer = nullptr;
+  mColorConverterBufferSize = 0;
+}
+
+// Called on MediaCodecReader::mLooper thread.
+void
+MediaCodecReader::onMessageReceived(const sp<AMessage> &aMessage)
+{
+  switch (aMessage->what()) {
+
+    case kNotifyCodecReserved:
+    {
+      // Our decode may have acquired the hardware resource that it needs
+      // to start. Notify the state machine to resume loading metadata.
+      mDecoder->NotifyWaitingForResourcesStatusChanged();
+      break;
+    }
+
+    case kNotifyCodecCanceled:
+    {
+      ReleaseCriticalResources();
+      break;
+    }
+
+    // TODO
+
+    default:
+      TRESPASS();
+      break;
+  }
+}
+
+// Called on Binder thread.
+void
+MediaCodecReader::codecReserved(Track& aTrack)
+{
+  if (!ConfigureMediaCodec(aTrack)) {
+    DestroyMediaCodecs(aTrack);
+    return;
+  }
+
+  if (mHandler != nullptr) {
+    // post kNotifyCodecReserved to MediaCodecReader::mLooper thread.
+    sp<AMessage> notify = new AMessage(kNotifyCodecReserved, mHandler->id());
+    notify->post();
+  }
+}
+
+// Called on Binder thread.
+void
+MediaCodecReader::codecCanceled(Track& aTrack)
+{
+  DestroyMediaCodecs(aTrack);
+
+  if (mHandler != nullptr) {
+    // post kNotifyCodecCanceled to MediaCodecReader::mLooper thread.
+    sp<AMessage> notify = new AMessage(kNotifyCodecCanceled, mHandler->id());
+    notify->post();
+  }
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/omx/MediaCodecReader.h
@@ -0,0 +1,250 @@
+/* -*- 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 MEDIA_CODEC_READER_H
+#define MEDIA_CODEC_READER_H
+
+#include <utils/threads.h>
+
+#include <mozilla/CheckedInt.h>
+
+#include "MediaData.h"
+
+#include "I420ColorConverterHelper.h"
+#include "MediaCodecProxy.h"
+#include "MediaDecoderReader.h"
+
+namespace android {
+struct ALooper;
+struct AMessage;
+
+class MOZ_EXPORT MediaExtractor;
+struct MOZ_EXPORT MediaSource;
+struct MediaCodec;
+} // namespace android
+
+namespace mozilla {
+
+class MediaCodecReader : public MediaDecoderReader
+{
+public:
+  MediaCodecReader(AbstractMediaDecoder* aDecoder);
+  virtual ~MediaCodecReader();
+
+  // Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE
+  // on failure.
+  virtual nsresult Init(MediaDecoderReader* aCloneDonor);
+
+  // True if this reader is waiting media resource allocation
+  virtual bool IsWaitingMediaResources();
+
+  // True when this reader need to become dormant state
+  virtual bool IsDormantNeeded();
+
+  // Release media resources they should be released in dormant state
+  virtual void ReleaseMediaResources();
+
+  // Destroys the decoding state. The reader cannot be made usable again.
+  // This is different from ReleaseMediaResources() as Shutdown() is
+  // irreversible, whereas ReleaseMediaResources() is reversible.
+  virtual void Shutdown();
+
+  // Decodes an unspecified amount of audio data, enqueuing the audio data
+  // in mAudioQueue. Returns true when there's more audio to decode,
+  // false if the audio is finished, end of file has been reached,
+  // or an un-recoverable read error has occured.
+  virtual bool DecodeAudioData();
+
+  // Reads and decodes one video frame. Packets with a timestamp less
+  // than aTimeThreshold will be decoded (unless they're not keyframes
+  // and aKeyframeSkip is true), but will not be added to the queue.
+  virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
+                                int64_t aTimeThreshold);
+
+  virtual bool HasAudio();
+  virtual bool HasVideo();
+
+  // Read header data for all bitstreams in the file. Fills aInfo with
+  // the data required to present the media, and optionally fills *aTags
+  // with tag metadata from the file.
+  // Returns NS_OK on success, or NS_ERROR_FAILURE on failure.
+  virtual nsresult ReadMetadata(MediaInfo* aInfo,
+                                MetadataTags** aTags);
+
+  // Moves the decode head to aTime microseconds. aStartTime and aEndTime
+  // denote the start and end times of the media in usecs, and aCurrentTime
+  // is the current playback position in microseconds.
+  virtual nsresult Seek(int64_t aTime,
+                        int64_t aStartTime,
+                        int64_t aEndTime,
+                        int64_t aCurrentTime);
+
+  virtual bool IsMediaSeekable() MOZ_OVERRIDE;
+
+protected:
+  struct Track
+  {
+    Track();
+
+    // pipeline parameters
+    android::sp<android::MediaSource> mSource;
+    android::sp<android::MediaCodecProxy> mCodec;
+    android::Vector<android::sp<android::ABuffer> > mInputBuffers;
+    android::Vector<android::sp<android::ABuffer> > mOutputBuffers;
+
+    // media parameters
+    int64_t mDurationUs;
+
+    // playback parameters
+    CheckedUint32 mInputIndex;
+    bool mEndOfStream;
+    int64_t mSeekTimeUs;
+    bool mFlushed; // meaningless when mSeekTimeUs is invalid.
+  };
+
+  // Receive a message from MessageHandler.
+  // Called on MediaCodecReader::mLooper thread.
+  void onMessageReceived(const android::sp<android::AMessage> &aMessage);
+
+  // Receive a notify from ResourceListener.
+  // Called on Binder thread.
+  virtual void codecReserved(Track& aTrack);
+  virtual void codecCanceled(Track& aTrack);
+
+private:
+  // An intermediary class that can be managed by android::sp<T>.
+  // Redirect onMessageReceived() to MediaCodecReader.
+  class MessageHandler : public android::AHandler
+  {
+  public:
+    MessageHandler(MediaCodecReader *aReader);
+    ~MessageHandler();
+
+    virtual void onMessageReceived(const android::sp<android::AMessage> &aMessage);
+
+  private:
+    // Forbidden
+    MessageHandler() MOZ_DELETE;
+    MessageHandler(const MessageHandler &rhs) MOZ_DELETE;
+    const MessageHandler &operator=(const MessageHandler &rhs) MOZ_DELETE;
+
+    MediaCodecReader *mReader;
+  };
+  friend class MessageHandler;
+
+  // An intermediary class that can be managed by android::sp<T>.
+  // Redirect codecReserved() and codecCanceled() to MediaCodecReader.
+  class VideoResourceListener : public android::MediaCodecProxy::CodecResourceListener
+  {
+  public:
+    VideoResourceListener(MediaCodecReader *aReader);
+    ~VideoResourceListener();
+
+    virtual void codecReserved();
+    virtual void codecCanceled();
+
+  private:
+    // Forbidden
+    VideoResourceListener() MOZ_DELETE;
+    VideoResourceListener(const VideoResourceListener &rhs) MOZ_DELETE;
+    const VideoResourceListener &operator=(const VideoResourceListener &rhs) MOZ_DELETE;
+
+    MediaCodecReader *mReader;
+  };
+  friend class VideoResourceListener;
+
+  struct AudioTrack : public Track
+  {
+    AudioTrack();
+  };
+
+  struct VideoTrack : public Track
+  {
+    VideoTrack();
+
+    int32_t mWidth;
+    int32_t mHeight;
+    int32_t mStride;
+    int32_t mSliceHeight;
+    int32_t mColorFormat;
+    int32_t mRotation;
+    nsIntSize mFrameSize;
+    nsIntRect mPictureRect;
+    gfx::IntRect mRelativePictureRect;
+  };
+
+  struct CodecBufferInfo
+  {
+    CodecBufferInfo();
+
+    android::sp<android::ABuffer> mBuffer;
+    size_t mIndex;
+    size_t mOffset;
+    size_t mSize;
+    int64_t mTimeUs;
+    uint32_t mFlags;
+  };
+
+  // Forbidden
+  MediaCodecReader() MOZ_DELETE;
+  const MediaCodecReader &operator=(const MediaCodecReader &rhs) MOZ_DELETE;
+
+  bool ReallocateResources();
+  void ReleaseCriticalResources();
+  void ReleaseResources();
+
+  bool CreateLooper();
+  void DestroyLooper();
+
+  bool CreateExtractor();
+  void DestroyExtractor();
+
+  bool CreateMediaSources();
+  void DestroyMediaSources();
+
+  bool CreateMediaCodecs();
+  static bool CreateMediaCodec(android::sp<android::ALooper> &aLooper,
+                               Track &aTrack,
+                               bool aAsync,
+                               android::wp<android::MediaCodecProxy::CodecResourceListener> aListener);
+  static bool ConfigureMediaCodec(Track &aTrack);
+  void DestroyMediaCodecs();
+  static void DestroyMediaCodecs(Track &aTrack);
+
+  bool UpdateDuration();
+  bool UpdateAudioInfo();
+  bool UpdateVideoInfo();
+
+  static android::status_t FlushCodecData(Track &aTrack);
+  static android::status_t FillCodecInputData(Track &aTrack);
+  static android::status_t GetCodecOutputData(Track &aTrack,
+                                              CodecBufferInfo &aBuffer,
+                                              int64_t aThreshold,
+                                              const TimeStamp &aTimeout);
+  static bool EnsureCodecFormatParsed(Track &aTrack);
+
+  uint8_t *GetColorConverterBuffer(int32_t aWidth, int32_t aHeight);
+  void ClearColorConverterBuffer();
+
+  android::sp<MessageHandler> mHandler;
+  android::sp<VideoResourceListener> mVideoListener;
+
+  android::sp<android::ALooper> mLooper;
+  android::sp<android::MediaExtractor> mExtractor;
+
+  // media elements
+  AudioTrack mAudioTrack;
+  VideoTrack mVideoTrack;
+
+  // color converter
+  android::I420ColorConverterHelper mColorConverter;
+  nsAutoArrayPtr<uint8_t> mColorConverterBuffer;
+  size_t mColorConverterBufferSize;
+};
+
+} // namespace mozilla
+
+#endif // MEDIA_CODEC_READER_H
--- a/content/media/omx/MediaOmxReader.cpp
+++ b/content/media/omx/MediaOmxReader.cpp
@@ -12,16 +12,17 @@
 #include "MediaResource.h"
 #include "VideoUtils.h"
 #include "MediaOmxDecoder.h"
 #include "AbstractMediaDecoder.h"
 #include "AudioChannelService.h"
 #include "OmxDecoder.h"
 #include "MPAPI.h"
 #include "gfx2DGlue.h"
+#include "MediaStreamSource.h"
 
 #ifdef MOZ_AUDIO_OFFLOAD
 #include <stagefright/Utils.h>
 #include <cutils/properties.h>
 #include <stagefright/MetaData.h>
 #endif
 
 #define MAX_DROPPED_FRAMES 25
@@ -114,17 +115,17 @@ void MediaOmxReader::ReleaseMediaResourc
 
 nsresult MediaOmxReader::InitOmxDecoder()
 {
   if (!mOmxDecoder.get()) {
     //register sniffers, if they are not registered in this process.
     DataSource::RegisterDefaultSniffers();
     mDecoder->GetResource()->SetReadMode(MediaCacheStream::MODE_METADATA);
 
-    sp<DataSource> dataSource = new MediaStreamSource(mDecoder->GetResource(), mDecoder);
+    sp<DataSource> dataSource = new MediaStreamSource(mDecoder->GetResource());
     dataSource->initCheck();
 
     mExtractor = MediaExtractor::Create(dataSource);
     if (!mExtractor.get()) {
       return NS_ERROR_FAILURE;
     }
     mOmxDecoder = new OmxDecoder(mDecoder->GetResource(), mDecoder);
     if (!mOmxDecoder->Init(mExtractor)) {
@@ -322,17 +323,17 @@ bool MediaOmxReader::DecodeVideoFrame(bo
     }
 
     if (!v) {
       NS_WARNING("Unable to create VideoData");
       return false;
     }
 
     decoded++;
-    NS_ASSERTION(decoded <= parsed, "Expect to decode fewer frames than parsed in MediaPlugin...");
+    NS_ASSERTION(decoded <= parsed, "Expect to decode fewer frames than parsed in OMX decoder...");
 
     mVideoQueue.Push(v);
 
     break;
   }
 
   return true;
 }
new file mode 100644
--- /dev/null
+++ b/content/media/omx/MediaStreamSource.cpp
@@ -0,0 +1,64 @@
+/* -*- 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 "MediaStreamSource.h"
+
+#include <utils/threads.h>
+
+#include "nsISeekableStream.h"
+
+namespace android {
+
+MediaStreamSource::MediaStreamSource(MediaResource *aResource)
+  : mResource(aResource)
+{
+}
+
+MediaStreamSource::~MediaStreamSource()
+{
+}
+
+status_t MediaStreamSource::initCheck() const
+{
+  return OK;
+}
+
+ssize_t MediaStreamSource::readAt(off64_t offset, void *data, size_t size)
+{
+  char *ptr = static_cast<char *>(data);
+  size_t todo = size;
+  while (todo > 0) {
+    Mutex::Autolock autoLock(mLock);
+    uint32_t bytesRead;
+    if ((offset != mResource->Tell() &&
+         NS_FAILED(mResource->Seek(nsISeekableStream::NS_SEEK_SET, offset))) ||
+        NS_FAILED(mResource->Read(ptr, todo, &bytesRead))) {
+      return ERROR_IO;
+    }
+
+    if (bytesRead == 0) {
+      return size - todo;
+    }
+
+    offset += bytesRead;
+    todo -= bytesRead;
+    ptr += bytesRead;
+  }
+  return size;
+}
+
+status_t MediaStreamSource::getSize(off64_t *size)
+{
+  uint64_t length = mResource->GetLength();
+  if (length == static_cast<uint64_t>(-1))
+    return ERROR_UNSUPPORTED;
+
+  *size = length;
+
+  return OK;
+}
+
+}  // namespace android
new file mode 100644
--- /dev/null
+++ b/content/media/omx/MediaStreamSource.h
@@ -0,0 +1,54 @@
+/* -*- 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 MEDIA_STREAM_SOURCE_H
+#define MEDIA_STREAM_SOURCE_H
+
+#include <stdint.h>
+
+#include <stagefright/DataSource.h>
+#include <stagefright/MediaSource.h>
+
+#include "MediaResource.h"
+#include "nsAutoPtr.h"
+
+namespace android {
+
+// MediaStreamSource is a DataSource that reads from a MPAPI media stream.
+class MediaStreamSource : public DataSource {
+  typedef mozilla::MediaResource MediaResource;
+
+  Mutex mLock;
+  nsRefPtr<MediaResource> mResource;
+public:
+  MediaStreamSource(MediaResource* aResource);
+
+  virtual status_t initCheck() const;
+  virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+  virtual ssize_t readAt(off_t offset, void *data, size_t size) {
+    return readAt(static_cast<off64_t>(offset), data, size);
+  }
+  virtual status_t getSize(off_t *size) {
+    off64_t size64;
+    status_t status = getSize(&size64);
+    *size = size64;
+    return status;
+  }
+  virtual status_t getSize(off64_t *size);
+  virtual uint32_t flags() {
+    return kWantsPrefetching;
+  }
+
+  virtual ~MediaStreamSource();
+
+private:
+  MediaStreamSource(const MediaStreamSource &);
+  MediaStreamSource &operator=(const MediaStreamSource &);
+};
+
+} // namespace android
+
+#endif // MEDIA_STREAM_SOURCE_H
--- a/content/media/omx/OmxDecoder.cpp
+++ b/content/media/omx/OmxDecoder.cpp
@@ -27,17 +27,16 @@
 #include "nsMimeTypes.h"
 #include "MPAPI.h"
 #include "prlog.h"
 
 #include "GonkNativeWindow.h"
 #include "GonkNativeWindowClient.h"
 #include "OMXCodecProxy.h"
 #include "OmxDecoder.h"
-#include "nsISeekableStream.h"
 
 #ifdef PR_LOGGING
 PRLogModuleInfo *gOmxDecoderLog;
 #define LOG(type, msg...) PR_LOG(gOmxDecoderLog, type, (msg))
 #else
 #define LOG(x...)
 #endif
 
@@ -190,70 +189,16 @@ private:
   uint64_t                         mFullLength;
 
   Monitor mCompletedMonitor;
   bool    mCompleted;
 };
 
 }
 
-namespace android {
-
-MediaStreamSource::MediaStreamSource(MediaResource *aResource,
-                                     AbstractMediaDecoder *aDecoder) :
-  mResource(aResource), mDecoder(aDecoder)
-{
-}
-
-MediaStreamSource::~MediaStreamSource()
-{
-}
-
-status_t MediaStreamSource::initCheck() const
-{
-  return OK;
-}
-
-ssize_t MediaStreamSource::readAt(off64_t offset, void *data, size_t size)
-{
-  char *ptr = static_cast<char *>(data);
-  size_t todo = size;
-  while (todo > 0) {
-    Mutex::Autolock autoLock(mLock);
-    uint32_t bytesRead;
-    if ((offset != mResource->Tell() &&
-         NS_FAILED(mResource->Seek(nsISeekableStream::NS_SEEK_SET, offset))) ||
-        NS_FAILED(mResource->Read(ptr, todo, &bytesRead))) {
-      return ERROR_IO;
-    }
-
-    if (bytesRead == 0) {
-      return size - todo;
-    }
-
-    offset += bytesRead;
-    todo -= bytesRead;
-    ptr += bytesRead;
-  }
-  return size;
-}
-
-status_t MediaStreamSource::getSize(off64_t *size)
-{
-  uint64_t length = mResource->GetLength();
-  if (length == static_cast<uint64_t>(-1))
-    return ERROR_UNSUPPORTED;
-
-  *size = length;
-
-  return OK;
-}
-
-}  // namespace android
-
 using namespace android;
 
 OmxDecoder::OmxDecoder(MediaResource *aResource,
                        AbstractMediaDecoder *aDecoder) :
   mDecoder(aDecoder),
   mResource(aResource),
   mDisplayWidth(0),
   mDisplayHeight(0),
--- a/content/media/omx/OmxDecoder.h
+++ b/content/media/omx/OmxDecoder.h
@@ -1,14 +1,11 @@
 #include <stagefright/foundation/ABase.h>
 #include <stagefright/foundation/AHandlerReflector.h>
 #include <stagefright/foundation/ALooper.h>
-#include <stagefright/MediaSource.h>
-#include <stagefright/DataSource.h>
-#include <stagefright/MediaSource.h>
 #include <utils/RefBase.h>
 #include <stagefright/MediaExtractor.h>
 
 #include "GonkNativeWindow.h"
 #include "GonkNativeWindowClient.h"
 #include "mozilla/layers/FenceUtils.h"
 #include "MP3FrameParser.h"
 #include "MPAPI.h"
@@ -17,51 +14,16 @@
 #include "OMXCodecProxy.h"
 
 namespace android {
 class OmxDecoder;
 };
 
 namespace android {
 
-// MediaStreamSource is a DataSource that reads from a MPAPI media stream.
-class MediaStreamSource : public DataSource {
-  typedef mozilla::MediaResource MediaResource;
-  typedef mozilla::AbstractMediaDecoder AbstractMediaDecoder;
-
-  Mutex mLock;
-  nsRefPtr<MediaResource> mResource;
-  AbstractMediaDecoder *mDecoder;
-public:
-  MediaStreamSource(MediaResource* aResource,
-                    AbstractMediaDecoder *aDecoder);
-
-  virtual status_t initCheck() const;
-  virtual ssize_t readAt(off64_t offset, void *data, size_t size);
-  virtual ssize_t readAt(off_t offset, void *data, size_t size) {
-    return readAt(static_cast<off64_t>(offset), data, size);
-  }
-  virtual status_t getSize(off_t *size) {
-    off64_t size64;
-    status_t status = getSize(&size64);
-    *size = size64;
-    return status;
-  }
-  virtual status_t getSize(off64_t *size);
-  virtual uint32_t flags() {
-    return kWantsPrefetching;
-  }
-
-  virtual ~MediaStreamSource();
-
-private:
-  MediaStreamSource(const MediaStreamSource &);
-  MediaStreamSource &operator=(const MediaStreamSource &);
-};
-
 class OmxDecoder : public OMXCodecProxy::EventListener {
   typedef MPAPI::AudioFrame AudioFrame;
   typedef MPAPI::VideoFrame VideoFrame;
   typedef mozilla::MP3FrameParser MP3FrameParser;
   typedef mozilla::MediaResource MediaResource;
   typedef mozilla::AbstractMediaDecoder AbstractMediaDecoder;
   typedef mozilla::layers::FenceHandle FenceHandle;
   typedef mozilla::layers::TextureClient TextureClient;
old mode 100755
new mode 100644
--- a/content/media/omx/moz.build
+++ b/content/media/omx/moz.build
@@ -8,16 +8,17 @@ EXPORTS += [
     'AudioOffloadPlayerBase.h',
     'MediaOmxDecoder.h',
     'MediaOmxReader.h',
 ]
 
 SOURCES += [
     'MediaOmxDecoder.cpp',
     'MediaOmxReader.cpp',
+    'MediaStreamSource.cpp',
     'OMXCodecProxy.cpp',
     'OmxDecoder.cpp',
 ]
 
 if CONFIG['MOZ_AUDIO_OFFLOAD']:
     EXPORTS += [
         'AudioOffloadPlayer.h',
         'AudioOutput.h',
@@ -44,20 +45,25 @@ if 'rtsp' in CONFIG['NECKO_PROTOCOLS']:
     ]
     SOURCES += [
         'RtspOmxDecoder.cpp',
         'RtspOmxReader.cpp',
     ]
 
 if int(CONFIG['ANDROID_VERSION']) >= 16:
     EXPORTS += [
+        'MediaCodecDecoder.h',
         'MediaCodecProxy.h',
+        'MediaCodecReader.h',
     ]
     SOURCES += [
+        'I420ColorConverterHelper.cpp',
+        'MediaCodecDecoder.cpp',
         'MediaCodecProxy.cpp',
+        'MediaCodecReader.cpp',
     ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
     '/content/base/src',
     '/content/html/content/src',
--- a/content/media/webspeech/recognition/SpeechRecognition.cpp
+++ b/content/media/webspeech/recognition/SpeechRecognition.cpp
@@ -579,29 +579,22 @@ SpeechRecognition::Observe(nsISupports* 
   }
 
   return NS_OK;
 }
 
 void
 SpeechRecognition::ProcessTestEventRequest(nsISupports* aSubject, const nsAString& aEventName)
 {
-  if (aEventName.EqualsLiteral("EVENT_START")) {
-    ErrorResult err;
-    Start(err);
-  } else if (aEventName.EqualsLiteral("EVENT_STOP")) {
-    Stop();
-  } else if (aEventName.EqualsLiteral("EVENT_ABORT")) {
+  if (aEventName.EqualsLiteral("EVENT_ABORT")) {
     Abort();
   } else if (aEventName.EqualsLiteral("EVENT_AUDIO_ERROR")) {
     DispatchError(SpeechRecognition::EVENT_AUDIO_ERROR,
                   SpeechRecognitionErrorCode::Audio_capture, // TODO different codes?
                   NS_LITERAL_STRING("AUDIO_ERROR test event"));
-  } else if (aEventName.EqualsLiteral("EVENT_AUDIO_DATA")) {
-    StartRecording(static_cast<DOMMediaStream*>(aSubject));
   } else {
     NS_ASSERTION(mTestConfig.mFakeRecognitionService,
                  "Got request for fake recognition service event, but "
                  TEST_PREFERENCE_FAKE_RECOGNITION_SERVICE " is unset");
 
     // let the fake recognition service handle the request
   }
 
@@ -688,17 +681,17 @@ SpeechRecognition::GetServiceURI(nsStrin
 void
 SpeechRecognition::SetServiceURI(const nsAString& aArg, ErrorResult& aRv)
 {
   aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   return;
 }
 
 void
-SpeechRecognition::Start(ErrorResult& aRv)
+SpeechRecognition::Start(const Optional<NonNull<DOMMediaStream>>& aStream, ErrorResult& aRv)
 {
   if (mCurrentState != STATE_IDLE) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   nsAutoCString speechRecognitionServiceCID;
   GetRecognitionServiceCID(speechRecognitionServiceCID);
@@ -708,17 +701,19 @@ SpeechRecognition::Start(ErrorResult& aR
   NS_ENSURE_SUCCESS_VOID(rv);
 
   rv = mRecognitionService->Initialize(this->asWeakPtr());
   NS_ENSURE_SUCCESS_VOID(rv);
 
   MediaStreamConstraints constraints;
   constraints.mAudio.SetAsBoolean() = true;
 
-  if (!mTestConfig.mFakeFSMEvents) {
+  if (aStream.WasPassed()) {
+    StartRecording(&aStream.Value());
+  } else {
     MediaManager* manager = MediaManager::Get();
     manager->GetUserMedia(false,
                           GetOwner(),
                           constraints,
                           new GetUserMediaSuccessCallback(this),
                           new GetUserMediaErrorCallback(this));
   }
 
--- a/content/media/webspeech/recognition/SpeechRecognition.h
+++ b/content/media/webspeech/recognition/SpeechRecognition.h
@@ -91,17 +91,17 @@ public:
   uint32_t GetMaxAlternatives(ErrorResult& aRv) const;
 
   void SetMaxAlternatives(uint32_t aArg, ErrorResult& aRv);
 
   void GetServiceURI(nsString& aRetVal, ErrorResult& aRv) const;
 
   void SetServiceURI(const nsAString& aArg, ErrorResult& aRv);
 
-  void Start(ErrorResult& aRv);
+  void Start(const Optional<NonNull<DOMMediaStream>>& aStream, ErrorResult& aRv);
 
   void Stop();
 
   void Abort();
 
   IMPL_EVENT_HANDLER(audiostart)
   IMPL_EVENT_HANDLER(soundstart)
   IMPL_EVENT_HANDLER(speechstart)
--- a/content/media/webspeech/recognition/test/head.js
+++ b/content/media/webspeech/recognition/test/head.js
@@ -85,44 +85,43 @@ function EventManager(sr) {
       if (self.doneFunc && !isDone &&
           nEventsExpected === self.eventsReceived.length) {
         isDone = true;
         self.doneFunc();
       }
     }
   }
 
+  self.start = function EventManager_start() {
+    isSendingAudioData = true;
+    var audioTag = document.createElement("audio");
+    audioTag.src = self.audioSampleFile;
+
+    var stream = audioTag.mozCaptureStreamUntilEnded();
+    audioTag.addEventListener("ended", function() {
+      info("Sample stream ended, requesting queued events");
+      isSendingAudioData = false;
+      while (queuedEventRequests.length) {
+        self.requestFSMEvent(queuedEventRequests.shift());
+      }
+    });
+
+    audioTag.play();
+    sr.start(stream);
+  }
+
   self.requestFSMEvent = function EventManager_requestFSMEvent(eventName) {
     if (isSendingAudioData) {
       info("Queuing event " + eventName + " until we're done sending audio data");
       queuedEventRequests.push(eventName);
       return;
     }
 
-    var subject = null;
-
-    if (eventName === "EVENT_AUDIO_DATA") {
-      isSendingAudioData = true;
-      var audioTag = document.createElement("audio");
-      audioTag.src = self.audioSampleFile;
-
-      subject = audioTag.mozCaptureStreamUntilEnded();
-      audioTag.addEventListener("ended", function() {
-        info("Sample stream ended, requesting queued events");
-        isSendingAudioData = false;
-        while (queuedEventRequests.length) {
-          self.requestFSMEvent(queuedEventRequests.shift());
-        }
-      });
-
-      audioTag.play();
-    }
-
     info("requesting " + eventName);
-    Services.obs.notifyObservers(subject,
+    Services.obs.notifyObservers(null,
                                  SPEECH_RECOGNITION_TEST_REQUEST_EVENT_TOPIC,
                                  eventName);
   }
 
   self.requestTestEnd = function EventManager_requestTestEnd() {
     Services.obs.notifyObservers(null, SPEECH_RECOGNITION_TEST_END_TOPIC, null);
   }
 }
@@ -163,13 +162,15 @@ function performTest(options) {
       }
     }
 
     em.audioSampleFile = DEFAULT_AUDIO_SAMPLE_FILE;
     if (options.audioSampleFile) {
       em.audioSampleFile = options.audioSampleFile;
     }
 
+    em.start();
+
     for (var i = 0; i < options.eventsToRequest.length; i++) {
       em.requestFSMEvent(options.eventsToRequest[i]);
     }
   });
 }
--- a/content/media/webspeech/recognition/test/test_abort.html
+++ b/content/media/webspeech/recognition/test/test_abort.html
@@ -52,17 +52,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     info("Aborting on " + nextEvent);
     expectedEvents[nextEvent] = function(evt, sr) {
       sr.abort();
     };
 
     nextEventIdx++;
 
     performTest({
-      eventsToRequest: ["EVENT_START", "EVENT_AUDIO_DATA"],
+      eventsToRequest: [],
       expectedEvents: expectedEvents,
       doneFunc: (nextEventIdx < eventsToAbortOn.length) ? doNextTest : SimpleTest.finish,
       prefs: [["media.webspeech.test.fake_fsm_events", true], ["media.webspeech.test.fake_recognition_service", true]]
     });
   }
 
   doNextTest();
 </script>
--- a/content/media/webspeech/recognition/test/test_audio_capture_error.html
+++ b/content/media/webspeech/recognition/test/test_audio_capture_error.html
@@ -16,17 +16,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script type="text/javascript">
   SimpleTest.waitForExplicitFinish();
 
   performTest({
-    eventsToRequest: ['EVENT_START', 'EVENT_AUDIO_ERROR'],
+    eventsToRequest: ['EVENT_AUDIO_ERROR'],
     expectedEvents: {
       'error': buildErrorCallback(errorCodes.AUDIO_CAPTURE),
       'end': null
     },
     doneFunc: SimpleTest.finish,
     prefs: [["media.webspeech.test.fake_fsm_events", true]]
   });
 </script>
--- a/content/media/webspeech/recognition/test/test_call_start_from_end_handler.html
+++ b/content/media/webspeech/recognition/test/test_call_start_from_end_handler.html
@@ -15,41 +15,49 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script type="text/javascript">
   SimpleTest.waitForExplicitFinish();
 
+  function createAudioStream() {
+    var audioTag = document.createElement("audio");
+    audioTag.src = DEFAULT_AUDIO_SAMPLE_FILE;
+
+    var stream = audioTag.mozCaptureStreamUntilEnded();
+    audioTag.play();
+
+    return stream;
+  }
+
   function endHandler(evt, sr) {
     try {
-      sr.start(); // shouldn't fail
+      sr.start(createAudioStream()); // shouldn't fail
     } catch (err) {
       ok(false, "Failed to start() from end() callback");
     }
 
     info("Successfully start() from end() callback");
   }
 
   function expectExceptionHandler(evt, sr) {
     try {
-      sr.start();
+      sr.start(createAudioStream());
     } catch (err) {
       is(err.name, "InvalidStateError");
       return;
     }
 
     ok(false, "Calling start() didn't raise InvalidStateError");
   }
 
   performTest({
     eventsToRequest: [
-      'EVENT_START',
-      'EVENT_AUDIO_DATA',
       'EVENT_RECOGNITIONSERVICE_FINAL_RESULT'
     ],
     expectedEvents: {
       'start': expectExceptionHandler,
       'audiostart': expectExceptionHandler,
       'speechstart': expectExceptionHandler,
       'speechend': expectExceptionHandler,
       'audioend': expectExceptionHandler,
--- a/content/media/webspeech/recognition/test/test_nested_eventloop.html
+++ b/content/media/webspeech/recognition/test/test_nested_eventloop.html
@@ -61,20 +61,17 @@ https://bugzilla.mozilla.org/show_bug.cg
    * the event handler. This causes the recording to stop, which raises
    * the audioend and (later on) end events.
    * Then, we abort (once again spinning the event loop) from the audioend
    * handler, attempting to cause a re-entry into the abort code. This second
    * call should be ignored, and we get the end callback and finish.
    */
 
   performTest({
-    eventsToRequest: [
-      "EVENT_START",
-      "EVENT_AUDIO_DATA",
-    ],
+    eventsToRequest: [],
     expectedEvents: {
       "audiostart": abortAndSpinEventLoop,
       "audioend": abortAndSpinEventLoop,
       "end": null
     },
     doneFunc: doneFunc,
     prefs: [["media.webspeech.test.fake_fsm_events", true],
             ["media.webspeech.test.fake_recognition_service", true]]
--- a/content/media/webspeech/recognition/test/test_recognition_service_error.html
+++ b/content/media/webspeech/recognition/test/test_recognition_service_error.html
@@ -17,18 +17,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 </div>
 <pre id="test">
 <script type="text/javascript">
   SimpleTest.waitForExplicitFinish();
 
   performTest({
     eventsToRequest: [
-      'EVENT_START',
-      'EVENT_AUDIO_DATA',
       'EVENT_RECOGNITIONSERVICE_ERROR'
     ],
     expectedEvents: {
       'start': null,
       'audiostart': null,
       'speechstart': null,
       'speechend': null,
       'audioend': null,
--- a/content/media/webspeech/recognition/test/test_success_without_recognition_service.html
+++ b/content/media/webspeech/recognition/test/test_success_without_recognition_service.html
@@ -17,18 +17,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 </div>
 <pre id="test">
 <script type="text/javascript">
   SimpleTest.waitForExplicitFinish();
 
   performTest({
     eventsToRequest: [
-      'EVENT_START',
-      'EVENT_AUDIO_DATA',
       'EVENT_RECOGNITIONSERVICE_FINAL_RESULT'
     ],
     expectedEvents: {
       'start': null,
       'audiostart': null,
       'speechstart': null,
       'speechend': null,
       'audioend': null,
--- a/content/media/webspeech/recognition/test/test_timeout.html
+++ b/content/media/webspeech/recognition/test/test_timeout.html
@@ -16,20 +16,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script type="text/javascript">
   SimpleTest.waitForExplicitFinish();
 
   performTest({
-    eventsToRequest: [
-      "EVENT_START",
-      "EVENT_AUDIO_DATA"
-    ],
+    eventsToRequest: [],
     expectedEvents: {
       "start": null,
       "audiostart": null,
       "audioend": null,
       "error": buildErrorCallback(errorCodes.NO_SPEECH),
       "end": null
     },
     doneFunc: SimpleTest.finish,
--- a/content/xml/document/src/moz.build
+++ b/content/xml/document/src/moz.build
@@ -15,17 +15,17 @@ UNIFIED_SOURCES += [
     'XMLDocument.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 MSVC_ENABLE_PGO = True
 
 LOCAL_INCLUDES += [
-    '/caps/include',
+    '/caps',
     '/content/base/src',
     '/content/html/document/src',
     '/content/xul/content/src',
     '/dom/base',
     '/layout/style',
 ]
 
 FINAL_LIBRARY = 'gklayout'
--- a/dom/animation/test/css-integration/test_element-get-animation-players.html
+++ b/dom/animation/test/css-integration/test_element-get-animation-players.html
@@ -191,16 +191,64 @@ test(function() {
     'getAnimationPlayers returns players only for those CSS Animations whose'
     + ' animation-name is not none');
 
   div.remove();
 }, 'getAnimationPlayers for CSS Animations with animation-name: none');
 
 test(function() {
   var div = addDiv();
+  div.style.animation = 'missing 100s';
+  window.getComputedStyle(div).animationName;
+
+  var players = div.getAnimationPlayers();
+  assert_equals(players.length, 0,
+    'getAnimationPlayers returns an empty sequence for an element'
+    + ' with animation-name: missing');
+
+  div.style.animation = 'anim1 100s, missing 100s';
+  window.getComputedStyle(div).animationName;
+  players = div.getAnimationPlayers();
+  assert_equals(players.length, 1,
+    'getAnimationPlayers returns players only for those CSS Animations whose'
+    + ' animation-name is found');
+
+  div.remove();
+}, 'getAnimationPlayers for CSS Animations with animation-name: missing');
+
+async_test(function(t) {
+  var div = addDiv();
+  div.style.animation = 'anim1 100s, notyet 100s';
+  window.getComputedStyle(div).animationName;
+
+  var players = div.getAnimationPlayers();
+  assert_equals(players.length, 1,
+    'getAnimationPlayers initally only returns players for CSS Animations whose'
+    + ' animation-name is found');
+
+  window.requestAnimationFrame(t.step_func(function() {
+    var keyframes = '@keyframes notyet { to { left: 100px; } }';
+    document.styleSheets[0].insertRule(keyframes, 0);
+    window.getComputedStyle(div).animationName;
+
+    players = div.getAnimationPlayers();
+    assert_equals(players.length, 2,
+      'getAnimationPlayers includes player when @keyframes rule is added'
+      + ' later');
+    assert_true(players[0].startTime < players[1].startTime,
+      'Newly added player has a later start time');
+    document.styleSheets[0].deleteRule(0);
+    div.remove();
+    t.done();
+  }));
+}, 'getAnimationPlayers for CSS Animations where the @keyframes rule is added'
+   + ' later');
+
+test(function() {
+  var div = addDiv();
   div.style.animation = 'anim1 100s, anim1 100s';
   window.getComputedStyle(div).animationName;
 
   assert_equals(div.getAnimationPlayers().length, 2,
     'getAnimationPlayers returns one player for each CSS animation-name'
     + ' even if the names are duplicated');
   div.remove();
 }, 'getAnimationPlayers for CSS Animations with duplicated animation-name');
--- a/dom/base/DOMRequestHelper.jsm
+++ b/dom/base/DOMRequestHelper.jsm
@@ -183,17 +183,16 @@ DOMRequestIpcHelper.prototype = {
     this._destroyed = true;
 
     Services.obs.removeObserver(this, "inner-window-destroyed");
 
     if (this._listeners) {
       Object.keys(this._listeners).forEach((aName) => {
         this._listeners[aName].weakRef ? cpmm.removeWeakMessageListener(aName, this)
                                        : cpmm.removeMessageListener(aName, this);
-        delete this._listeners[aName];
       });
     }
 
     this._listeners = null;
     this._requests = null;
 
     // Objects inheriting from DOMRequestIPCHelper may have an uninit function.
     if (this.uninit) {
--- a/dom/browser-element/mochitest/browserElement_Alert.js
+++ b/dom/browser-element/mochitest/browserElement_Alert.js
@@ -42,19 +42,19 @@ function runTest() {
 }
 
 function test1() {
   iframe.addEventListener('mozbrowsershowmodalprompt', test2);
 
   // Do window.alert within the iframe, then modify the global |testState|
   // after the alert.
   var script = 'data:,\
-    testState = 0; \
+    this.testState = 0; \
     content.alert("Hello, world!"); \
-    testState = 1; \
+    this.testState = 1; \
   ';
 
   mm.loadFrameScript(script, /* allowDelayedLoad = */ false);
 
   // Triggers a mozbrowsershowmodalprompt event, which sends us down to test2.
 }
 
 // test2 is a mozbrowsershowmodalprompt listener.
@@ -66,39 +66,39 @@ function test2(e) {
 
   SimpleTest.executeSoon(function() { test2a(e); });
 }
 
 function test2a(e) {
   // The iframe should be blocked on the alert call at the moment, so testState
   // should still be 0.
   var script = 'data:,\
-    if (testState === 0) { \
+    if (this.testState === 0) { \
       sendAsyncMessage("test-success", "1: Correct testState"); \
     } \
     else { \
-      sendAsyncMessage("test-fail", "1: Wrong testState: " + testState); \
+      sendAsyncMessage("test-fail", "1: Wrong testState: " + this.testState); \
     }';
 
   mm.loadFrameScript(script, /* allowDelayedLoad = */ false);
   numPendingChildTests++;
 
   waitForPendingTests(function() { test3(e); });
 }
 
 function test3(e) {
   // Now unblock the iframe and check that the script completed.
   e.detail.unblock();
 
   var script2 = 'data:,\
-    if (testState === 1) { \
+    if (this.testState === 1) { \
       sendAsyncMessage("test-success", "2: Correct testState"); \
     } \
     else { \
-      sendAsyncMessage("test-try-again", "2: Wrong testState (for now): " + testState); \
+      sendAsyncMessage("test-try-again", "2: Wrong testState (for now): " + this.testState); \
     }';
 
   // Urgh.  e.unblock() didn't necessarily unblock us immediately, so we have
   // to spin and wait.
   function onTryAgain() {
     SimpleTest.executeSoon(function() {
       //dump('onTryAgain\n');
       mm.loadFrameScript(script2, /* allowDelayedLoad = */ false);
--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -186,16 +186,17 @@ GetNotifyIMEMessageName(IMEMessage aMess
   }
 }
 #endif // #ifdef PR_LOGGING
 
 nsIContent* IMEStateManager::sContent = nullptr;
 nsPresContext* IMEStateManager::sPresContext = nullptr;
 bool IMEStateManager::sInstalledMenuKeyboardListener = false;
 bool IMEStateManager::sIsTestingIME = false;
+bool IMEStateManager::sIsGettingNewIMEState = false;
 
 // sActiveIMEContentObserver points to the currently active IMEContentObserver.
 // sActiveIMEContentObserver is null if there is no focused editor.
 IMEContentObserver* IMEStateManager::sActiveIMEContentObserver = nullptr;
 TextCompositionArray* IMEStateManager::sTextCompositions = nullptr;
 
 // static
 void
@@ -563,20 +564,29 @@ IMEStateManager::OnFocusInEditor(nsPresC
 // static
 void
 IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
                                 nsIContent* aContent)
 {
   PR_LOG(sISMLog, PR_LOG_ALWAYS,
     ("ISM: IMEStateManager::UpdateIMEState(aNewIMEState={ mEnabled=%s, "
      "mOpen=%s }, aContent=0x%p), "
-     "sPresContext=0x%p, sContent=0x%p, sActiveIMEContentObserver=0x%p",
+     "sPresContext=0x%p, sContent=0x%p, sActiveIMEContentObserver=0x%p, "
+     "sIsGettingNewIMEState=%s",
      GetIMEStateEnabledName(aNewIMEState.mEnabled),
      GetIMEStateSetOpenName(aNewIMEState.mOpen), aContent,
-     sPresContext, sContent, sActiveIMEContentObserver));
+     sPresContext, sContent, sActiveIMEContentObserver,
+     GetBoolName(sIsGettingNewIMEState)));
+
+  if (sIsGettingNewIMEState) {
+    PR_LOG(sISMLog, PR_LOG_DEBUG,
+      ("ISM:   IMEStateManager::UpdateIMEState(), "
+       "does nothing because of called while getting new IME state"));
+    return;
+  }
 
   if (NS_WARN_IF(!sPresContext)) {
     PR_LOG(sISMLog, PR_LOG_ERROR,
       ("ISM:   IMEStateManager::UpdateIMEState(), FAILED due to "
        "no managing nsPresContext"));
     return;
   }
   nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
@@ -654,16 +664,23 @@ IMEStateManager::GetNewIMEState(nsPresCo
       return IMEState(IMEState::ENABLED);
     }
     PR_LOG(sISMLog, PR_LOG_DEBUG,
       ("ISM:   IMEStateManager::GetNewIMEState() returns DISABLED because "
        "no content has focus"));
     return IMEState(IMEState::DISABLED);
   }
 
+  // nsIContent::GetDesiredIMEState() may cause a call of UpdateIMEState()
+  // from nsEditor::PostCreate() because GetDesiredIMEState() needs to retrieve
+  // an editor instance for the element if it's editable element.
+  // For avoiding such nested IME state updates, we should set
+  // sIsGettingNewIMEState here and UpdateIMEState() should check it.
+  GettingNewIMEStateBlocker blocker;
+
   IMEState newIMEState = aContent->GetDesiredIMEState();
   PR_LOG(sISMLog, PR_LOG_DEBUG,
     ("ISM:   IMEStateManager::GetNewIMEState() returns { mEnabled=%s, "
      "mOpen=%s }",
      GetIMEStateEnabledName(newIMEState.mEnabled),
      GetIMEStateSetOpenName(newIMEState.mOpen)));
   return newIMEState;
 }
--- a/dom/events/IMEStateManager.h
+++ b/dom/events/IMEStateManager.h
@@ -141,16 +141,33 @@ protected:
   static bool IsEditable(nsINode* node);
 
   static bool IsEditableIMEState(nsIWidget* aWidget);
 
   static nsIContent*    sContent;
   static nsPresContext* sPresContext;
   static bool           sInstalledMenuKeyboardListener;
   static bool           sIsTestingIME;
+  static bool           sIsGettingNewIMEState;
+
+  class MOZ_STACK_CLASS GettingNewIMEStateBlocker MOZ_FINAL
+  {
+  public:
+    GettingNewIMEStateBlocker()
+      : mOldValue(IMEStateManager::sIsGettingNewIMEState)
+    {
+      IMEStateManager::sIsGettingNewIMEState = true;
+    }
+    ~GettingNewIMEStateBlocker()
+    {
+      IMEStateManager::sIsGettingNewIMEState = mOldValue;
+    }
+  private:
+    bool mOldValue;
+  };
 
   static IMEContentObserver* sActiveIMEContentObserver;
 
   // All active compositions in the process are stored by this array.
   // When you get an item of this array and use it, please be careful.
   // The instances in this array can be destroyed automatically if you do
   // something to cause committing or canceling the composition.
   static TextCompositionArray* sTextCompositions;
--- a/dom/events/test/test_bug603008.html
+++ b/dom/events/test/test_bug603008.html
@@ -340,16 +340,19 @@ function testTouchChanged() {
 
   var moveEvents = 0;
   function onMove(aEvent) {
     moveEvents++;
   }
 
   window.addEventListener("touchmove", onMove, false);
 
+  // the first touchmove should always fire an event
+  sendTouchEvent(cwu, "touchmove", event, 0);
+
   // changing nothing should not fire a touchmove event
   sendTouchEvent(cwu, "touchmove", event, 0);
 
   // test moving x
   event.touches[0].page.x -= 1;
   sendTouchEvent(cwu, "touchmove", event, 0);
 
   // test moving y
@@ -370,17 +373,17 @@ function testTouchChanged() {
 
   // test changing force
   event.touches[0].force += 1;
   sendTouchEvent(cwu, "touchmove", event, 0);
 
   // changing nothing again
   sendTouchEvent(cwu, "touchmove", event, 0);
   
-  is(moveEvents, 6, "Six move events fired");
+  is(moveEvents, 7, "Six move events fired");
 
   window.removeEventListener("touchmove", onMove, false);
   sendTouchEvent(cwu, "touchend", event, 0);
   nextTest();
 }
 
 function testPreventDefault() {
   let cwu = SpecialPowers.getDOMWindowUtils(window);
deleted file mode 100644
--- a/dom/imptests/failures/html/html/semantics/forms/the-form-element/mochitest.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
-[DEFAULT]
-support-files =
-
-
-[test_form-elements-nameditem-01.html.json]
deleted file mode 100644
--- a/dom/imptests/failures/html/html/semantics/forms/the-form-element/test_form-elements-nameditem-01.html.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "RadioNodeList should exist": true
-}
--- a/dom/imptests/moz.build
+++ b/dom/imptests/moz.build
@@ -18,17 +18,16 @@ MOCHITEST_MANIFESTS += [
     'failures/html/dom/lists/mochitest.ini',
     'failures/html/dom/mochitest.ini',
     'failures/html/dom/nodes/mochitest.ini',
     'failures/html/html/browsers/the-window-object/mochitest.ini',
     'failures/html/html/browsers/the-window-object/named-access-on-the-window-object/mochitest.ini',
     'failures/html/html/dom/documents/dta/doc.gEBN/mochitest.ini',
     'failures/html/html/dom/documents/dta/mochitest.ini',
     'failures/html/html/obsolete/implreq/oeaaa/mochitest.ini',
-    'failures/html/html/semantics/forms/the-form-element/mochitest.ini',
     'failures/html/html/semantics/forms/the-option-element/mochitest.ini',
     'failures/html/html/semantics/forms/the-select-element/mochitest.ini',
     'failures/html/html/semantics/scripting-1/the-script-element/mochitest.ini',
     'failures/html/html/semantics/tabular-data/the-table-element/mochitest.ini',
     'failures/html/html/webappapis/atob/mochitest.ini',
     'failures/html/js/builtins/mochitest.ini',
     'failures/html/microdata/microdata-dom-api/mochitest.ini',
     'failures/html/typedarrays/mochitest.ini',
--- a/dom/indexedDB/moz.build
+++ b/dom/indexedDB/moz.build
@@ -60,17 +60,17 @@ SOURCES += [
 ]
 
 FAIL_ON_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
-    '/caps/include',
+    '/caps',
     '/content/base/src',
     '/db/sqlite3/src',
     '/dom/base',
     '/dom/quota',
     '/dom/src/storage',
     '/xpcom/build',
 ]
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1756,17 +1756,16 @@ ContentParent::ContentParent(mozIApplica
     // PID along with the warning.
     nsDebugImpl::SetMultiprocessMode("Parent");
 
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     ChildPrivileges privs = aIsNuwaProcess
         ? base::PRIVILEGES_INHERIT
         : base::PRIVILEGES_DEFAULT;
     mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content, privs);
-    mSubprocess->SetSandboxEnabled(ShouldSandboxContentProcesses());
 
     IToplevelProtocol::SetTransport(mSubprocess->GetChannel());
 
     if (!aIsNuwaProcess) {
         // Tell the memory reporter manager that this ContentParent exists.
         nsRefPtr<nsMemoryReporterManager> mgr =
             nsMemoryReporterManager::GetOrCreate();
         if (mgr) {
@@ -3626,26 +3625,16 @@ ContentParent::ShouldContinueFromReplyTi
 {
     // The only time ContentParent sends blocking messages is for CPOWs, so
     // timeouts should only ever occur in electrolysis-enabled sessions.
     MOZ_ASSERT(BrowserTabsRemote());
     return false;
 }
 
 bool
-ContentParent::ShouldSandboxContentProcesses()
-{
-#ifdef MOZ_CONTENT_SANDBOX
-    return !PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX");
-#else
-    return true;
-#endif
-}
-
-bool
 ContentParent::RecvRecordingDeviceEvents(const nsString& aRecordingStatus,
                                          const nsString& aPageURL,
                                          const bool& aIsAudio,
                                          const bool& aIsVideo)
 {
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     if (obs) {
         // recording-device-ipc-events needs to gather more information from content process
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -269,17 +269,16 @@ public:
         const BlobConstructorParams& aParams) MOZ_OVERRIDE;
 
 protected:
     void OnChannelConnected(int32_t pid) MOZ_OVERRIDE;
     virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
     void OnNuwaForkTimeout();
 
     bool ShouldContinueFromReplyTimeout() MOZ_OVERRIDE;
-    bool ShouldSandboxContentProcesses();
 
 private:
     static nsDataHashtable<nsStringHashKey, ContentParent*> *sAppContentParents;
     static nsTArray<ContentParent*>* sNonAppContentParents;
     static nsTArray<ContentParent*>* sPrivateContent;
     static StaticAutoPtr<LinkedList<ContentParent> > sContentParents;
 
     static void JoinProcessesIOThread(const nsTArray<ContentParent*>* aProcesses,
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -113,25 +113,51 @@ static bool sActiveDurationMsSet = false
 typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap;
 static TabChildMap* sTabChildren;
 
 TabChildBase::TabChildBase()
   : mContentDocumentIsDisplayed(false)
   , mTabChildGlobal(nullptr)
   , mInnerSize(0, 0)
 {
+  mozilla::HoldJSObjects(this);
 }
 
+TabChildBase::~TabChildBase()
+{
+  mAnonymousGlobalScopes.Clear();
+  mozilla::DropJSObjects(this);
+}
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(TabChildBase)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TabChildBase)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChildGlobal)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mAnonymousGlobalScopes)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TabChildBase)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChildGlobal)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(TabChildBase)
+  for (uint32_t i = 0; i < tmp->mAnonymousGlobalScopes.Length(); ++i) {
+    NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAnonymousGlobalScopes[i])
+  }
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TabChildBase)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
 NS_IMPL_CYCLE_COLLECTING_ADDREF(TabChildBase)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(TabChildBase)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TabChildBase)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTION(TabChildBase, mTabChildGlobal, mGlobal)
 
 void
 TabChildBase::InitializeRootMetrics()
 {
   // Calculate a really simple resolution that we probably won't
   // be keeping, as well as putting the scroll offset back to
   // the top-left of the page.
   mLastRootMetrics.mViewport = CSSRect(CSSPoint(), kDefaultViewportSize);
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -160,18 +160,19 @@ protected:
 // It make sense to place in this class all helper functions, and functionality which could be shared between
 // Cross-process/Cross-thread implmentations.
 class TabChildBase : public nsISupports,
                      public nsFrameScriptExecutor,
                      public ipc::MessageManagerCallback
 {
 public:
     TabChildBase();
+
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-    NS_DECL_CYCLE_COLLECTION_CLASS(TabChildBase)
+    NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TabChildBase)
 
     virtual nsIWebNavigation* WebNavigation() = 0;
     virtual nsIWidget* WebWidget() = 0;
     nsIPrincipal* GetPrincipal() { return mPrincipal; }
     bool IsAsyncPanZoomEnabled();
     // Recalculates the display state, including the CSS
     // viewport. This should be called whenever we believe the
     // viewport data on a document may have changed. If it didn't
@@ -183,17 +184,17 @@ public:
                                          const bool& aIsRoot,
                                          const mozilla::layers::ZoomConstraints& aConstraints) = 0;
 
     nsEventStatus DispatchSynthesizedMouseEvent(uint32_t aMsg, uint64_t aTime,
                                                 const LayoutDevicePoint& aRefPoint,
                                                 nsIWidget* aWidget);
 
 protected:
-    ~TabChildBase() {}
+    virtual ~TabChildBase();
     CSSSize GetPageSize(nsCOMPtr<nsIDocument> aDocument, const CSSSize& aViewport);
 
     // Get the DOMWindowUtils for the top-level window in this tab.
     already_AddRefed<nsIDOMWindowUtils> GetDOMWindowUtils();
     // Get the Document for the top-level window in this tab.
     already_AddRefed<nsIDocument> GetDocument();
 
     // Wrapper for nsIDOMWindowUtils.setCSSViewport(). This updates some state
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -61,14 +61,14 @@ if CONFIG['MOZ_B2G']:
         'MediaPermissionGonk.cpp',
     ]
 
 FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
     '../base',
     '../camera',
-    '/caps/include',
+    '/caps',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
--- a/dom/push/src/PushService.jsm
+++ b/dom/push/src/PushService.jsm
@@ -25,20 +25,16 @@ Cu.import("resource://gre/modules/Timer.
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 Cu.importGlobalProperties(["indexedDB"]);
 
 XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
                                    "@mozilla.org/network/dns-service;1",
                                    "nsIDNSService");
 
-XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
-                                   "@mozilla.org/settingsService;1",
-                                   "nsISettingsService");
-
 XPCOMUtils.defineLazyModuleGetter(this, "AlarmService",
                                   "resource://gre/modules/AlarmService.jsm");
 
 var threadManager = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
 
 this.EXPORTED_SYMBOLS = ["PushService"];
 
 const prefs = new Preferences("services.push.");
@@ -828,46 +824,23 @@ this.PushService = {
       debug("Push over an insecure connection (ws://) is not allowed!");
       return;
     }
     else {
       debug("Unsupported websocket scheme " + uri.scheme);
       return;
     }
 
-    // Read the APN data from the settings DB.
-    let lock = gSettingsService.createLock();
-    lock.get("ril.data.apnSettings", this);
-
     debug("serverURL: " + uri.spec);
     this._wsListener = new PushWebSocketListener(this);
     this._ws.protocol = "push-notification";
     this._ws.asyncOpen(uri, serverURL, this._wsListener, null);
     this._currentState = STATE_WAITING_FOR_WS_START;
   },
 
-  /**
-   * nsISettingsServiceCallback
-   */
-  handle: function(name, result) {
-    if (name !== "ril.data.apnSettings" || !result) {
-      return;
-    }
-    let apn = result[0].filter(function(e) {
-      return e.types[0] === "default";
-    });
-    if (apn.length === 0 || !apn[0].apn) {
-      this._apnDomain = null;
-      debug("No APN Domain found. No netid support");
-      return;
-    }
-    this._apnDomain = apn[0].apn;
-    debug("APN Domain: " + this._apnDomain);
-  },
-
   _startListeningIfChannelsPresent: function() {
     // Check to see if we need to do anything.
     this._db.getAllChannelIDs(function(channelIDs) {
       if (channelIDs.length > 0) {
         this._beginWSSetup();
       }
     }.bind(this));
   },
@@ -1756,17 +1729,17 @@ this.PushService = {
 
     if (typeof callback !== 'function') {
       throw new Error("No callback method. Aborting push agent !");
     }
 
     var networkInfo = this._getNetworkInformation();
 
     if (networkInfo.ip) {
-      this._getMobileNetworkId(function(netid) {
+      this._getMobileNetworkId(networkInfo, function(netid) {
         debug("Recovered netID = " + netid);
         callback({
           mcc: networkInfo.mcc,
           mnc: networkInfo.mnc,
           ip:  networkInfo.ip,
           netid: netid
         });
       });
@@ -1780,18 +1753,25 @@ this.PushService = {
     try {
       Cc["@mozilla.org/network/manager;1"].getService(Ci.nsINetworkManager);
       return "network-active-changed";
     } catch (e) {
       return "network:offline-status-changed";
     }
   },
 
-  // Get the mobile network ID (netid)
-  _getMobileNetworkId: function(callback) {
+  /*
+   * Get the mobile network ID (netid)
+   *
+   * @param networkInfo
+   *        Network information object { mcc, mnc, ip, port }
+   * @param callback
+   *        Callback function to invoke with the netid or null if not found
+   */
+  _getMobileNetworkId: function(networkInfo, callback) {
     if (typeof callback !== 'function') {
       return;
     }
 
     function queryDNSForDomain(domain) {
       debug("[_getMobileNetworkId:queryDNSForDomain] Querying DNS for " +
         domain);
       let netIDDNSListener = {
@@ -1807,23 +1787,15 @@ this.PushService = {
           }
         }
       };
       gDNSService.asyncResolve(domain, 0, netIDDNSListener,
         threadManager.currentThread);
       return [];
     }
 
-    debug("[_getMobileNetworkId:queryDNSForDomain] Getting mobile network ID (I'm " +
-       gDNSService.myHostName + ")");
+    debug("[_getMobileNetworkId:queryDNSForDomain] Getting mobile network ID");
 
-    let netidAddress = prefs.get("udp.well-known_netidAddress");
-    if (netidAddress.endsWith(".")) {
-      if (this._apnDomain) {
-        queryDNSForDomain(netidAddress + this._apnDomain, callback);
-      } else {
-        callback(null);   // No netid could be recovered
-      }
-    } else if(netidAddress) {
-      queryDNSForDomain(netidAddress, callback);
-    }
+    let netidAddress = "wakeup.mnc" + ("00" + networkInfo.mnc).slice(-3) +
+      ".mcc" + ("00" + networkInfo.mcc).slice(-3) + ".3gppnetwork.org";
+    queryDNSForDomain(netidAddress, callback);
   }
 }
--- a/dom/quota/moz.build
+++ b/dom/quota/moz.build
@@ -41,11 +41,11 @@ UNIFIED_SOURCES += [
 FAIL_ON_WARNINGS = True
 
 MSVC_ENABLE_PGO = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
-    '/caps/include',
+    '/caps',
 ]
 
--- a/dom/tests/browser/browser.ini
+++ b/dom/tests/browser/browser.ini
@@ -1,19 +1,21 @@
 [DEFAULT]
 skip-if = e10s # Bug ?????? - most of these tests fail for currently unknown reasons.
 support-files =
   browser_frame_elements.html
   browser_geolocation_privatebrowsing_page.html
   network_geolocation.sjs
   page_privatestorageevent.html
+  position.html
   test-console-api.html
   test_bug1004814.html
   worker_bug1004814.js
 
+[browser_bug1008941_dismissGeolocationHanger.js]
 [browser_test__content.js]
 [browser_ConsoleAPITests.js]
 [browser_ConsoleStorageAPITests.js]
 [browser_ConsoleStoragePBTest_perwindowpb.js]
 [browser_autofocus_background.js]
 [browser_autofocus_preference.js]
 [browser_bug396843.js]
 [browser_focus_steal_from_chrome.js]
new file mode 100644
--- /dev/null
+++ b/dom/tests/browser/browser_bug1008941_dismissGeolocationHanger.js
@@ -0,0 +1,61 @@
+/* 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/.
+ */
+"use strict";
+
+const TEST_URI = "http://example.com/" +
+                 "browser/dom/tests/browser/position.html";
+
+add_task(function testDismissHanger() {
+  info("Check that location is not shared when dismissing the geolocation hanger");
+
+  let promisePanelShown = waitForPanelShow();
+
+  gBrowser.selectedTab = gBrowser.addTab(TEST_URI);
+  yield waitForPageLoad(gBrowser.selectedTab);
+  info("Page was loaded");
+
+  yield promisePanelShown;
+  info("Panel is shown");
+
+  // click outside the Geolocation hanger to dismiss it
+  window.document.getElementById("nav-bar").click();
+  info("Clicked outside the Geolocation panel to dismiss it");
+
+  let result = gBrowser.getBrowserForTab(gBrowser.selectedTab)
+                       .contentDocument.body.innerHTML;
+  ok(result.contains("location..."), "Location is not shared");
+});
+
+add_task(function asyncCleanup() {
+  // close the tab
+  gBrowser.removeTab(gBrowser.selectedTab);
+  info("Cleanup: Closed the tab");
+});
+
+function waitForPageLoad(aTab) {
+  let deferred = Promise.defer();
+
+  function onTabLoad(event) {
+    aTab.linkedBrowser.removeEventListener("load", onTabLoad, true);
+    info("Load tab event received");
+    deferred.resolve();
+  }
+
+  aTab.linkedBrowser.addEventListener("load", onTabLoad, true, true);
+  return deferred.promise;
+}
+
+function waitForPanelShow(aPanel) {
+  let deferred = Promise.defer();
+
+  function onPopupShown(event) {
+    PopupNotifications.panel.removeEventListener("popupshown", onPopupShown, true);
+    info("Popup shown event received");
+    deferred.resolve();
+  }
+
+  PopupNotifications.panel.addEventListener("popupshown", onPopupShown, true, true);
+  return deferred.promise;
+}
new file mode 100644
--- /dev/null
+++ b/dom/tests/browser/position.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en" dir="ltr">
+<head>
+  <script type="text/javascript">
+    var result = null;
+
+    function handlePosition(position) {
+      result.innerHTML = position.coords.latitude + " " + position.coords.longitude;
+    }
+
+    function handleError(error) {
+      result.innerHTML = error.message;
+    }
+
+    function init() {
+      result = document.getElementById("result");
+
+      if (navigator.geolocation)
+        navigator.geolocation.getCurrentPosition(handlePosition, handleError);
+      else
+        result.innerHTML = "not available";
+    }
+
+  </script>
+</head>
+<body onload="init()">
+  <p id="result">location...</p>
+</body>
+</html>
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -811,16 +811,18 @@ var interfaceNamesInGlobalScope =
     "ProcessingInstruction",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ProgressEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Promise",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PropertyNodeList",
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    "RadioNodeList",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Range",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "RecordErrorEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Rect",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "RGBColor",
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/dom/webidl/HTMLFormControlsCollection.webidl
+++ b/dom/webidl/HTMLFormControlsCollection.webidl
@@ -6,14 +6,12 @@
  * The origin of this IDL file is
  * http://www.whatwg.org/specs/web-apps/current-work/#htmlformcontrolscollection
  *
  * © Copyright 2004-2013 Apple Computer, Inc., Mozilla Foundation, and
  * Opera Software ASA. You are granted a license to use, reproduce
  * and create derivative works of this document.
  */
 
-typedef NodeList RadioNodeList;
-
 interface HTMLFormControlsCollection : HTMLCollection {
   // inherits length and item()
   /* legacycaller */ getter (RadioNodeList or Element)? namedItem(DOMString name); // shadows inherited namedItem()
 };
--- a/dom/webidl/HTMLMediaElement.webidl
+++ b/dom/webidl/HTMLMediaElement.webidl
@@ -139,23 +139,25 @@ partial interface HTMLMediaElement {
 };
 
 enum MediaWaitingFor {
   "none",
   "data",
   "key"
 };
 
+#ifdef MOZ_EME
 // Encrypted Media Extensions
 partial interface HTMLMediaElement {
   [Pref="media.eme.enabled"]
   readonly attribute MediaKeys? mediaKeys;
-  
+
   // Promise<any>
   [Pref="media.eme.enabled", Throws, NewObject]
   Promise setMediaKeys(MediaKeys? mediaKeys);
-  
+
   [Pref="media.eme.enabled"]
   attribute EventHandler onneedkey;
 
   [Pref="media.eme.enabled"]
   readonly attribute MediaWaitingFor waitingFor;
 };
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/webidl/RadioNodeList.webidl
@@ -0,0 +1,16 @@
+/* -*- Mode: IDL; 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/.
+ *
+ * The origin of this IDL file is
+ * http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#htmlformcontrolscollection-0
+ *
+ * © Copyright 2004-2014 Apple Computer, Inc., Mozilla Foundation, and
+ * Opera Software ASA. You are granted a license to use, reproduce
+ * and create derivative works of this document.
+ */
+
+interface RadioNodeList : NodeList {
+  attribute DOMString value;
+};
--- a/dom/webidl/SpeechRecognition.webidl
+++ b/dom/webidl/SpeechRecognition.webidl
@@ -24,17 +24,17 @@ interface SpeechRecognition : EventTarge
     attribute boolean interimResults;
     [Throws]
     attribute unsigned long maxAlternatives;
     [Throws]
     attribute DOMString serviceURI;
 
     // methods to drive the speech interaction
     [Throws]
-    void start();
+    void start(optional MediaStream stream);
     void stop();
     void abort();
 
     // event methods
     attribute EventHandler onaudiostart;
     attribute EventHandler onsoundstart;
     attribute EventHandler onspeechstart;
     attribute EventHandler onspeechend;
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -5,16 +5,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 GENERATED_WEBIDL_FILES = [
     'CSS2Properties.webidl',
 ]
 
 PREPROCESSED_WEBIDL_FILES = [
     'Crypto.webidl',
+    'HTMLMediaElement.webidl',
     'Navigator.webidl',
     'Window.webidl',
 ]
 
 WEBIDL_FILES = [
     'AbstractWorker.webidl',
     'ActivityRequestHandler.webidl',
     'AlarmsManager.webidl',
@@ -164,17 +165,16 @@ WEBIDL_FILES = [
     'HTMLIFrameElement.webidl',
     'HTMLImageElement.webidl',
     'HTMLInputElement.webidl',
     'HTMLLabelElement.webidl',
     'HTMLLegendElement.webidl',
     'HTMLLIElement.webidl',
     'HTMLLinkElement.webidl',
     'HTMLMapElement.webidl',
-    'HTMLMediaElement.webidl',
     'HTMLMenuElement.webidl',
     'HTMLMenuItemElement.webidl',
     'HTMLMetaElement.webidl',
     'HTMLMeterElement.webidl',
     'HTMLModElement.webidl',
     'HTMLObjectElement.webidl',
     'HTMLOListElement.webidl',
     'HTMLOptGroupElement.webidl',
@@ -232,21 +232,16 @@ WEBIDL_FILES = [
     'KeyboardEvent.webidl',
     'KeyEvent.webidl',
     'LegacyQueryInterface.webidl',
     'LinkStyle.webidl',
     'LocalMediaStream.webidl',
     'Location.webidl',
     'MediaElementAudioSourceNode.webidl',
     'MediaError.webidl',
-    'MediaKeyError.webidl',
-    'MediaKeyMessageEvent.webidl',
-    'MediaKeyNeededEvent.webidl',
-    'MediaKeys.webidl',
-    'MediaKeySession.webidl',
     'MediaList.webidl',
     'MediaQueryList.webidl',
     'MediaRecorder.webidl',
     'MediaSource.webidl',
     'MediaStream.webidl',
     'MediaStreamAudioDestinationNode.webidl',
     'MediaStreamAudioSourceNode.webidl',
     'MediaStreamTrack.webidl',
@@ -299,16 +294,17 @@ WEBIDL_FILES = [
     'PluginArray.webidl',
     'PointerEvent.webidl',
     'Position.webidl',
     'PositionError.webidl',
     'ProcessingInstruction.webidl',
     'Promise.webidl',
     'PromiseDebugging.webidl',
     'PushManager.webidl',
+    'RadioNodeList.webidl',
     'Range.webidl',
     'Rect.webidl',
     'ResourceStats.webidl',
     'ResourceStatsManager.webidl',
     'RGBColor.webidl',
     'RTCConfiguration.webidl',
     'RTCIceCandidate.webidl',
     'RTCIdentityAssertion.webidl',
@@ -726,8 +722,17 @@ if CONFIG['MOZ_BUILD_APP'] in ['browser'
     WEBIDL_FILES += [
         'BrowserFeedWriter.webidl',
     ]
 
 if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']:
     WEBIDL_FILES += [
         'External.webidl',
     ]
+
+if CONFIG['MOZ_EME']:
+    WEBIDL_FILES += [
+        'MediaKeyError.webidl',
+        'MediaKeyMessageEvent.webidl',
+        'MediaKeyNeededEvent.webidl',
+        'MediaKeys.webidl',
+        'MediaKeySession.webidl',
+    ]
deleted file mode 100644
--- a/editor/idl/moz.build
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-XPIDL_SOURCES += [
-    'nsIContentFilter.idl',
-    'nsIDocumentStateListener.idl',
-    'nsIEditActionListener.idl',
-    'nsIEditor.idl',
-    'nsIEditorIMESupport.idl',
-    'nsIEditorMailSupport.idl',
-    'nsIEditorObserver.idl',
-    'nsIEditorSpellCheck.idl',
-    'nsIEditorStyleSheets.idl',
-    'nsIHTMLAbsPosEditor.idl',
-    'nsIHTMLEditor.idl',
-    'nsIHTMLInlineTableEditor.idl',
-    'nsIHTMLObjectResizeListener.idl',
-    'nsIHTMLObjectResizer.idl',
-    'nsIPlaintextEditor.idl',
-    'nsITableEditor.idl',
-    'nsIURIRefObject.idl',
-    'nsPIEditorTransaction.idl',
-]
-
-XPIDL_MODULE = 'editor'
-
--- a/editor/moz.build
+++ b/editor/moz.build
@@ -1,18 +1,43 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 PARALLEL_DIRS += [
-    'public',
-    'idl',
     'txtsvc',
     'libeditor',
     'txmgr',
     'composer',
 ]
 
+XPIDL_SOURCES += [
+    'nsIContentFilter.idl',
+    'nsIDocumentStateListener.idl',
+    'nsIEditActionListener.idl',
+    'nsIEditor.idl',
+    'nsIEditorIMESupport.idl',
+    'nsIEditorMailSupport.idl',
+    'nsIEditorObserver.idl',
+    'nsIEditorSpellCheck.idl',
+    'nsIEditorStyleSheets.idl',
+    'nsIHTMLAbsPosEditor.idl',
+    'nsIHTMLEditor.idl',
+    'nsIHTMLInlineTableEditor.idl',
+    'nsIHTMLObjectResizeListener.idl',
+    'nsIHTMLObjectResizer.idl',
+    'nsIPlaintextEditor.idl',
+    'nsITableEditor.idl',
+    'nsIURIRefObject.idl',
+    'nsPIEditorTransaction.idl',
+]
+
+XPIDL_MODULE = 'editor'
+
+EXPORTS += [
+    'nsEditorCID.h',
+]
+
 EXTRA_JS_MODULES += [
     'AsyncSpellCheckTestHelper.jsm',
 ]
rename from editor/public/nsEditorCID.h
rename to editor/nsEditorCID.h
rename from editor/idl/nsIContentFilter.idl
rename to editor/nsIContentFilter.idl
rename from editor/idl/nsIDocumentStateListener.idl
rename to editor/nsIDocumentStateListener.idl
rename from editor/idl/nsIEditActionListener.idl
rename to editor/nsIEditActionListener.idl
rename from editor/idl/nsIEditor.idl
rename to editor/nsIEditor.idl
rename from editor/idl/nsIEditorIMESupport.idl
rename to editor/nsIEditorIMESupport.idl
rename from editor/idl/nsIEditorMailSupport.idl
rename to editor/nsIEditorMailSupport.idl
rename from editor/idl/nsIEditorObserver.idl
rename to editor/nsIEditorObserver.idl
rename from editor/idl/nsIEditorSpellCheck.idl
rename to editor/nsIEditorSpellCheck.idl
rename from editor/idl/nsIEditorStyleSheets.idl
rename to editor/nsIEditorStyleSheets.idl
rename from editor/idl/nsIHTMLAbsPosEditor.idl
rename to editor/nsIHTMLAbsPosEditor.idl
rename from editor/idl/nsIHTMLEditor.idl
rename to editor/nsIHTMLEditor.idl
rename from editor/idl/nsIHTMLInlineTableEditor.idl
rename to editor/nsIHTMLInlineTableEditor.idl
rename from editor/idl/nsIHTMLObjectResizeListener.idl
rename to editor/nsIHTMLObjectResizeListener.idl
rename from editor/idl/nsIHTMLObjectResizer.idl
rename to editor/nsIHTMLObjectResizer.idl
rename from editor/idl/nsIPlaintextEditor.idl
rename to editor/nsIPlaintextEditor.idl
rename from editor/idl/nsITableEditor.idl
rename to editor/nsITableEditor.idl
rename from editor/idl/nsIURIRefObject.idl
rename to editor/nsIURIRefObject.idl
rename from editor/idl/nsPIEditorTransaction.idl
rename to editor/nsPIEditorTransaction.idl
deleted file mode 100644
--- a/editor/public/moz.build
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-EXPORTS += [
-    'nsEditorCID.h',
-]
-
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -120,16 +120,17 @@ AppendToString(std::stringstream& aStrea
 {
   aStream << pfx;
   AppendToString(aStream, m.mCompositionBounds, "{ cb=");
   AppendToString(aStream, m.mScrollableRect, " sr=");
   AppendToString(aStream, m.GetScrollOffset(), " s=");
   AppendToString(aStream, m.mDisplayPort, " dp=");
   AppendToString(aStream, m.mCriticalDisplayPort, " cdp=");
   if (!detailed) {
+    AppendToString(aStream, m.GetScrollId(), " scrollId=");
     aStream << nsPrintfCString(" z=%.3f }", m.GetZoom().scale).get();
   } else {
     AppendToString(aStream, m.GetDisplayPortMargins(), " dpm=");
     aStream << nsPrintfCString(" um=%d", m.GetUseDisplayPortMargins()).get();
     AppendToString(aStream, m.GetRootCompositionSize(), " rcs=");
     AppendToString(aStream, m.mViewport, " v=");
     aStream << nsPrintfCString(" z=(ld=%.3f r=%.3f cr=%.3f z=%.3f ts=%.3f)",
             m.mDevPixelsPerCSSPixel.scale, m.mResolution.scale,
--- a/gfx/layers/LayersLogging.h
+++ b/gfx/layers/LayersLogging.h
@@ -146,12 +146,22 @@ AppendToString(std::stringstream& aStrea
 void
 AppendToString(std::stringstream& aStream, mozilla::layers::TextureFlags flags,
                const char* pfx="", const char* sfx="");
 
 void
 AppendToString(std::stringstream& aStream, mozilla::gfx::SurfaceFormat format,
                const char* pfx="", const char* sfx="");
 
+// Sometimes, you just want a string from a single value.
+template <typename T>
+std::string
+Stringify(const T& obj)
+{
+  std::stringstream ss;
+  AppendToString(ss, obj);
+  return ss.str();
+}
+
 } // namespace
 } // namespace
 
 #endif /* GFX_LAYERSLOGGING_H */
--- a/gfx/layers/TiledLayerBuffer.h
+++ b/gfx/layers/TiledLayerBuffer.h
@@ -25,28 +25,19 @@
 namespace mozilla {
 namespace layers {
 
 // You can enable all the TILING_LOG print statements by
 // changing the 0 to a 1 in the following #define.
 #define ENABLE_TILING_LOG 0
 
 #if ENABLE_TILING_LOG
-#  define TILING_LOG(_args) printf_stderr _args ;
-#  define TILING_LOG_OBJ(_args, obj) \
-    { \
-    std::stringstream ss; \
-    AppendToString(ss, obj); \
-    nsAutoCString tmpstr; \
-    tmpstr = ss.str().c_str(); \
-    printf_stderr _args ; \
-    }
+#  define TILING_LOG(...) printf_stderr(__VA_ARGS__);
 #else
-#  define TILING_LOG(_args)
-#  define TILING_LOG_OBJ(_args, obj)
+#  define TILING_LOG(...)
 #endif
 
 // An abstract implementation of a tile buffer. This code covers the logic of
 // moving and reusing tiles and leaves the validation up to the implementor. To
 // avoid the overhead of virtual dispatch, we employ the curiously recurring
 // template pattern.
 //
 // Tiles are aligned to a grid with one of the grid points at (0,0) and other
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -718,17 +718,16 @@ AsyncPanZoomController::AsyncPanZoomCont
      mLastAsyncScrollTime(GetFrameTime()),
      mLastAsyncScrollOffset(0, 0),
      mCurrentAsyncScrollOffset(0, 0),
      mAsyncScrollTimeoutTask(nullptr),
      mTouchBlockBalance(0),
      mTreeManager(aTreeManager),
      mScrollParentId(FrameMetrics::NULL_SCROLL_ID),
      mAPZCId(sAsyncPanZoomControllerCount++),
-     mSharedFrameMetricsBuffer(nullptr),
      mSharedLock(nullptr)
 {
   MOZ_COUNT_CTOR(AsyncPanZoomController);
 
   if (aGestures == USE_GESTURE_DETECTOR) {
     mGestureEventListener = new GestureEventListener(this);
   }
 }
@@ -786,17 +785,16 @@ AsyncPanZoomController::Destroy()
   PCompositorParent* compositor = GetSharedFrameMetricsCompositor();
   // Only send the release message if the SharedFrameMetrics has been created.
   if (compositor && mSharedFrameMetricsBuffer) {
     unused << compositor->SendReleaseSharedCompositorFrameMetrics(mFrameMetrics.GetScrollId(), mAPZCId);
   }
 
   { // scope the lock
     ReentrantMonitorAutoEnter lock(mMonitor);
-    delete mSharedFrameMetricsBuffer;
     mSharedFrameMetricsBuffer = nullptr;
     delete mSharedLock;
     mSharedLock = nullptr;
   }
 }
 
 bool
 AsyncPanZoomController::IsDestroyed()
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -963,17 +963,17 @@ private:
    * The functions and members in this section are used for sharing the
    * FrameMetrics across processes for the progressive tiling code.
    */
 private:
   /* Unique id assigned to each APZC. Used with ViewID to uniquely identify
    * shared FrameMeterics used in progressive tile painting. */
   const uint32_t mAPZCId;
 
-  ipc::SharedMemoryBasic* mSharedFrameMetricsBuffer;
+  nsRefPtr<ipc::SharedMemoryBasic> mSharedFrameMetricsBuffer;
   CrossProcessMutex* mSharedLock;
   /**
    * Called when ever mFrameMetrics is updated so that if it is being
    * shared with the content process the shared FrameMetrics may be updated.
    */
   void UpdateSharedCompositorFrameMetrics();
   /**
    * Create a shared memory buffer for containing the FrameMetrics and
--- a/gfx/layers/apz/util/ActiveElementManager.cpp
+++ b/gfx/layers/apz/util/ActiveElementManager.cpp
@@ -113,16 +113,21 @@ ActiveElementManager::HandleTouchEnd(boo
   AEM_LOG("Touch end, aWasClick: %d\n", aWasClick);
 
   // If the touch was a click, make mTarget :active right away.
   // nsEventStateManager will reset the active element when processing
   // the mouse-down event generated by the click.
   CancelTask();
   if (aWasClick) {
     SetActive(mTarget);
+  } else {
+    // We might reach here if mCanBePan was false on touch-start and
+    // so we set the element active right away. Now it turns out the
+    // action was not a click so we need to reset the active element.
+    ResetActive();
   }
 
   ResetTouchBlockState();
 }
 
 void
 ActiveElementManager::SetActive(dom::Element* aTarget)
 {
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -651,16 +651,18 @@ PixmanTransform(const gfxImageSurface* a
 
   NS_ABORT_IF_FALSE(src && dest, "Failed to create pixman images?");
 
   pixman_transform pixTransform = BasicLayerManager_Matrix3DToPixman(aTransform);
   pixman_transform pixTransformInverted;
 
   // If the transform is singular then nothing would be drawn anyway, return here
   if (!pixman_transform_invert(&pixTransformInverted, &pixTransform)) {
+    pixman_image_unref(dest);
+    pixman_image_unref(src);
     return;
   }
   pixman_image_set_transform(src, &pixTransformInverted);
 
   pixman_image_composite32(PIXMAN_OP_SRC,
                            src,
                            nullptr,
                            dest,
--- a/gfx/layers/client/ClientTiledThebesLayer.cpp
+++ b/gfx/layers/client/ClientTiledThebesLayer.cpp
@@ -132,18 +132,18 @@ ClientTiledThebesLayer::BeginPaint()
 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_B2G)
     // Both Android and b2g are guaranteed to have a displayport set, so this
     // should never happen.
     NS_WARNING("Tiled Thebes layer with no scrollable container ancestor");
 #endif
     return;
   }
 
-  TILING_LOG(("TILING %p: Found scrollAncestor %p and displayPortAncestor %p\n", this,
-    scrollAncestor, displayPortAncestor));
+  TILING_LOG("TILING %p: Found scrollAncestor %p and displayPortAncestor %p\n", this,
+    scrollAncestor, displayPortAncestor);
 
   const FrameMetrics& scrollMetrics = scrollAncestor->GetFrameMetrics();
   const FrameMetrics& displayportMetrics = displayPortAncestor->GetFrameMetrics();
 
   // Calculate the transform required to convert ParentLayer space of our
   // display port ancestor to the Layer space of this layer.
   gfx3DMatrix transformDisplayPortToLayer =
     GetTransformToAncestorsParentLayer(this, displayPortAncestor).Inverse();
@@ -156,33 +156,33 @@ ClientTiledThebesLayer::BeginPaint()
 
   // Compute the critical display port that applies to this layer in the
   // LayoutDevice space of this layer.
   ParentLayerRect criticalDisplayPort =
     (displayportMetrics.mCriticalDisplayPort * displayportMetrics.GetZoomToParent())
     + displayportMetrics.mCompositionBounds.TopLeft();
   mPaintData.mCriticalDisplayPort = RoundedOut(
     ApplyParentLayerToLayerTransform(transformDisplayPortToLayer, criticalDisplayPort));
-  TILING_LOG_OBJ(("TILING %p: Critical displayport %s\n", this, tmpstr.get()), mPaintData.mCriticalDisplayPort);
+  TILING_LOG("TILING %p: Critical displayport %s\n", this, Stringify(mPaintData.mCriticalDisplayPort).c_str());
 
   // Store the resolution from the displayport ancestor layer. Because this is Gecko-side,
   // before any async transforms have occurred, we can use the zoom for this.
   mPaintData.mResolution = displayportMetrics.GetZoomToParent();
-  TILING_LOG(("TILING %p: Resolution %f\n", this, mPaintData.mResolution.scale));
+  TILING_LOG("TILING %p: Resolution %f\n", this, mPaintData.mResolution.scale);
 
   // Store the applicable composition bounds in this layer's Layer units.
   mPaintData.mTransformToCompBounds =
     GetTransformToAncestorsParentLayer(this, scrollAncestor);
   mPaintData.mCompositionBounds = ApplyParentLayerToLayerTransform(
     mPaintData.mTransformToCompBounds.Inverse(), scrollMetrics.mCompositionBounds);
-  TILING_LOG_OBJ(("TILING %p: Composition bounds %s\n", this, tmpstr.get()), mPaintData.mCompositionBounds);
+  TILING_LOG("TILING %p: Composition bounds %s\n", this, Stringify(mPaintData.mCompositionBounds).c_str());
 
   // Calculate the scroll offset since the last transaction
   mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoomToParent();
-  TILING_LOG_OBJ(("TILING %p: Scroll offset %s\n", this, tmpstr.get()), mPaintData.mScrollOffset);
+  TILING_LOG("TILING %p: Scroll offset %s\n", this, Stringify(mPaintData.mScrollOffset).c_str());
 }
 
 bool
 ClientTiledThebesLayer::UseFastPath()
 {
   const FrameMetrics& parentMetrics = GetParent()->GetFrameMetrics();
   bool multipleTransactionsNeeded = gfxPrefs::UseProgressiveTilePainting()
                                  || gfxPrefs::UseLowPrecisionBuffer()
@@ -211,31 +211,31 @@ ClientTiledThebesLayer::RenderHighPrecis
     // We clip the old valid region to the visible region, as it only gets
     // used to decide stale content (currently valid and previously visible)
     nsIntRegion oldValidRegion = mContentClient->mTiledBuffer.GetValidRegion();
     oldValidRegion.And(oldValidRegion, mVisibleRegion);
     if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
       oldValidRegion.And(oldValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
     }
 
-    TILING_LOG_OBJ(("TILING %p: Progressive update with old valid region %s\n", this, tmpstr.get()), oldValidRegion);
+    TILING_LOG("TILING %p: Progressive update with old valid region %s\n", this, Stringify(oldValidRegion).c_str());
 
     return mContentClient->mTiledBuffer.ProgressiveUpdate(mValidRegion, aInvalidRegion,
                       oldValidRegion, &mPaintData, aCallback, aCallbackData);
   }
 
   // Otherwise do a non-progressive paint
 
   mValidRegion = mVisibleRegion;
   if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
     mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
   }
 
-  TILING_LOG_OBJ(("TILING %p: Non-progressive paint invalid region %s\n", this, tmpstr.get()), aInvalidRegion);
-  TILING_LOG_OBJ(("TILING %p: Non-progressive paint new valid region %s\n", this, tmpstr.get()), mValidRegion);
+  TILING_LOG("TILING %p: Non-progressive paint invalid region %s\n", this, Stringify(aInvalidRegion).c_str());
+  TILING_LOG("TILING %p: Non-progressive paint new valid region %s\n", this, Stringify(mValidRegion).c_str());
 
   mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
   mContentClient->mTiledBuffer.PaintThebes(mValidRegion, aInvalidRegion, aCallback, aCallbackData);
   return true;
 }
 
 bool
 ClientTiledThebesLayer::RenderLowPrecision(nsIntRegion& aInvalidRegion,
@@ -267,30 +267,30 @@ ClientTiledThebesLayer::RenderLowPrecisi
       mLowPrecisionValidRegion.And(mLowPrecisionValidRegion, mVisibleRegion);
     }
     mPaintData.mLowPrecisionPaintCount++;
 
     // Remove the valid high-precision region from the invalid low-precision
     // region. We don't want to spend time drawing things twice.
     aInvalidRegion.Sub(aInvalidRegion, mValidRegion);
 
-    TILING_LOG_OBJ(("TILING %p: Progressive paint: low-precision invalid region is %s\n", this, tmpstr.get()), aInvalidRegion);
-    TILING_LOG_OBJ(("TILING %p: Progressive paint: low-precision old valid region is %s\n", this, tmpstr.get()), oldValidRegion);
+    TILING_LOG("TILING %p: Progressive paint: low-precision invalid region is %s\n", this, Stringify(aInvalidRegion).c_str());
+    TILING_LOG("TILING %p: Progressive paint: low-precision old valid region is %s\n", this, Stringify(oldValidRegion).c_str());
 
     if (!aInvalidRegion.IsEmpty()) {
       updatedBuffer = mContentClient->mLowPrecisionTiledBuffer.ProgressiveUpdate(
                             mLowPrecisionValidRegion, aInvalidRegion, oldValidRegion,
                             &mPaintData, aCallback, aCallbackData);
     }
 
-    TILING_LOG_OBJ(("TILING %p: Progressive paint: low-precision new valid region is %s\n", this, tmpstr.get()), mLowPrecisionValidRegion);
+    TILING_LOG("TILING %p: Progressive paint: low-precision new valid region is %s\n", this, Stringify(mLowPrecisionValidRegion).c_str());
     return updatedBuffer;
   }
   if (!mLowPrecisionValidRegion.IsEmpty()) {
-    TILING_LOG(("TILING %p: Clearing low-precision buffer\n", this));
+    TILING_LOG("TILING %p: Clearing low-precision buffer\n", this);
     // Clear the low precision tiled buffer.
     mLowPrecisionValidRegion.SetEmpty();
     mContentClient->mLowPrecisionTiledBuffer.ResetPaintedAndValidState();
     // Return true here so we send a Painted callback after clearing the valid
     // region of the low precision buffer. This allows the shadow buffer's valid
     // region to be updated and the associated resources to be freed.
     return true;
   }
@@ -298,17 +298,17 @@ ClientTiledThebesLayer::RenderLowPrecisi
 }
 
 void
 ClientTiledThebesLayer::EndPaint()
 {
   mPaintData.mLastScrollOffset = mPaintData.mScrollOffset;
   mPaintData.mPaintFinished = true;
   mPaintData.mFirstPaint = false;
-  TILING_LOG(("TILING %p: Paint finished\n", this));
+  TILING_LOG("TILING %p: Paint finished\n", this);
 }
 
 void
 ClientTiledThebesLayer::RenderLayer()
 {
   LayerManager::DrawThebesLayerCallback callback =
     ClientManager()->GetThebesLayerCallback();
   void *data = ClientManager()->GetThebesLayerCallbackData();
@@ -324,36 +324,36 @@ ClientTiledThebesLayer::RenderLayer()
     ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
     MOZ_ASSERT(mContentClient->GetForwarder());
   }
 
   if (mContentClient->mTiledBuffer.HasFormatChanged()) {
     mValidRegion = nsIntRegion();
   }
 
-  TILING_LOG_OBJ(("TILING %p: Initial visible region %s\n", this, tmpstr.get()), mVisibleRegion);
-  TILING_LOG_OBJ(("TILING %p: Initial valid region %s\n", this, tmpstr.get()), mValidRegion);
-  TILING_LOG_OBJ(("TILING %p: Initial low-precision valid region %s\n", this, tmpstr.get()), mLowPrecisionValidRegion);
+  TILING_LOG("TILING %p: Initial visible region %s\n", this, Stringify(mVisibleRegion).c_str());
+  TILING_LOG("TILING %p: Initial valid region %s\n", this, Stringify(mValidRegion).c_str());
+  TILING_LOG("TILING %p: Initial low-precision valid region %s\n", this, Stringify(mLowPrecisionValidRegion).c_str());
 
   nsIntRegion invalidRegion;
   invalidRegion.Sub(mVisibleRegion, mValidRegion);
   if (invalidRegion.IsEmpty()) {
     EndPaint();
     return;
   }
 
   if (!ClientManager()->IsRepeatTransaction()) {
     // Only paint the mask layer on the first transaction.
     if (GetMaskLayer()) {
       ToClientLayer(GetMaskLayer())->RenderLayer();
     }
 
     // In some cases we can take a fast path and just be done with it.
     if (UseFastPath()) {
-      TILING_LOG(("TILING %p: Taking fast-path\n", this));
+      TILING_LOG("TILING %p: Taking fast-path\n", this);
       mValidRegion = mVisibleRegion;
       mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion, callback, data);
       ClientManager()->Hold(this);
       mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);
       return;
     }
 
     // For more complex cases we need to calculate a bunch of metrics before we
@@ -367,33 +367,33 @@ ClientTiledThebesLayer::RenderLayer()
     // critical displayport are discarded on the first update. Also make sure that we
     // only draw stuff inside the critical displayport on the first update.
     mValidRegion.And(mValidRegion, mVisibleRegion);
     if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
       mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
       invalidRegion.And(invalidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
     }
 
-    TILING_LOG_OBJ(("TILING %p: First-transaction valid region %s\n", this, tmpstr.get()), mValidRegion);
-    TILING_LOG_OBJ(("TILING %p: First-transaction invalid region %s\n", this, tmpstr.get()), invalidRegion);
+    TILING_LOG("TILING %p: First-transaction valid region %s\n", this, Stringify(mValidRegion).c_str());
+    TILING_LOG("TILING %p: First-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str());
   } else {
     if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
       invalidRegion.And(invalidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
     }
-    TILING_LOG_OBJ(("TILING %p: Repeat-transaction invalid region %s\n", this, tmpstr.get()), invalidRegion);
+    TILING_LOG("TILING %p: Repeat-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str());
   }
 
   nsIntRegion lowPrecisionInvalidRegion;
   if (gfxPrefs::UseLowPrecisionBuffer()) {
     // Calculate the invalid region for the low precision buffer. Make sure
     // to remove the valid high-precision area so we don't double-paint it.
     lowPrecisionInvalidRegion.Sub(mVisibleRegion, mLowPrecisionValidRegion);
     lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, mValidRegion);
   }
-  TILING_LOG_OBJ(("TILING %p: Low-precision invalid region %s\n", this, tmpstr.get()), lowPrecisionInvalidRegion);
+  TILING_LOG("TILING %p: Low-precision invalid region %s\n", this, Stringify(lowPrecisionInvalidRegion).c_str());
 
   bool updatedHighPrecision = RenderHighPrecision(invalidRegion, callback, data);
   if (updatedHighPrecision) {
     ClientManager()->Hold(this);
     mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);
 
     if (!mPaintData.mPaintFinished) {
       // There is still more high-res stuff to paint, so we're not
@@ -409,17 +409,17 @@ ClientTiledThebesLayer::RenderLayer()
     return;
   }
 
   if (updatedHighPrecision) {
     // If there are low precision updates, but we just did some high-precision
     // updates, then mark the paint as unfinished and request a repeat transaction.
     // This is so that we don't perform low-precision updates in the same transaction
     // as high-precision updates.
-    TILING_LOG(("TILING %p: Scheduling repeat transaction for low-precision painting\n", this));
+    TILING_LOG("TILING %p: Scheduling repeat transaction for low-precision painting\n", this);
     ClientManager()->SetRepeatTransaction();
     mPaintData.mLowPrecisionPaintCount = 1;
     mPaintData.mPaintFinished = false;
     return;
   }
 
   bool updatedLowPrecision = RenderLowPrecision(lowPrecisionInvalidRegion, callback, data);
   if (updatedLowPrecision) {
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -182,28 +182,28 @@ SharedFrameMetricsHelper::UpdateFromComp
 
   aViewTransform = ComputeViewTransform(contentMetrics, compositorMetrics);
 
   // Reset the checkerboard risk flag when switching to low precision
   // rendering.
   if (aLowPrecision && !mLastProgressiveUpdateWasLowPrecision) {
     // Skip low precision rendering until we're at risk of checkerboarding.
     if (!mProgressiveUpdateWasInDanger) {
-      TILING_LOG(("TILING: Aborting low-precision rendering because not at risk of checkerboarding\n"));
+      TILING_LOG("TILING: Aborting low-precision rendering because not at risk of checkerboarding\n");
       return true;
     }
     mProgressiveUpdateWasInDanger = false;
   }
   mLastProgressiveUpdateWasLowPrecision = aLowPrecision;
 
   // Always abort updates if the resolution has changed. There's no use
   // in drawing at the incorrect resolution.
   if (!FuzzyEquals(compositorMetrics.GetZoom().scale, contentMetrics.GetZoom().scale)) {
-    TILING_LOG(("TILING: Aborting because resolution changed from %f to %f\n",
-        contentMetrics.GetZoom().scale, compositorMetrics.GetZoom().scale));
+    TILING_LOG("TILING: Aborting because resolution changed from %f to %f\n",
+        contentMetrics.GetZoom().scale, compositorMetrics.GetZoom().scale);
     return true;
   }
 
   // Never abort drawing if we can't be sure we've sent a more recent
   // display-port. If we abort updating when we shouldn't, we can end up
   // with blank regions on the screen and we open up the risk of entering
   // an endless updating cycle.
   if (fabsf(contentMetrics.GetScrollOffset().x - compositorMetrics.GetScrollOffset().x) <= 2 &&
@@ -232,17 +232,17 @@ SharedFrameMetricsHelper::UpdateFromComp
       mProgressiveUpdateWasInDanger = true;
       return true;
     }
   }
 
   // Abort drawing stale low-precision content if there's a more recent
   // display-port in the pipeline.
   if (aLowPrecision && !aHasPendingNewThebesContent) {
-    TILING_LOG(("TILING: Aborting low-precision because of new pending content\n"));
+    TILING_LOG("TILING: Aborting low-precision because of new pending content\n");
     return true;
   }
 
   return false;
 }
 
 bool
 SharedFrameMetricsHelper::AboutToCheckerboard(const FrameMetrics& aContentMetrics,
@@ -267,20 +267,20 @@ SharedFrameMetricsHelper::AboutToChecker
 
   // Clamp both rects to the scrollable rect, because having either of those
   // exceed the scrollable rect doesn't make sense, and could lead to false
   // positives.
   painted = painted.Intersect(aContentMetrics.mScrollableRect);
   showing = showing.Intersect(aContentMetrics.mScrollableRect);
 
   if (!painted.Contains(showing)) {
-    TILING_LOG_OBJ(("TILING: About to checkerboard; content %s\n", tmpstr.get()), aContentMetrics);
-    TILING_LOG_OBJ(("TILING: About to checkerboard; painted %s\n", tmpstr.get()), painted);
-    TILING_LOG_OBJ(("TILING: About to checkerboard; compositor %s\n", tmpstr.get()), aCompositorMetrics);
-    TILING_LOG_OBJ(("TILING: About to checkerboard; showing %s\n", tmpstr.get()), showing);
+    TILING_LOG("TILING: About to checkerboard; content %s\n", Stringify(aContentMetrics).c_str());
+    TILING_LOG("TILING: About to checkerboard; painted %s\n", Stringify(painted).c_str());
+    TILING_LOG("TILING: About to checkerboard; compositor %s\n", Stringify(aCompositorMetrics).c_str());
+    TILING_LOG("TILING: About to checkerboard; showing %s\n", Stringify(showing).c_str());
     return true;
   }
   return false;
 }
 
 ClientTiledLayerBuffer::ClientTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer,
                                              CompositableClient* aCompositableClient,
                                              ClientLayerManager* aManager,
@@ -706,18 +706,18 @@ ClientTiledLayerBuffer::GetSurfaceDescri
 }
 
 void
 ClientTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
                                    const nsIntRegion& aPaintRegion,
                                    LayerManager::DrawThebesLayerCallback aCallback,
                                    void* aCallbackData)
 {
-  TILING_LOG_OBJ(("TILING %p: PaintThebes painting region %s\n", mThebesLayer, tmpstr.get()), aPaintRegion);
-  TILING_LOG_OBJ(("TILING %p: PaintThebes new valid region %s\n", mThebesLayer, tmpstr.get()), aNewValidRegion);
+  TILING_LOG("TILING %p: PaintThebes painting region %s\n", mThebesLayer, Stringify(aPaintRegion).c_str());
+  TILING_LOG("TILING %p: PaintThebes new valid region %s\n", mThebesLayer, Stringify(aNewValidRegion).c_str());
 
   mCallback = aCallback;
   mCallbackData = aCallbackData;
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   long start = PR_IntervalNow();
 #endif
 
@@ -1037,17 +1037,17 @@ ClientTiledLayerBuffer::ComputeProgressi
   // assumption is that the contents is less important, so visual coherency
   // is lower priority than speed.
   bool drawingLowPrecision = IsLowPrecision();
 
   // Find out if we have any non-stale content to update.
   nsIntRegion staleRegion;
   staleRegion.And(aInvalidRegion, aOldValidRegion);
 
-  TILING_LOG_OBJ(("TILING %p: Progressive update stale region %s\n", mThebesLayer, tmpstr.get()), staleRegion);
+  TILING_LOG("TILING %p: Progressive update stale region %s\n", mThebesLayer, Stringify(staleRegion).c_str());
 
   ContainerLayer* scrollAncestor = nullptr;
   mThebesLayer->GetAncestorLayers(&scrollAncestor, nullptr);
 
   // Find out the current view transform to determine which tiles to draw
   // first, and see if we should just abort this paint. Aborting is usually
   // caused by there being an incoming, more relevant paint.
   ViewTransform viewTransform;
@@ -1069,17 +1069,17 @@ ClientTiledLayerBuffer::ComputeProgressi
   bool abortPaint =
     mSharedFrameMetricsHelper->UpdateFromCompositorFrameMetrics(
       scrollAncestor,
       !staleRegion.Contains(aInvalidRegion),
       drawingLowPrecision,
       viewTransform);
 #endif
 
-  TILING_LOG(("TILING %p: Progressive update view transform %f %f zoom %f abort %d\n", mThebesLayer, viewTransform.mTranslation.x, viewTransform.mTranslation.y, viewTransform.mScale.scale, abortPaint));
+  TILING_LOG("TILING %p: Progressive update view transform %f %f zoom %f abort %d\n", mThebesLayer, viewTransform.mTranslation.x, viewTransform.mTranslation.y, viewTransform.mScale.scale, abortPaint);
 
   if (abortPaint) {
     // We ignore if front-end wants to abort if this is the first,
     // non-low-precision paint, as in that situation, we're about to override
     // front-end's page/viewport metrics.
     if (!aPaintData->mFirstPaint || drawingLowPrecision) {
       PROFILER_LABEL("ClientTiledLayerBuffer", "ComputeProgressiveUpdateRegion",
         js::ProfileEntry::Category::GRAPHICS);
@@ -1089,17 +1089,17 @@ ClientTiledLayerBuffer::ComputeProgressi
     }
   }
 
   LayerRect transformedCompositionBounds =
     GetCompositorSideCompositionBounds(scrollAncestor,
                                        aPaintData->mTransformToCompBounds,
                                        viewTransform);
 
-  TILING_LOG_OBJ(("TILING %p: Progressive update transformed compositor bounds %s\n", mThebesLayer, tmpstr.get()), transformedCompositionBounds);
+  TILING_LOG("TILING %p: Progressive update transformed compositor bounds %s\n", mThebesLayer, Stringify(transformedCompositionBounds).c_str());
 
   // Compute a "coherent update rect" that we should paint all at once in a
   // single transaction. This is to avoid rendering glitches on animated
   // page content, and when layers change size/shape.
   // On Fennec uploads are more expensive because we're not using gralloc, so
   // we use a coherent update rect that is intersected with the screen at the
   // time of issuing the draw command. This will paint faster but also potentially
   // make the progressive paint more visible to the user while scrolling.
@@ -1108,40 +1108,40 @@ ClientTiledLayerBuffer::ComputeProgressi
   nsIntRect coherentUpdateRect(LayerIntRect::ToUntyped(RoundedOut(
 #ifdef MOZ_WIDGET_ANDROID
     transformedCompositionBounds.Intersect(aPaintData->mCompositionBounds)
 #else
     transformedCompositionBounds
 #endif
   )));
 
-  TILING_LOG_OBJ(("TILING %p: Progressive update final coherency rect %s\n", mThebesLayer, tmpstr.get()), coherentUpdateRect);
+  TILING_LOG("TILING %p: Progressive update final coherency rect %s\n", mThebesLayer, Stringify(coherentUpdateRect).c_str());
 
   aRegionToPaint.And(aInvalidRegion, coherentUpdateRect);
   aRegionToPaint.Or(aRegionToPaint, staleRegion);
   bool drawingStale = !aRegionToPaint.IsEmpty();
   if (!drawingStale) {
     aRegionToPaint = aInvalidRegion;
   }
 
   // Prioritise tiles that are currently visible on the screen.
   bool paintingVisible = false;
   if (aRegionToPaint.Intersects(coherentUpdateRect)) {
     aRegionToPaint.And(aRegionToPaint, coherentUpdateRect);
     paintingVisible = true;
   }
 
-  TILING_LOG_OBJ(("TILING %p: Progressive update final paint region %s\n", mThebesLayer, tmpstr.get()), aRegionToPaint);
+  TILING_LOG("TILING %p: Progressive update final paint region %s\n", mThebesLayer, Stringify(aRegionToPaint).c_str());
 
   // Paint area that's visible and overlaps previously valid content to avoid
   // visible glitches in animated elements, such as gifs.
   bool paintInSingleTransaction = paintingVisible && (drawingStale || aPaintData->mFirstPaint);
 
-  TILING_LOG(("TILING %p: paintingVisible %d drawingStale %d firstPaint %d singleTransaction %d\n",
-    mThebesLayer, paintingVisible, drawingStale, aPaintData->mFirstPaint, paintInSingleTransaction));
+  TILING_LOG("TILING %p: paintingVisible %d drawingStale %d firstPaint %d singleTransaction %d\n",
+    mThebesLayer, paintingVisible, drawingStale, aPaintData->mFirstPaint, paintInSingleTransaction);
 
   // The following code decides what order to draw tiles in, based on the
   // current scroll direction of the primary scrollable layer.
   NS_ASSERTION(!aRegionToPaint.IsEmpty(), "Unexpectedly empty paint region!");
   nsIntRect paintBounds = aRegionToPaint.GetBounds();
 
   int startX, incX, startY, incY;
   gfx::IntSize scaledTileSize = GetScaledTileSize();
@@ -1204,33 +1204,33 @@ ClientTiledLayerBuffer::ComputeProgressi
 bool
 ClientTiledLayerBuffer::ProgressiveUpdate(nsIntRegion& aValidRegion,
                                          nsIntRegion& aInvalidRegion,
                                          const nsIntRegion& aOldValidRegion,
                                          BasicTiledLayerPaintData* aPaintData,
                                          LayerManager::DrawThebesLayerCallback aCallback,
                                          void* aCallbackData)
 {
-  TILING_LOG_OBJ(("TILING %p: Progressive update valid region %s\n", mThebesLayer, tmpstr.get()), aValidRegion);
-  TILING_LOG_OBJ(("TILING %p: Progressive update invalid region %s\n", mThebesLayer, tmpstr.get()), aInvalidRegion);
-  TILING_LOG_OBJ(("TILING %p: Progressive update old valid region %s\n", mThebesLayer, tmpstr.get()), aOldValidRegion);
+  TILING_LOG("TILING %p: Progressive update valid region %s\n", mThebesLayer, Stringify(aValidRegion).c_str());
+  TILING_LOG("TILING %p: Progressive update invalid region %s\n", mThebesLayer, Stringify(aInvalidRegion).c_str());
+  TILING_LOG("TILING %p: Progressive update old valid region %s\n", mThebesLayer, Stringify(aOldValidRegion).c_str());
 
   bool repeat = false;
   bool isBufferChanged = false;
   do {
     // Compute the region that should be updated. Repeat as many times as
     // is required.
     nsIntRegion regionToPaint;
     repeat = ComputeProgressiveUpdateRegion(aInvalidRegion,
                                             aOldValidRegion,
                                             regionToPaint,
                                             aPaintData,
                                             repeat);
 
-    TILING_LOG_OBJ(("TILING %p: Progressive update computed paint region %s repeat %d\n", mThebesLayer, tmpstr.get(), repeat), regionToPaint);
+    TILING_LOG("TILING %p: Progressive update computed paint region %s repeat %d\n", mThebesLayer, Stringify(regionToPaint).c_str(), repeat);
 
     // There's no further work to be done.
     if (regionToPaint.IsEmpty()) {
       break;
     }
 
     isBufferChanged = true;
 
@@ -1243,18 +1243,18 @@ ClientTiledLayerBuffer::ProgressiveUpdat
     nsIntRegion validOrStale;
     validOrStale.Or(aValidRegion, aOldValidRegion);
 
     // Paint the computed region and subtract it from the invalid region.
     PaintThebes(validOrStale, regionToPaint, aCallback, aCallbackData);
     aInvalidRegion.Sub(aInvalidRegion, regionToPaint);
   } while (repeat);
 
-  TILING_LOG_OBJ(("TILING %p: Progressive update final valid region %s buffer changed %d\n", mThebesLayer, tmpstr.get(), isBufferChanged), aValidRegion);
-  TILING_LOG_OBJ(("TILING %p: Progressive update final invalid region %s\n", mThebesLayer, tmpstr.get()), aInvalidRegion);
+  TILING_LOG("TILING %p: Progressive update final valid region %s buffer changed %d\n", mThebesLayer, Stringify(aValidRegion).c_str(), isBufferChanged);
+  TILING_LOG("TILING %p: Progressive update final invalid region %s\n", mThebesLayer, Stringify(aInvalidRegion).c_str());
 
   // Return false if nothing has been drawn, or give what has been drawn
   // to the shadow layer to upload.
   return isBufferChanged;
 }
 
 }
 }
--- a/gfx/layers/ipc/CompositorChild.cpp
+++ b/gfx/layers/ipc/CompositorChild.cpp
@@ -207,32 +207,31 @@ CompositorChild::RecvReleaseSharedCompos
   }
   return true;
 }
 
 CompositorChild::SharedFrameMetricsData::SharedFrameMetricsData(
     const ipc::SharedMemoryBasic::Handle& metrics,
     const CrossProcessMutexHandle& handle,
     const uint32_t& aAPZCId) :
-    mBuffer(nullptr),
     mMutex(nullptr),
     mAPZCId(aAPZCId)
 {
   mBuffer = new ipc::SharedMemoryBasic(metrics);
   mBuffer->Map(sizeof(FrameMetrics));
   mMutex = new CrossProcessMutex(handle);
   MOZ_COUNT_CTOR(SharedFrameMetricsData);
 }
 
 CompositorChild::SharedFrameMetricsData::~SharedFrameMetricsData()
 {
   // When the hash table deletes the class, delete
   // the shared memory and mutex.
   delete mMutex;
-  delete mBuffer;
+  mBuffer = nullptr;
   MOZ_COUNT_DTOR(SharedFrameMetricsData);
 }
 
 void
 CompositorChild::SharedFrameMetricsData::CopyFrameMetrics(FrameMetrics* aFrame)
 {
   FrameMetrics* frame = static_cast<FrameMetrics*>(mBuffer->memory());
   MOZ_ASSERT(frame);
--- a/gfx/layers/ipc/CompositorChild.h
+++ b/gfx/layers/ipc/CompositorChild.h
@@ -95,17 +95,17 @@ private:
 
     void CopyFrameMetrics(FrameMetrics* aFrame);
     FrameMetrics::ViewID GetViewID();
     uint32_t GetAPZCId();
 
   private:
     // Pointer to the class that allows access to the shared memory that contains
     // the shared FrameMetrics
-    mozilla::ipc::SharedMemoryBasic* mBuffer;
+    nsRefPtr<mozilla::ipc::SharedMemoryBasic> mBuffer;
     CrossProcessMutex* mMutex;
     // Unique ID of the APZC that is sharing the FrameMetrics
     uint32_t mAPZCId;
   };
 
   nsRefPtr<ClientLayerManager> mLayerManager;
 
   // The ViewID of the FrameMetrics is used as the key for this hash table.
--- a/gfx/layers/ipc/SharedBufferManagerParent.cpp
+++ b/gfx/layers/ipc/SharedBufferManagerParent.cpp
@@ -9,16 +9,17 @@
 #include "base/process.h"               // for ProcessHandle
 #include "base/process_util.h"          // for OpenProcessHandle
 #include "base/task.h"                  // for CancelableTask, DeleteTask, etc
 #include "base/tracked.h"               // for FROM_HERE
 #include "base/thread.h"
 #include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc
 #include "mozilla/ipc/ProtocolUtils.h"
 #include "mozilla/ipc/Transport.h"      // for Transport
+#include "mozilla/UniquePtr.h"          // for UniquePtr
 #include "nsIMemoryReporter.h"
 #ifdef MOZ_WIDGET_GONK
 #include "ui/PixelFormat.h"
 #endif
 #include "nsPrintfCString.h"
 #include "nsThreadUtils.h"
 
 using namespace mozilla::ipc;
@@ -46,17 +47,17 @@ public:
     if (SharedBufferManagerParent::sManagerMonitor) {
       SharedBufferManagerParent::sManagerMonitor->Lock();
     }
     map<base::ProcessId, SharedBufferManagerParent*>::iterator it;
     for (it = SharedBufferManagerParent::sManagers.begin(); it != SharedBufferManagerParent::sManagers.end(); it++) {
       base::ProcessId pid = it->first;
       SharedBufferManagerParent *mgr = it->second;
 
-      MutexAutoLock lock(mgr->mBuffersMutex);
+      MutexAutoLock lock(mgr->mLock);
       std::map<int64_t, android::sp<android::GraphicBuffer> >::iterator buf_it;
       for (buf_it = mgr->mBuffers.begin(); buf_it != mgr->mBuffers.end(); buf_it++) {
         nsresult rv;
         android::sp<android::GraphicBuffer> gb = buf_it->second;
         int bpp = android::bytesPerPixel(gb->getPixelFormat());
         int stride = gb->getStride();
         int height = gb->getHeight();
         int amount = bpp > 0
@@ -96,23 +97,38 @@ NS_IMPL_ISUPPORTS(GrallocReporter, nsIMe
 
 void InitGralloc() {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
 #ifdef MOZ_WIDGET_GONK
   RegisterStrongMemoryReporter(new GrallocReporter());
 #endif
 }
 
+/**
+ * Task that deletes SharedBufferManagerParent on a specified thread.
+ */
+class DeleteSharedBufferManagerParentTask : public Task
+{
+public:
+    DeleteSharedBufferManagerParentTask(UniquePtr<SharedBufferManagerParent> aSharedBufferManager)
+        : mSharedBufferManager(Move(aSharedBufferManager)) {
+    }
+    virtual void Run() MOZ_OVERRIDE {}
+private:
+    UniquePtr<SharedBufferManagerParent> mSharedBufferManager;
+};
+
 SharedBufferManagerParent::SharedBufferManagerParent(Transport* aTransport, base::ProcessId aOwner, base::Thread* aThread)
   : mTransport(aTransport)
   , mThread(aThread)
-#ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
-  , mBuffersMutex("BuffersMonitor")
-#endif
+  , mMainMessageLoop(MessageLoop::current())
+  , mDestroyed(false)
+  , mLock("SharedBufferManagerParent.mLock")
 {
+  MOZ_ASSERT(NS_IsMainThread());
   if (!sManagerMonitor) {
     sManagerMonitor = new Monitor("Manager Monitor");
   }
 
   MonitorAutoLock lock(*sManagerMonitor.get());
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread");
   if (!aThread->IsRunning()) {
     aThread->Start();
@@ -134,20 +150,24 @@ SharedBufferManagerParent::~SharedBuffer
   }
   sManagers.erase(mOwner);
   delete mThread;
 }
 
 void
 SharedBufferManagerParent::ActorDestroy(ActorDestroyReason aWhy)
 {
+  MutexAutoLock lock(mLock);
+  mDestroyed = true;
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
-  MutexAutoLock lock(mBuffersMutex);
   mBuffers.clear();
 #endif
+  DeleteSharedBufferManagerParentTask* task =
+    new DeleteSharedBufferManagerParentTask(UniquePtr<SharedBufferManagerParent>(this));
+  mMainMessageLoop->PostTask(FROM_HERE, task);
 }
 
 static void
 ConnectSharedBufferManagerInParentProcess(SharedBufferManagerParent* aManager,
                                           Transport* aTransport,
                                           base::ProcessHandle aOtherProcess)
 {
   aManager->Open(aTransport, aOtherProcess, XRE_GetIOMessageLoop(), ipc::ParentSide);
@@ -206,67 +226,83 @@ bool SharedBufferManagerParent::RecvAllo
     bufferKey = ++sBufferKey; 
   }
   GrallocBufferRef ref;
   ref.mOwner = mOwner;
   ref.mKey = bufferKey;
   *aHandle = MagicGrallocBufferHandle(outgoingBuffer, ref);
 
   {
-    MutexAutoLock lock(mBuffersMutex);
+    MutexAutoLock lock(mLock);
     mBuffers[bufferKey] = outgoingBuffer;
   }
 #endif
   return true;
 }
 
 bool SharedBufferManagerParent::RecvDropGrallocBuffer(const mozilla::layers::MaybeMagicGrallocBufferHandle& handle)
 {
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
   NS_ASSERTION(handle.type() == MaybeMagicGrallocBufferHandle::TGrallocBufferRef, "We shouldn't interact with the real buffer!");
   int64_t bufferKey = handle.get_GrallocBufferRef().mKey;
   sp<GraphicBuffer> buf = GetGraphicBuffer(bufferKey);
   MOZ_ASSERT(buf.get());
-  MutexAutoLock lock(mBuffersMutex);
+  MutexAutoLock lock(mLock);
   NS_ASSERTION(mBuffers.count(bufferKey) == 1, "No such buffer");
   mBuffers.erase(bufferKey);
 
   if(!buf.get()) {
     printf_stderr("SharedBufferManagerParent::RecvDropGrallocBuffer -- invalid buffer key.");
     return true;
   }
 
 #endif
   return true;
 }
 
+/*static*/
 void SharedBufferManagerParent::DropGrallocBufferSync(SharedBufferManagerParent* mgr, mozilla::layers::SurfaceDescriptor aDesc)
 {
   mgr->DropGrallocBufferImpl(aDesc);
 }
 
-void SharedBufferManagerParent::DropGrallocBuffer(mozilla::layers::SurfaceDescriptor aDesc)
+/*static*/
+void SharedBufferManagerParent::DropGrallocBuffer(ProcessId id, mozilla::layers::SurfaceDescriptor aDesc)
 {
   if (aDesc.type() != SurfaceDescriptor::TNewSurfaceDescriptorGralloc) {
     return;
   }
 
-  if (PlatformThread::CurrentId() == mThread->thread_id()) {
-    DropGrallocBufferImpl(aDesc);
+  MonitorAutoLock lock(*sManagerMonitor.get());
+  SharedBufferManagerParent* mgr = SharedBufferManagerParent::GetInstance(id);
+  if (!mgr) {
+    return;
+  }
+
+  MutexAutoLock mgrlock(mgr->mLock);
+  if (mgr->mDestroyed) {
+    return;
+  }
+
+  if (PlatformThread::CurrentId() == mgr->mThread->thread_id()) {
+    MOZ_CRASH("SharedBufferManagerParent::DropGrallocBuffer should not be called on SharedBufferManagerParent thread");
   } else {
-    mThread->message_loop()->PostTask(FROM_HERE,
-                                      NewRunnableFunction(&DropGrallocBufferSync, this, aDesc));
+    mgr->mThread->message_loop()->PostTask(FROM_HERE,
+                                      NewRunnableFunction(&DropGrallocBufferSync, mgr, aDesc));
   }
   return;
 }
 
 void SharedBufferManagerParent::DropGrallocBufferImpl(mozilla::layers::SurfaceDescriptor aDesc)
 {
+  MutexAutoLock lock(mLock);
+  if (mDestroyed) {
+    return;
+  }
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
-  MutexAutoLock lock(mBuffersMutex);
   int64_t key = -1;
   MaybeMagicGrallocBufferHandle handle;
   if (aDesc.type() == SurfaceDescriptor::TNewSurfaceDescriptorGralloc) {
     handle = aDesc.get_NewSurfaceDescriptorGralloc().buffer();
   } else {
     return;
   }
 
@@ -285,38 +321,38 @@ void SharedBufferManagerParent::DropGral
 
 MessageLoop* SharedBufferManagerParent::GetMessageLoop()
 {
   return mThread->message_loop();
 }
 
 SharedBufferManagerParent* SharedBufferManagerParent::GetInstance(ProcessId id)
 {
-  MonitorAutoLock lock(*sManagerMonitor.get());
   NS_ASSERTION(sManagers.count(id) == 1, "No BufferManager for the process");
   return sManagers[id];
 }
 
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
 android::sp<android::GraphicBuffer>
 SharedBufferManagerParent::GetGraphicBuffer(int64_t key)
 {
-  MutexAutoLock lock(mBuffersMutex);
+  MutexAutoLock lock(mLock);
   if (mBuffers.count(key) == 1) {
     return mBuffers[key];
   } else {
     // The buffer can be dropped, or invalid
     printf_stderr("SharedBufferManagerParent::GetGraphicBuffer -- invalid key");
     return nullptr;
   }
 }
 
 android::sp<android::GraphicBuffer>
 SharedBufferManagerParent::GetGraphicBuffer(GrallocBufferRef aRef)
 {
+  MonitorAutoLock lock(*sManagerMonitor.get());
   return GetInstance(aRef.mOwner)->GetGraphicBuffer(aRef.mKey);
 }
 #endif
 
 IToplevelProtocol*
 SharedBufferManagerParent::CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
                                  base::ProcessHandle aPeerProcess,
                                  mozilla::ipc::ProtocolCloneContext* aCtx)
--- a/gfx/layers/ipc/SharedBufferManagerParent.h
+++ b/gfx/layers/ipc/SharedBufferManagerParent.h
@@ -35,21 +35,16 @@ class SharedBufferManagerParent : public
 {
 friend class GrallocReporter;
 public:
   /**
    * Create a SharedBufferManagerParent for child process, and link to the child side before leaving
    */
   static PSharedBufferManagerParent* Create(Transport* aTransport, ProcessId aOtherProcess);
 
-  /**
-   * Function for find the buffer owner, most buffer passing on IPC contains only owner/key pair.
-   * Use these function to access the real buffer.
-   */
-  static SharedBufferManagerParent* GetInstance(ProcessId id);
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
   android::sp<android::GraphicBuffer> GetGraphicBuffer(int64_t key);
   static android::sp<android::GraphicBuffer> GetGraphicBuffer(GrallocBufferRef aRef);
 #endif
   /**
    * Create a SharedBufferManagerParent but do not open the link
    */
   SharedBufferManagerParent(Transport* aTransport, ProcessId aOwner, base::Thread* aThread);
@@ -61,52 +56,62 @@ public:
   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
   virtual bool RecvAllocateGrallocBuffer(const IntSize&, const uint32_t&, const uint32_t&, mozilla::layers::MaybeMagicGrallocBufferHandle*);
   virtual bool RecvDropGrallocBuffer(const mozilla::layers::MaybeMagicGrallocBufferHandle& handle);
 
   /**
    * Break the buffer's sharing state, decrease buffer reference for both side
    */
-  void DropGrallocBuffer(mozilla::layers::SurfaceDescriptor aDesc);
+  static void DropGrallocBuffer(ProcessId id, mozilla::layers::SurfaceDescriptor aDesc);
 
   // Overriden from IToplevelProtocol
   IToplevelProtocol*
   CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
                 base::ProcessHandle aPeerProcess,
                 mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
   MessageLoop* GetMessageLoop();
 
 protected:
-  /**
-   * All living SharedBufferManager instances used to find the buffer owner, and parent->child IPCs
-   */
-  static std::map<base::ProcessId, SharedBufferManagerParent*> sManagers;
 
   /**
    * Break the buffer's sharing state, decrease buffer reference for both side
    *
    * Must be called from SharedBufferManagerParent's thread
    */
   void DropGrallocBufferImpl(mozilla::layers::SurfaceDescriptor aDesc);
 
   // dispatched function
   static void DropGrallocBufferSync(SharedBufferManagerParent* mgr, mozilla::layers::SurfaceDescriptor aDesc);
 
+  /**
+   * Function for find the buffer owner, most buffer passing on IPC contains only owner/key pair.
+   * Use these function to access the real buffer.
+   * Caller needs to hold sManagerMonitor.
+   */
+  static SharedBufferManagerParent* GetInstance(ProcessId id);
+
+  /**
+   * All living SharedBufferManager instances used to find the buffer owner, and parent->child IPCs
+   */
+  static std::map<base::ProcessId, SharedBufferManagerParent*> sManagers;
+
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
   /**
    * Buffers owned by this SharedBufferManager pair
    */
   std::map<int64_t, android::sp<android::GraphicBuffer> > mBuffers;
-  Mutex mBuffersMutex;
 #endif
   
   Transport* mTransport;
   base::ProcessId mOwner;
   base::Thread* mThread;
+  MessageLoop* mMainMessageLoop;
+  bool mDestroyed;
+  Mutex mLock;
+
   static uint64_t sBufferKey;
-
   static StaticAutoPtr<Monitor> sManagerMonitor;
 };
 
 } /* namespace layers */
 } /* namespace mozilla */
 #endif /* SharedBufferManagerPARENT_H_ */
--- a/gfx/layers/opengl/GrallocTextureHost.cpp
+++ b/gfx/layers/opengl/GrallocTextureHost.cpp
@@ -378,17 +378,17 @@ GrallocTextureHostOGL::DeallocateSharedD
     base::ProcessId owner;
     if (handle.type() == MaybeMagicGrallocBufferHandle::TGrallocBufferRef) {
       owner = handle.get_GrallocBufferRef().mOwner;
     }
     else {
       owner = handle.get_MagicGrallocBufferHandle().mRef.mOwner;
     }
 
-    SharedBufferManagerParent::GetInstance(owner)->DropGrallocBuffer(mGrallocHandle);
+    SharedBufferManagerParent::DropGrallocBuffer(owner, mGrallocHandle);
   }
 }
 
 void
 GrallocTextureHostOGL::ForgetSharedData()
 {
   if (mTextureSource) {
     mTextureSource->ForgetBuffer();
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -731,17 +731,17 @@ gfxUserFontSet::OnLoadComplete(gfxMixedF
     } else {
         // download failed
         LogMessage(aFamily, aProxy,
                    "download failed", nsIScriptError::errorFlag,
                    aDownloadStatus);
     }
 
     if (aFontData) {
-        NS_Free((void*)aFontData);
+        moz_free((void*)aFontData);
     }
 
     // error occurred, load next src
     (void)aProxy->LoadNext(aFamily, mLocalRulesUsed);
 
     // We ignore the status returned by LoadNext();
     // even if loading failed, we need to bump the font-set generation
     // and return true in order to trigger reflow, so that fallback
--- a/ipc/app/Makefile.in
+++ b/ipc/app/Makefile.in
@@ -35,20 +35,18 @@ endif
 NSDISTMODE = copy
 
 include $(topsrcdir)/config/config.mk
 
 include $(topsrcdir)/config/rules.mk
 
 ifeq ($(OS_ARCH),WINNT) #{
 
-ifdef MOZ_CONTENT_SANDBOX
 LIBS += ../../security/sandbox/$(LIB_PREFIX)sandbox_s.$(LIB_SUFFIX)
 LIBS += $(NSPR_LIBS)
-endif
 
 # Note the manifest file exists in the tree, so we use the explicit filename
 # here.
 EXTRA_DEPS += plugin-container.exe.manifest
 endif #}
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) #{
 
--- a/ipc/app/MozillaRuntimeMain.cpp
+++ b/ipc/app/MozillaRuntimeMain.cpp
@@ -16,17 +16,17 @@
 #include <windows.h>
 // we want a wmain entry point
 // but we don't want its DLL load protection, because we'll handle it here
 #define XRE_DONT_PROTECT_DLL_LOAD
 #include "nsWindowsWMain.cpp"
 #include "nsSetDllDirectory.h"
 #endif
 
-#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
+#if defined(XP_WIN)
 #include "sandbox/chromium/base/basictypes.h"
 #include "sandbox/win/src/sandbox.h"
 #include "sandbox/win/src/sandbox_factory.h"
 #include "mozilla/sandboxTarget.h"
 #endif
 
 #ifdef MOZ_WIDGET_GONK
 # include <sys/time.h>
@@ -63,17 +63,17 @@ InitializeBinder(void *aDummy) {
     int err = setpriority(PRIO_PROCESS, 0, 0);
     MOZ_ASSERT(!err);
     LOGE_IF(err, "setpriority failed. Current process needs root permission.");
     android::ProcessState::self()->startThreadPool();
     setpriority(PRIO_PROCESS, 0, curPrio);
 }
 #endif
 
-#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
+#if defined(XP_WIN)
 static bool gIsSandboxEnabled = false;
 void StartSandboxCallback()
 {
     if (gIsSandboxEnabled) {
         sandbox::TargetServices* target_service =
             sandbox::SandboxFactory::GetTargetServices();
         target_service->LowerToken();
     }
@@ -81,17 +81,17 @@ void StartSandboxCallback()
 #endif
 
 int
 main(int argc, char* argv[])
 {
     bool isNuwa = false;
     for (int i = 1; i < argc; i++) {
         isNuwa |= strcmp(argv[i], "-nuwa") == 0;
-#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
+#if defined(XP_WIN)
         gIsSandboxEnabled |= strcmp(argv[i], "-sandbox") == 0;
 #endif
     }
 
 #ifdef MOZ_NUWA_PROCESS
     if (isNuwa) {
         PrepareNuwaProcess();
     }
@@ -124,30 +124,28 @@ main(int argc, char* argv[])
     // For plugins, this is done in PluginProcessChild::Init, as we need to
     // avoid it for unsupported plugins.  See PluginProcessChild::Init for
     // the details.
     if (proctype != GeckoProcessType_Plugin) {
         mozilla::SanitizeEnvironmentVariables();
         SetDllDirectory(L"");
     }
 
-#ifdef MOZ_CONTENT_SANDBOX
     if (gIsSandboxEnabled) {
         sandbox::TargetServices* target_service =
             sandbox::SandboxFactory::GetTargetServices();
         if (!target_service) {
             return 1;
         }
 
         sandbox::ResultCode result = target_service->Init();
         if (result != sandbox::SBOX_ALL_OK) {
            return 2;
         }
         mozilla::SandboxTarget::Instance()->SetStartSandboxCallback(StartSandboxCallback);
     }
 #endif
-#endif
 
     nsresult rv = XRE_InitChildProcess(argc, argv, proctype);
     NS_ENSURE_SUCCESS(rv, 1);
 
     return 0;
 }
--- a/ipc/app/moz.build
+++ b/ipc/app/moz.build
@@ -17,17 +17,17 @@ else:
     ]
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/toolkit/xre',
     '/xpcom/base',
 ]
 
-if CONFIG['MOZ_CONTENT_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
+if CONFIG['OS_ARCH'] == 'WINNT':
     # For sandbox includes and the include dependencies those have
     LOCAL_INCLUDES += [
         '/security',
         '/security/sandbox',
         '/security/sandbox/chromium',
     ]
 
 if CONFIG['_MSC_VER']:
--- a/ipc/chromium/src/chrome/common/file_descriptor_set_posix.h
+++ b/ipc/chromium/src/chrome/common/file_descriptor_set_posix.h
@@ -16,26 +16,20 @@
 // associated with IPC messages so that descriptors can be transmitted over a
 // UNIX domain socket.
 // -----------------------------------------------------------------------------
 class FileDescriptorSet : public base::RefCountedThreadSafe<FileDescriptorSet> {
  public:
   FileDescriptorSet();
   ~FileDescriptorSet();
 
-  // This is the maximum number of descriptors per message. We need to know this
-  // because the control message kernel interface has to be given a buffer which
-  // is large enough to store all the descriptor numbers. Otherwise the kernel
-  // tells us that it truncated the control data and the extra descriptors are
-  // lost.
-  //
-  // In debugging mode, it's a fatal error to try and add more than this number
-  // of descriptors to a FileDescriptorSet.
+  // Mac and Linux both limit the number of file descriptors per message to
+  // slightly more than 250.
   enum {
-    MAX_DESCRIPTORS_PER_MESSAGE = 7
+    MAX_DESCRIPTORS_PER_MESSAGE = 250
   };
 
   // ---------------------------------------------------------------------------
   // Interfaces for building during message serialisation...
 
   // Add a descriptor to the end of the set. Returns false iff the set is full.
   bool Add(int fd);
   // Add a descriptor to the end of the set and automatically close it after
--- a/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
+++ b/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
@@ -278,16 +278,18 @@ Channel::ChannelImpl::ChannelImpl(int fd
   Init(mode, listener);
   pipe_ = fd;
   waiting_connect_ = (MODE_SERVER == mode);
 
   EnqueueHelloMessage();
 }
 
 void Channel::ChannelImpl::Init(Mode mode, Listener* listener) {
+  DCHECK(kControlBufferSlopBytes >= CMSG_SPACE(0));
+
   mode_ = mode;
   is_blocked_on_write_ = false;
   message_send_bytes_written_ = 0;
   uses_fifo_ = false;
   server_listen_pipe_ = -1;
   pipe_ = -1;
   client_pipe_ = -1;
   listener_ = listener;
--- a/ipc/chromium/src/chrome/common/ipc_channel_posix.h
+++ b/ipc/chromium/src/chrome/common/ipc_channel_posix.h
@@ -98,30 +98,37 @@ class Channel::ChannelImpl : public Mess
   Listener* listener_;
 
   // Messages to be sent are queued here.
   std::queue<Message*> output_queue_;
 
   // We read from the pipe into this buffer
   char input_buf_[Channel::kReadBufferSize];
 
+  // We want input_cmsg_buf_ to be big enough to hold
+  // CMSG_SPACE(Channel::kReadBufferSize) bytes (see the comment below for an
+  // explanation of where Channel::kReadBufferSize comes from). However,
+  // CMSG_SPACE is apparently not a constant on Macs, so we can't use it in the
+  // array size. Consequently, we pick a number here that is at least
+  // CMSG_SPACE(0) on all platforms. And we assert at runtime, in
+  // Channel::ChannelImpl::Init, that it's big enough.
   enum {
-    // We assume a worst case: kReadBufferSize bytes of messages, where each
-    // message has no payload and a full complement of descriptors.
-    MAX_READ_FDS = (Channel::kReadBufferSize / sizeof(IPC::Message::Header)) *
-                   FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE
+    kControlBufferSlopBytes = 32
   };
 
-  // This is a control message buffer large enough to hold kMaxReadFDs
-#if defined(OS_MACOSX) || defined(OS_NETBSD)
-  // TODO(agl): OSX appears to have non-constant CMSG macros!
-  char input_cmsg_buf_[1024];
-#else
-  char input_cmsg_buf_[CMSG_SPACE(sizeof(int) * MAX_READ_FDS)];
-#endif
+  // This is a control message buffer large enough to hold all the file
+  // descriptors that will be read in when reading Channel::kReadBufferSize
+  // bytes of data. Message::WriteFileDescriptor always writes one word of
+  // data for every file descriptor added to the message, so kReadBufferSize
+  // bytes of data can never be accompanied by more than
+  // kReadBufferSize / sizeof(int) file descriptors. Since a file descriptor
+  // takes sizeof(int) bytes, the control buffer must be
+  // Channel::kReadBufferSize bytes. We add kControlBufferSlopBytes bytes
+  // for the control header.
+  char input_cmsg_buf_[Channel::kReadBufferSize + kControlBufferSlopBytes];
 
   // Large messages that span multiple pipe buffers, get built-up using
   // this buffer.
   std::string input_overflow_buf_;
   std::vector<int> input_overflow_fds_;
 
   // In server-mode, we have to wait for the client to connect before we
   // can begin reading.  We make use of the input_state_ when performing
--- a/ipc/chromium/src/chrome/common/ipc_message.cc
+++ b/ipc/chromium/src/chrome/common/ipc_message.cc
@@ -123,16 +123,18 @@ void Message::set_received_time(int64_t 
   received_time_ = time;
 }
 #endif
 
 #if defined(OS_POSIX)
 bool Message::WriteFileDescriptor(const base::FileDescriptor& descriptor) {
   // We write the index of the descriptor so that we don't have to
   // keep the current descriptor as extra decoding state when deserialising.
+  // Also, we rely on each file descriptor being accompanied by sizeof(int)
+  // bytes of data in the message. See the comment for input_cmsg_buf_.
   WriteInt(file_descriptor_set()->size());
   if (descriptor.auto_close) {
     return file_descriptor_set()->AddAndAutoClose(descriptor.fd);
   } else {
     return file_descriptor_set()->Add(descriptor.fd);
   }
 }
 
--- a/ipc/glue/CrossProcessMutex.h
+++ b/ipc/glue/CrossProcessMutex.h
@@ -8,16 +8,17 @@
 
 #include "base/process.h"
 #include "mozilla/Mutex.h"
 
 #if defined(OS_LINUX)
 #include <pthread.h>
 #include "SharedMemoryBasic.h"
 #include "mozilla/Atomics.h"
+#include "nsAutoPtr.h"
 #endif
 
 namespace IPC {
 template<typename T>
 struct ParamTraits;
 }
 
 //
@@ -95,17 +96,17 @@ private:
 
   CrossProcessMutex();
   CrossProcessMutex(const CrossProcessMutex&);
   CrossProcessMutex &operator=(const CrossProcessMutex&);
 
 #ifdef XP_WIN
   HANDLE mMutex;
 #elif defined(OS_LINUX)
-  mozilla::ipc::SharedMemoryBasic* mSharedBuffer;
+  nsRefPtr<mozilla::ipc::SharedMemoryBasic> mSharedBuffer;
   pthread_mutex_t* mMutex;
   mozilla::Atomic<int32_t>* mCount;
 #endif
 };
 
 typedef BaseAutoLock<CrossProcessMutex> CrossProcessMutexAutoLock;
 typedef BaseAutoUnlock<CrossProcessMutex> CrossProcessMutexAutoUnlock;
 
--- a/ipc/glue/CrossProcessMutex_posix.cpp
+++ b/ipc/glue/CrossProcessMutex_posix.cpp
@@ -33,18 +33,17 @@ InitMutex(pthread_mutex_t* mMutex)
   }
 
   if (pthread_mutex_init(mMutex, &mutexAttributes)) {
     MOZ_CRASH();
   }
 }
 
 CrossProcessMutex::CrossProcessMutex(const char*)
-    : mSharedBuffer(nullptr)
-    , mMutex(nullptr)
+    : mMutex(nullptr)
     , mCount(nullptr)
 {
   mSharedBuffer = new ipc::SharedMemoryBasic;
   if (!mSharedBuffer->Create(sizeof(MutexData))) {
     MOZ_CRASH();
   }
 
   if (!mSharedBuffer->Map(sizeof(MutexData))) {
@@ -62,18 +61,17 @@ CrossProcessMutex::CrossProcessMutex(con
 
   *mCount = 1;
   InitMutex(mMutex);
 
   MOZ_COUNT_CTOR(CrossProcessMutex);
 }
 
 CrossProcessMutex::CrossProcessMutex(CrossProcessMutexHandle aHandle)
-    : mSharedBuffer(nullptr)
-    , mMutex(nullptr)
+    : mMutex(nullptr)
     , mCount(nullptr)
 {
   if (!ipc::SharedMemoryBasic::IsHandleValid(aHandle)) {
     MOZ_CRASH();
   }
 
   mSharedBuffer = new ipc::SharedMemoryBasic(aHandle);
 
@@ -104,17 +102,16 @@ CrossProcessMutex::~CrossProcessMutex()
 {
   int32_t count = --(*mCount);
 
   if (count == 0) {
     // Nothing can be done if the destroy fails so ignore return code.
     unused << pthread_mutex_destroy(mMutex);
   }
 
-  delete mSharedBuffer;
   MOZ_COUNT_DTOR(CrossProcessMutex);
 }
 
 void
 CrossProcessMutex::Lock()
 {
   MOZ_ASSERT(*mCount > 0, "Attempting to lock mutex with zero ref count");
   pthread_mutex_lock(mMutex);
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -1,20 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; 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 "GeckoChildProcessHost.h"
 
-#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
-#include "sandboxBroker.h"
-#endif
-
 #include "base/command_line.h"
 #include "base/path_service.h"
 #include "base/string_util.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/process_watcher.h"
 #ifdef MOZ_WIDGET_COCOA
 #include "chrome/common/mach_ipc_mac.h"
 #include "base/rand_util.h"
@@ -86,17 +82,16 @@ GeckoChildProcessHost::DefaultChildPrivi
   return (kLowRightsSubprocesses ?
           base::PRIVILEGES_UNPRIVILEGED : base::PRIVILEGES_INHERIT);
 }
 
 GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
                                              ChildPrivileges aPrivileges)
   : ChildProcessHost(RENDER_PROCESS), // FIXME/cjones: we should own this enum
     mProcessType(aProcessType),
-    mSandboxEnabled(true),
     mPrivileges(aPrivileges),
     mMonitor("mozilla.ipc.GeckChildProcessHost.mMonitor"),
     mProcessState(CREATING_CHANNEL),
     mDelegate(nullptr),
     mChildProcessHandle(0)
 #if defined(MOZ_WIDGET_COCOA)
   , mChildTask(MACH_PORT_NULL)
 #endif
@@ -794,21 +789,52 @@ GeckoChildProcessHost::PerformAsyncLaunc
     }
     file = Omnijar::GetPath(Omnijar::APP);
     if (file && NS_SUCCEEDED(file->GetPath(path))) {
       cmdLine.AppendLooseValue(UTF8ToWide("-appomni"));
       cmdLine.AppendLooseValue(path.get());
     }
   }
 
-#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
-  if (mSandboxEnabled) {
-    // Tell the process that it should lower its rights after initialization.
-    cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
-  }
+#if defined(XP_WIN)
+  bool shouldSandboxCurrentProcess = false;
+  switch (mProcessType) {
+    case GeckoProcessType_Content:
+#if defined(MOZ_CONTENT_SANDBOX)
+      if (!PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX")) {
+        mSandboxBroker.SetSecurityLevelForContentProcess();
+        cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
+        shouldSandboxCurrentProcess = true;
+      }
+#endif // MOZ_CONTENT_SANDBOX
+      break;
+    case GeckoProcessType_Plugin:
+      // XXX: We don't sandbox this process type yet
+      // mSandboxBroker.SetSecurityLevelForPluginProcess();
+      // cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
+      // shouldSandboxCurrentProcess = true;
+      break;
+    case GeckoProcessType_IPDLUnitTest:
+      // XXX: We don't sandbox this process type yet
+      // mSandboxBroker.SetSecurityLevelForIPDLUnitTestProcess();
+      // cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
+      // shouldSandboxCurrentProcess = true;
+      break;
+    case GeckoProcessType_GMPlugin:
+      if (!PR_GetEnv("MOZ_DISABLE_GMP_SANDBOX")) {
+        mSandboxBroker.SetSecurityLevelForGMPlugin();
+        cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
+        shouldSandboxCurrentProcess = true;
+      }
+      break;
+    case GeckoProcessType_Default:
+    default:
+      MOZ_CRASH("Bad process type in GeckoChildProcessHost");
+      break;
+  };
 #endif
 
   // Add the application directory path (-appdir path)
   AddAppDirToCommandLine(cmdLine);
 
   // XXX Command line params past this point are expected to be at
   // the end of the command line string, and in a specific order.
   // See XRE_InitChildProcess in nsEmbedFunction.
@@ -822,23 +848,21 @@ GeckoChildProcessHost::PerformAsyncLaunc
 #if defined(MOZ_CRASHREPORTER)
   cmdLine.AppendLooseValue(
     UTF8ToWide(CrashReporter::GetChildNotificationPipe()));
 #endif
 
   // Process type
   cmdLine.AppendLooseValue(UTF8ToWide(childProcessType));
 
-#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
-  if (mSandboxEnabled) {
-
-    mozilla::SandboxBroker sandboxBroker;
-    sandboxBroker.LaunchApp(cmdLine.program().c_str(),
-                            cmdLine.command_line_string().c_str(),
-                            &process);
+#if defined(XP_WIN)
+  if (shouldSandboxCurrentProcess) {
+    mSandboxBroker.LaunchApp(cmdLine.program().c_str(),
+                             cmdLine.command_line_string().c_str(),
+                             &process);
   } else
 #endif
   {
     base::LaunchApp(cmdLine, false, false, &process);
   }
 
 #else
 #  error Sorry
--- a/ipc/glue/GeckoChildProcessHost.h
+++ b/ipc/glue/GeckoChildProcessHost.h
@@ -15,16 +15,20 @@
 #include "mozilla/ipc/FileDescriptor.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/StaticPtr.h"
 
 #include "nsCOMPtr.h"
 #include "nsXULAppAPI.h"        // for GeckoProcessType
 #include "nsString.h"
 
+#if defined(XP_WIN)
+#include "sandboxBroker.h"
+#endif
+
 class nsIFile;
 
 namespace mozilla {
 namespace ipc {
 
 class GeckoChildProcessHost : public ChildProcessHost
 {
 protected:
@@ -126,25 +130,20 @@ public:
    * Must run on the IO thread.  Cause the OS process to exit and
    * ensure its OS resources are cleaned up.
    */
   void Join();
 
   // For bug 943174: Skip the EnsureProcessTerminated call in the destructor.
   void SetAlreadyDead();
 
-  void SetSandboxEnabled(bool aSandboxEnabled) {
-    mSandboxEnabled = aSandboxEnabled;
-  }
-
   static void CacheGreDir();
 
 protected:
   GeckoProcessType mProcessType;
-  bool mSandboxEnabled;
   ChildPrivileges mPrivileges;
   Monitor mMonitor;
   FilePath mProcessPath;
 
   // This value must be accessed while holding mMonitor.
   enum {
     // This object has been constructed, but the OS process has not
     // yet.
@@ -163,17 +162,18 @@ protected:
 
   static int32_t mChildCounter;
 
   void PrepareLaunch();
 
 #ifdef XP_WIN
   void InitWindowsGroupID();
   nsString mGroupId;
-#endif
+  SandboxBroker mSandboxBroker;
+#endif // XP_WIN
 
 #if defined(OS_POSIX)
   base::file_handle_mapping_vector mFileMap;
 #endif
 
   base::WaitableEventWatcher::Delegate* mDelegate;
 
   ProcessHandle mChildProcessHandle;
--- a/ipc/glue/moz.build
+++ b/ipc/glue/moz.build
@@ -146,14 +146,14 @@ FINAL_LIBRARY = 'xul'
 for var in ('MOZ_CHILD_PROCESS_NAME', 'MOZ_CHILD_PROCESS_BUNDLE',
             'DLL_PREFIX', 'DLL_SUFFIX'):
     DEFINES[var] = '"%s"' % CONFIG[var]
 
 LOCAL_INCLUDES += [
     '/toolkit/crashreporter',
 ]
 
-if CONFIG['MOZ_CONTENT_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
+if CONFIG['OS_ARCH'] == 'WINNT':
     LOCAL_INCLUDES += [
         '/security/sandbox/win/src/sandboxbroker',
     ]
 
 FAIL_ON_WARNINGS = True
--- a/js/public/HashTable.h
+++ b/js/public/HashTable.h
@@ -202,17 +202,17 @@ class HashMap
         return impl.sizeOfExcludingThis(mallocSizeOf);
     }
     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
         return mallocSizeOf(this) + impl.sizeOfExcludingThis(mallocSizeOf);
     }
 
     // If |generation()| is the same before and after a HashMap operation,
     // pointers into the table remain valid.
-    unsigned generation() const                       { return impl.generation(); }
+    uint32_t generation() const                       { return impl.generation(); }
 
     /************************************************** Shorthand operations */
 
     bool has(const Lookup &l) const {
         return impl.lookup(l) != nullptr;
     }
 
     // Overwrite existing value with v. Return false on oom.
@@ -430,17 +430,17 @@ class HashSet
         return impl.sizeOfExcludingThis(mallocSizeOf);
     }
     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
         return mallocSizeOf(this) + impl.sizeOfExcludingThis(mallocSizeOf);
     }
 
     // If |generation()| is the same before and after a HashSet operation,
     // pointers into the table remain valid.
-    unsigned generation() const                       { return impl.generation(); }
+    uint32_t generation() const                       { return impl.generation(); }
 
     /************************************************** Shorthand operations */
 
     bool has(const Lookup &l) const {
         return impl.lookup(l) != nullptr;
     }
 
     // Add |u| if it is not present already. Return false on oom.
@@ -737,16 +737,18 @@ class HashTableEntry
         new(mem.addr()) T(mozilla::Forward<U>(u));
         MOZ_ASSERT(isLive());
     }
 };
 
 template <class T, class HashPolicy, class AllocPolicy>
 class HashTable : private AllocPolicy
 {
+    friend class mozilla::ReentrancyGuard;
+
     typedef typename mozilla::RemoveConst<T>::Type NonConstT;
     typedef typename HashPolicy::KeyType Key;
     typedef typename HashPolicy::Lookup Lookup;
 
   public:
     typedef HashTableEntry<T> Entry;
 
     // A nullable pointer to a hash table element. A Ptr |p| can be tested
@@ -812,20 +814,26 @@ class HashTable : private AllocPolicy
         }
     };
 
     // A Ptr that can be used to add a key after a failed lookup.
     class AddPtr : public Ptr
     {
         friend class HashTable;
         HashNumber keyHash;
-        mozilla::DebugOnly<uint64_t> mutationCount;
+#ifdef DEBUG
+        uint64_t mutationCount;
+#endif
 
         AddPtr(Entry &entry, const HashTable &tableArg, HashNumber hn)
-          : Ptr(entry, tableArg), keyHash(hn), mutationCount(tableArg.mutationCount)
+          : Ptr(entry, tableArg)
+          , keyHash(hn)
+#ifdef DEBUG
+          , mutationCount(tableArg.mutationCount)
+#endif
         {}
 
       public:
         // Leaves AddPtr uninitialized.
         AddPtr() {}
     };
 
     // A collection of hash table entries. The collection is enumerated by
@@ -979,28 +987,28 @@ class HashTable : private AllocPolicy
     }
 
   private:
     // HashTable is not copyable or assignable
     HashTable(const HashTable &) MOZ_DELETE;
     void operator=(const HashTable &) MOZ_DELETE;
 
   private:
-    uint32_t    hashShift;      // multiplicative hash shift
-    uint32_t    entryCount;     // number of entries in table
-    uint32_t    gen;            // entry storage generation number
-    uint32_t    removedCount;   // removed entry sentinels in table
-    Entry       *table;         // entry storage
+    static const size_t CAP_BITS = 24;
 
-    void setTableSizeLog2(unsigned sizeLog2)
-    {
-        hashShift = sHashBits - sizeLog2;
-    }
+  public:
+    Entry       *table;                 // entry storage
+    uint32_t    gen;                    // entry storage generation number
+    uint32_t    entryCount;             // number of entries in table
+    uint32_t    removedCount:CAP_BITS;  // removed entry sentinels in table
+    uint32_t    hashShift:8;            // multiplicative hash shift
 
 #ifdef JS_DEBUG
+    mozilla::DebugOnly<uint64_t>     mutationCount;
+    mutable mozilla::DebugOnly<bool> mEntered;
     mutable struct Stats
     {
         uint32_t        searches;       // total number of table searches
         uint32_t        steps;          // hash chain links traversed
         uint32_t        hits;           // searches that found key
         uint32_t        misses;         // searches that didn't find key
         uint32_t        addOverRemoved; // adds that recycled a removed entry
         uint32_t        removes;        // calls to remove
@@ -1010,38 +1018,39 @@ class HashTable : private AllocPolicy
         uint32_t        compresses;     // table compressions
         uint32_t        rehashes;       // tombstone decontaminations
     } stats;
 #   define METER(x) x
 #else
 #   define METER(x)
 #endif
 
-    friend class mozilla::ReentrancyGuard;
-    mutable mozilla::DebugOnly<bool> mEntered;
-    mozilla::DebugOnly<uint64_t>     mutationCount;
-
     // The default initial capacity is 32 (enough to hold 16 elements), but it
     // can be as low as 4.
     static const unsigned sMinCapacityLog2 = 2;
     static const unsigned sMinCapacity  = 1 << sMinCapacityLog2;
-    static const unsigned sMaxInit      = JS_BIT(23);
-    static const unsigned sMaxCapacity  = JS_BIT(24);
+    static const unsigned sMaxInit      = JS_BIT(CAP_BITS - 1);
+    static const unsigned sMaxCapacity  = JS_BIT(CAP_BITS);
     static const unsigned sHashBits     = mozilla::tl::BitSize<HashNumber>::value;
 
     // Hash-table alpha is conceptually a fraction, but to avoid floating-point
     // math we implement it as a ratio of integers.
     static const uint8_t sAlphaDenominator = 4;
     static const uint8_t sMinAlphaNumerator = 1; // min alpha: 1/4
     static const uint8_t sMaxAlphaNumerator = 3; // max alpha: 3/4
 
     static const HashNumber sFreeKey = Entry::sFreeKey;
     static const HashNumber sRemovedKey = Entry::sRemovedKey;
     static const HashNumber sCollisionBit = Entry::sCollisionBit;
 
+    void setTableSizeLog2(unsigned sizeLog2)
+    {
+        hashShift = sHashBits - sizeLog2;
+    }
+
     static bool isLiveHash(HashNumber hash)
     {
         return Entry::isLiveHash(hash);
     }
 
     static HashNumber prepareHash(const Lookup& l)
     {
         HashNumber keyHash = ScrambleHashCode(HashPolicy::hash(l));
@@ -1065,24 +1074,26 @@ class HashTable : private AllocPolicy
     {
         for (Entry *e = oldTable, *end = e + capacity; e < end; ++e)
             e->destroyIfLive();
         alloc.free_(oldTable);
     }
 
   public:
     explicit HashTable(AllocPolicy ap)
-      : AllocPolicy(ap),
-        hashShift(sHashBits),
-        entryCount(0),
-        gen(0),
-        removedCount(0),
-        table(nullptr),
-        mEntered(false),
-        mutationCount(0)
+      : AllocPolicy(ap)
+      , table(nullptr)
+      , gen(0)
+      , entryCount(0)
+      , removedCount(0)
+      , hashShift(sHashBits)
+#ifdef DEBUG
+      , mutationCount(0)
+      , mEntered(false)
+#endif
     {}
 
     MOZ_WARN_UNUSED_RESULT bool init(uint32_t length)
     {
         MOZ_ASSERT(!initialized());
 
         // Reject all lengths whose initial computed capacity would exceed
         // sMaxCapacity.  Round that maximum length down to the nearest power
@@ -1359,17 +1370,19 @@ class HashTable : private AllocPolicy
         if (e.hasCollision()) {
             e.removeLive();
             removedCount++;
         } else {
             METER(stats.removeFrees++);
             e.clearLive();
         }
         entryCount--;
+#ifdef DEBUG
         mutationCount++;
+#endif
     }
 
     void checkUnderloaded()
     {
         if (underloaded()) {
             METER(stats.shrinks++);
             (void) changeTableSize(-1);
         }
@@ -1442,32 +1455,36 @@ class HashTable : private AllocPolicy
             memset(table, 0, sizeof(*table) * capacity());
         } else {
             uint32_t tableCapacity = capacity();
             for (Entry *e = table, *end = table + tableCapacity; e < end; ++e)
                 e->clear();
         }
         removedCount = 0;
         entryCount = 0;
+#ifdef DEBUG
         mutationCount++;
+#endif
     }
 
     void finish()
     {
         MOZ_ASSERT(!mEntered);
 
         if (!table)
             return;
 
         destroyTable(*this, table, capacity());
         table = nullptr;
         gen++;
         entryCount = 0;
         removedCount = 0;
+#ifdef DEBUG
         mutationCount++;
+#endif
     }
 
     Range all() const
     {
         MOZ_ASSERT(table);
         return Range(*this, table, table + capacity());
     }
 
@@ -1547,18 +1564,18 @@ class HashTable : private AllocPolicy
             if (status == RehashFailed)
                 return false;
             if (status == Rehashed)
                 p.entry_ = &findFreeEntry(p.keyHash);
         }
 
         p.entry_->setLive(p.keyHash, mozilla::Forward<U>(u));
         entryCount++;
+#ifdef DEBUG
         mutationCount++;
-#ifdef DEBUG
         p.generation = generation();
         p.mutationCount = mutationCount;
 #endif
         return true;
     }
 
     // Note: |l| may be a reference to a piece of |u|, so this function
     // must take care not to use |l| after moving |u|.
@@ -1573,17 +1590,19 @@ class HashTable : private AllocPolicy
         if (entry->isRemoved()) {
             METER(stats.addOverRemoved++);
             removedCount--;
             keyHash |= sCollisionBit;
         }
 
         entry->setLive(keyHash, mozilla::Forward<U>(u));
         entryCount++;
+#ifdef DEBUG
         mutationCount++;
+#endif
     }
 
     // Note: |l| may be a reference to a piece of |u|, so this function
     // must take care not to use |l| after moving |u|.
     template <class U>
     bool putNew(const Lookup &l, U &&u)
     {
         if (checkOverloaded() == RehashFailed)
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -17,16 +17,19 @@ TOPLEVEL_BUILD := 1
 run_for_side_effects := $(shell echo 'MAKE: $(MAKE)')
 STATIC_LIBRARY_NAME = js_static
 LIBS		= $(NSPR_LIBS)
 
 DIST_INSTALL = 1
 
 ifdef JS_STANDALONE
 SHARED_LIBRARY_LIBS += $(call EXPAND_LIBNAME_PATH,mfbt,$(DEPTH)/mfbt)
+ifndef MOZ_NATIVE_ZLIB
+SHARED_LIBRARY_LIBS += $(call EXPAND_LIBNAME_PATH,mozz,$(DEPTH)/modules/zlib/src)
+endif
 endif
 
 ifdef JS_HAS_CTYPES
 ifdef MOZ_NATIVE_FFI
 LOCAL_INCLUDES = $(MOZ_FFI_CFLAGS)
 endif
 
 ifdef MOZ_NATIVE_FFI
@@ -214,22 +217,16 @@ endif
 
 # HP-UX does not require the extra linking of "-lm"
 ifeq (,$(filter HP-UX WINNT,$(OS_ARCH)))
 EXTRA_LIBS	+= -lm
 endif
 
 CFLAGS += $(MOZ_ZLIB_CFLAGS)
 EXTRA_LIBS += $(MOZ_ZLIB_LIBS)
-# Enable zlib usage if zlib has been located. When building the browser on
-# Windows, MOZ_ZLIB_LIBS is empty because zlib is part of libmozglue. We thus
-# also enable zlib if mozglue is present.
-ifneq (,$(MOZ_ZLIB_LIBS)$(MOZ_GLUE_LDFLAGS))
-DEFINES += -DUSE_ZLIB
-endif
 
 ifdef MOZ_SHARED_ICU
 EXTRA_DSO_LDOPTS += $(MOZ_ICU_LIBS)
 else
 SHARED_LIBRARY_LIBS += $(MOZ_ICU_LIBS)
 endif
 
 ifeq ($(OS_ARCH),FreeBSD)
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -474,8 +474,49 @@ js::DirectEval(JSContext *cx, const Call
     return EvalKernel(cx, args, DIRECT_EVAL, caller, scopeChain, iter.pc());
 }
 
 bool
 js::IsAnyBuiltinEval(JSFunction *fun)
 {
     return fun->maybeNative() == IndirectEval;
 }
+
+JS_FRIEND_API(bool)
+js::ExecuteInGlobalAndReturnScope(JSContext *cx, HandleObject global, HandleScript scriptArg,
+                                  MutableHandleObject scopeArg)
+{
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, global);
+    MOZ_ASSERT(global->is<GlobalObject>());
+
+    RootedScript script(cx, scriptArg);
+    if (script->compartment() != cx->compartment()) {
+        script = CloneScript(cx, NullPtr(), NullPtr(), script);
+        if (!script)
+            return false;
+    }
+
+    RootedObject scope(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
+    if (!scope)
+        return false;
+
+    if (!scope->setQualifiedVarObj(cx))
+        return false;
+
+    if (!scope->setUnqualifiedVarObj(cx))
+        return false;
+
+    JSObject *thisobj = JSObject::thisObject(cx, global);
+    if (!thisobj)
+        return false;
+
+    RootedValue thisv(cx, ObjectValue(*thisobj));
+    RootedValue rval(cx);
+    if (!ExecuteKernel(cx, script, *scope, thisv, EXECUTE_GLOBAL,
+                       NullFramePtr() /* evalInFrame */, rval.address()))
+    {
+        return false;
+    }
+
+    scopeArg.set(scope);
+    return true;
+}
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1885,16 +1885,57 @@ FindPath(JSContext *cx, unsigned argc, j
 
         result->setDenseElement(length - i - 1, ObjectValue(*obj));
     }
 
     args.rval().setObject(*result);
     return true;
 }
 
+static bool
+EvalReturningScope(JSContext *cx, unsigned argc, jsval *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    RootedString str(cx);
+    if (!JS_ConvertArguments(cx, args, "S", str.address()))
+        return false;
+
+    AutoStableStringChars strChars(cx);
+    if (!strChars.initTwoByte(cx, str))
+        return false;
+
+    mozilla::Range<const jschar> chars = strChars.twoByteRange();
+    size_t srclen = chars.length();
+    const jschar *src = chars.start().get();
+
+    JS::AutoFilename filename;
+    unsigned lineno;
+
+    DescribeScriptedCaller(cx, &filename, &lineno);
+
+    JS::CompileOptions options(cx);
+    options.setFileAndLine(filename.get(), lineno);
+    options.setNoScriptRval(true);
+    options.setCompileAndGo(false);
+
+    JS::SourceBufferHolder srcBuf(src, srclen, JS::SourceBufferHolder::NoOwnership);
+    RootedScript script(cx);
+    if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script))
+        return false;
+
+    RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
+    RootedObject scope(cx);
+    if (!js::ExecuteInGlobalAndReturnScope(cx, global, script, &scope))
+        return false;
+
+    args.rval().setObject(*scope);
+    return true;
+}
+
 static const JSFunctionSpecWithHelp TestingFunctions[] = {
     JS_FN_HELP("gc", ::GC, 0, 0,
 "gc([obj] | 'compartment')",
 "  Run the garbage collector. When obj is given, GC only its compartment.\n"
 "  If 'compartment' is given, GC any compartments that were scheduled for\n"
 "  GC via schedulegc."),
 
     JS_FN_HELP("minorgc", ::MinorGC, 0, 0,
@@ -2184,16 +2225,20 @@ static const JSFunctionSpecWithHelp Test
 "  the last array element is implicitly |target|.\n"),
 
 #ifdef DEBUG
     JS_FN_HELP("dumpObject", DumpObject, 1, 0,
 "dumpObject()",
 "  Dump an internal representation of an object."),
 #endif
 
+    JS_FN_HELP("evalReturningScope", EvalReturningScope, 1, 0,
+"evalReturningScope(scriptStr)",
+"  Evaluate the script in a new scope and return the scope."),
+
     JS_FS_HELP_END
 };
 
 static const JSPropertySpec TestingProperties[] = {
     JS_PSG("timesAccessed", TimesAccessed, 0),
     JS_PS_END
 };
 
--- a/js/src/builtin/embedjs.py
+++ b/js/src/builtin/embedjs.py
@@ -91,36 +91,26 @@ def embed(cxx, preprocessorOption, msgs,
   args = ['-D%(k)s=%(v)s' % { 'k': k, 'v': env[k] } for k in env]
   preprocessed = preprocess(cxx, preprocessorOption, combinedSources, args)
   processed = '\n'.join([line for line in preprocessed.splitlines() if \
                          (line.strip() and not line.startswith('#'))])
 
   with open(js_out, 'w') as output:
     output.write(processed)
   with open(c_out, 'w') as output:
-    if 'USE_ZLIB' in env:
-      import zlib
-      compressed = zlib.compress(processed)
-      data = ToCArray(compressed)
-      output.write(HEADER_TEMPLATE % {
-          'sources_type': 'unsigned char',
-          'sources_data': data,
-          'sources_name': 'compressedSources',
-          'compressed_total_length': len(compressed),
-          'raw_total_length': len(processed)
-      })
-    else:
-      data = ToCAsciiArray(processed)
-      output.write(HEADER_TEMPLATE % {
-          'sources_type': 'char',
-          'sources_data': data,
-          'sources_name': 'rawSources',
-          'compressed_total_length': 0,
-          'raw_total_length': len(processed)
-      })
+    import zlib
+    compressed = zlib.compress(processed)
+    data = ToCArray(compressed)
+    output.write(HEADER_TEMPLATE % {
+        'sources_type': 'unsigned char',
+        'sources_data': data,
+        'sources_name': 'compressedSources',
+        'compressed_total_length': len(compressed),
+        'raw_total_length': len(processed)
+    })
 
 def preprocess(cxx, preprocessorOption, source, args = []):
   if (not os.path.exists(cxx[0])):
     cxx[0] = which.which(cxx[0])
   # Clang seems to complain and not output anything if the extension of the
   # input is not something it recognizes, so just fake a .cpp here.
   tmpIn = 'self-hosting-cpp-input.cpp';
   tmpOut = 'self-hosting-preprocessed.pp';
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -1644,16 +1644,21 @@ ia64*-hpux*)
         MKSHLIB_FORCE_ALL=
         MKSHLIB_UNFORCE_ALL=
         DSO_LDOPTS=-SUBSYSTEM:WINDOWS
         _USE_CPP_INCLUDE_FLAG=1
         _DEFINES_CFLAGS='-FI $(DEPTH)/js/src/js-confdefs.h -DMOZILLA_CLIENT'
         _DEFINES_CXXFLAGS='-FI $(DEPTH)/js/src/js-confdefs.h -DMOZILLA_CLIENT'
         CFLAGS="$CFLAGS -W3 -Gy"
         CXXFLAGS="$CXXFLAGS -W3 -Gy"
+        if test "$_CC_SUITE" -ge "11"; then
+            dnl VS2012+ defaults to -arch:SSE2.
+            CFLAGS="$CFLAGS -arch:IA32"
+            CXXFLAGS="$CXXFLAGS -arch:IA32"
+        fi
         if test "$_CC_SUITE" -ge "12"; then
             dnl VS2013+ requires -FS when parallel building by make -jN.
             dnl If nothing, compiler sometimes causes C1041 error.
             dnl
             dnl Visual Studio 2013 supports -Gw flags
             dnl http://blogs.msdn.com/b/vcblog/archive/2013/09/11/introducing-gw-compiler-switch.aspx
             CFLAGS="$CFLAGS -FS -Gw"
             CXXFLAGS="$CXXFLAGS -FS -Gw"
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -693,16 +693,22 @@ class GCRuntime
 #endif
 
     /* Synchronize GC heap access between main thread and GCHelperState. */
     PRLock                *lock;
     mozilla::DebugOnly<PRThread *>   lockOwner;
 
     GCHelperState helperState;
 
+    /*
+     * During incremental sweeping, this field temporarily holds the arenas of
+     * the current AllocKind being swept in order of increasing free space.
+     */
+    SortedArenaList incrementalSweepList;
+
     ConservativeGCData conservativeGC;
 
     friend class js::GCHelperState;
     friend class js::gc::MarkingValidator;
     friend class js::gc::AutoTraceSession;
 };
 
 #ifdef JS_GC_ZEAL
--- a/js/src/gc/Heap.h
+++ b/js/src/gc/Heap.h
@@ -34,16 +34,17 @@ struct Runtime;
 namespace js {
 
 class FreeOp;
 
 namespace gc {
 
 struct Arena;
 class ArenaList;
+class SortedArenaList;
 struct ArenaHeader;
 struct Chunk;
 
 /*
  * This flag allows an allocation site to request a specific heap based upon the
  * estimated lifetime or lifetime requirements of objects allocated from that
  * site.
  */
@@ -600,17 +601,17 @@ struct Arena
 
     uintptr_t thingsEnd() {
         return address() + ArenaSize;
     }
 
     void setAsFullyUnused(AllocKind thingKind);
 
     template <typename T>
-    bool finalize(FreeOp *fop, AllocKind thingKind, size_t thingSize);
+    size_t finalize(FreeOp *fop, AllocKind thingKind, size_t thingSize);
 };
 
 static_assert(sizeof(Arena) == ArenaSize, "The hardcoded arena size must match the struct size.");
 
 inline size_t
 ArenaHeader::getThingSize() const
 {
     JS_ASSERT(allocated());
@@ -836,17 +837,18 @@ struct Chunk
 
     inline void addToAvailableList(JS::Zone *zone);
     inline void insertToAvailableList(Chunk **insertPoint);
     inline void removeFromAvailableList();
 
     ArenaHeader *allocateArena(JS::Zone *zone, AllocKind kind);
 
     void releaseArena(ArenaHeader *aheader);
-    void recycleArena(ArenaHeader *aheader, ArenaList &dest, AllocKind thingKind);
+    void recycleArena(ArenaHeader *aheader, SortedArenaList &dest, AllocKind thingKind,
+                      size_t thingsPerArena);
 
     static Chunk *allocate(JSRuntime *rt);
 
     void decommitAllArenas(JSRuntime *rt);
 
     /*
      * Assuming that the info.prevp points to the next field of the previous
      * chunk in a doubly-linked list, get that chunk.
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug673569.js
@@ -0,0 +1,24 @@
+function qualified_tests(prefix) {
+  let scope = evalReturningScope(prefix + "let x = 1");
+  assertEq(scope.x, 1);
+
+  scope = evalReturningScope(prefix + "var x = 1");
+  assertEq(scope.x, 1);
+
+  scope = evalReturningScope(prefix + "const x = 1");
+  assertEq(scope.x, 1);
+}
+
+qualified_tests("");
+qualified_tests("'use strict'; ");
+
+let scope = evalReturningScope("x = 1");
+assertEq(scope.x, 1);
+
+let fail = true;
+try {
+  evalReturningScope("'use strict'; x = 1");
+} catch (e) {
+  fail = false;
+}
+assertEq(fail, false);
--- a/js/src/jit-test/tests/ion/dce-with-rinstructions.js
+++ b/js/src/jit-test/tests/ion/dce-with-rinstructions.js
@@ -532,16 +532,35 @@ function rsqrt_object(i) {
     var o = { valueOf: function () { return t; } };
     var x = Math.sqrt(o); /* computed with t == i, not 1.5 */
     t = 1.5;
     if (uceFault_sqrt_object(i) || uceFault_sqrt_object(i))
         assertEq(x, Math.sqrt(99));
     return i;
 }
 
+var uceFault_atan2_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_atan2_number'));
+function ratan2_number(i) {
+    var x = Math.atan2(i, i+1);
+    if (uceFault_atan2_number(i) || uceFault_atan2_number(i))
+        assertEq(x, Math.atan2(99, 100));
+    return i;
+}
+
+var uceFault_atan2_object = eval(uneval(uceFault).replace('uceFault', 'uceFault_atan2_object'));
+function ratan2_object(i) {
+    var t = i;
+    var o = { valueOf: function () { return t; } };
+    var x = Math.atan2(o, o+1);
+    t = 1000;
+    if (uceFault_atan2_object(i) || uceFault_atan2_object(i))
+        assertEq(x, Math.atan2(i, i+1));
+    return i;
+}
+
 var uceFault_str_split = eval(uneval(uceFault).replace('uceFault', 'uceFault_str_split'))
 function rstr_split(i) {
     var x = "str01234567899876543210rts".split("" + i);
     if (uceFault_str_split(i) || uceFault_str_split(i)) {
         assertEq(x[0], "str012345678");
     }
     return i;
 }
@@ -599,16 +618,18 @@ for (i = 0; i < 100; i++) {
     rmin_object(i);
     rmax_number(i);
     rmax_object(i);
     rabs_number(i);
     rabs_object(i);
     rsqrt_number(i);
     rsqrt_float(i);
     rsqrt_object(i);
+    ratan2_number(i);
+    ratan2_object(i);
     rstr_split(i);
 }
 
 // Test that we can refer multiple time to the same recover instruction, as well
 // as chaining recover instructions.
 
 function alignedAlloc($size, $alignment) {
     var $1 = $size + 4 | 0;
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -5969,17 +5969,17 @@ DoBindNameFallback(JSContext *cx, Baseli
     mozilla::DebugOnly<JSOp> op = JSOp(*pc);
     FallbackICSpew(cx, stub, "BindName(%s)", js_CodeName[JSOp(*pc)]);
 
     JS_ASSERT(op == JSOP_BINDNAME);
 
     RootedPropertyName name(cx, frame->script()->getName(pc));
 
     RootedObject scope(cx);
-    if (!LookupNameWithGlobalDefault(cx, name, scopeChain, &scope))
+    if (!LookupNameUnqualified(cx, name, scopeChain, &scope))
         return false;
 
     res.setObject(*scope);
     return true;
 }
 
 typedef bool (*DoBindNameFallbackFn)(JSContext *, BaselineFrame *, ICBindName_Fallback *,
                                      HandleObject, MutableHandleValue);
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -4161,17 +4161,17 @@ BindNameIC::update(JSContext *cx, size_t
     IonScript *ion = outerScript->ionScript();
     BindNameIC &cache = ion->getCache(cacheIndex).toBindName();
     HandlePropertyName name = cache.name();
 
     RootedObject holder(cx);
     if (scopeChain->is<GlobalObject>()) {
         holder = scopeChain;
     } else {
-        if (!LookupNameWithGlobalDefault(cx, name, scopeChain, &holder))
+        if (!LookupNameUnqualified(cx, name, scopeChain, &holder))
             return nullptr;
     }
 
     // Stop generating new stubs once we hit the stub count limit, see
     // GetPropertyCache.
     if (cache.canAttachStub()) {
         if (scopeChain->is<GlobalObject>()) {
             if (!cache.attachGlobal(cx, outerScript, ion, scopeChain))
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -170,23 +170,27 @@ EvaluateExactReciprocal(TempAllocator &a
 void
 MDefinition::printName(FILE *fp) const
 {
     PrintOpcodeName(fp, op());
     fprintf(fp, "%u", id());
 }
 
 HashNumber
+MDefinition::addU32ToHash(HashNumber hash, uint32_t data)
+{
+    return data + (hash << 6) + (hash << 16) - hash;
+}
+
+HashNumber
 MDefinition::valueHash() const
 {
     HashNumber out = op();
-    for (size_t i = 0, e = numOperands(); i < e; i++) {
-        uint32_t valueNumber = getOperand(i)->id();
-        out = valueNumber + (out << 6) + (out << 16) - out;
-    }
+    for (size_t i = 0, e = numOperands(); i < e; i++)
+        out = addU32ToHash(out, getOperand(i)->id());
     return out;
 }
 
 bool
 MDefinition::congruentIfOperandsEqual(const MDefinition *ins) const
 {
     if (op() != ins->op())
         return false;
@@ -681,17 +685,19 @@ MParameter::printOpcode(FILE *fp) const
         fprintf(fp, " THIS_SLOT");
     else
         fprintf(fp, " %d", index());
 }
 
 HashNumber
 MParameter::valueHash() const
 {
-    return index_; // Why not?
+    HashNumber hash = MDefinition::valueHash();
+    hash = addU32ToHash(hash, index_);
+    return hash;
 }
 
 bool
 MParameter::congruentTo(const MDefinition *ins) const
 {
     if (!ins->isParameter())
         return false;
 
@@ -2861,34 +2867,86 @@ MAsmJSLoadGlobalVar::mightAlias(const MD
 {
     if (def->isAsmJSStoreGlobalVar()) {
         const MAsmJSStoreGlobalVar *store = def->toAsmJSStoreGlobalVar();
         return store->globalDataOffset() == globalDataOffset_;
     }
     return true;
 }
 
+HashNumber
+MAsmJSLoadGlobalVar::valueHash() const
+{
+    HashNumber hash = MDefinition::valueHash();
+    hash = addU32ToHash(hash, globalDataOffset_);
+    return hash;
+}
+
 bool
 MAsmJSLoadGlobalVar::congruentTo(const MDefinition *ins) const
 {
     if (ins->isAsmJSLoadGlobalVar()) {
         const MAsmJSLoadGlobalVar *load = ins->toAsmJSLoadGlobalVar();
         return globalDataOffset_ == load->globalDataOffset_;
     }
     return false;
 }
 
+HashNumber
+MAsmJSLoadFuncPtr::valueHash() const
+{
+    HashNumber hash = MDefinition::valueHash();
+    hash = addU32ToHash(hash, globalDataOffset_);
+    return hash;
+}
+
+bool
+MAsmJSLoadFuncPtr::congruentTo(const MDefinition *ins) const
+{
+    if (ins->isAsmJSLoadFuncPtr()) {
+        const MAsmJSLoadFuncPtr *load = ins->toAsmJSLoadFuncPtr();
+        return globalDataOffset_ == load->globalDataOffset_;
+    }
+    return false;
+}
+
+HashNumber
+MAsmJSLoadFFIFunc::valueHash() const
+{
+    HashNumber hash = MDefinition::valueHash();
+    hash = addU32ToHash(hash, globalDataOffset_);
+    return hash;
+}
+
+bool
+MAsmJSLoadFFIFunc::congruentTo(const MDefinition *ins) const
+{
+    if (ins->isAsmJSLoadFFIFunc()) {
+        const MAsmJSLoadFFIFunc *load = ins->toAsmJSLoadFFIFunc();
+        return globalDataOffset_ == load->globalDataOffset_;
+    }
+    return false;
+}
+
 bool
 MLoadSlot::mightAlias(const MDefinition *store) const
 {
     if (store->isStoreSlot() && store->toStoreSlot()->slot() != slot())
         return false;
     return true;
 }
 
+HashNumber
+MLoadSlot::valueHash() const
+{
+    HashNumber hash = MDefinition::valueHash();
+    hash = addU32ToHash(hash, slot_);
+    return hash;
+}
+
 bool
 MGuardShapePolymorphic::congruentTo(const MDefinition *ins) const
 {
     if (!ins->isGuardShapePolymorphic())
         return false;
 
     const MGuardShapePolymorphic *other = ins->toGuardShapePolymorphic();
     if (numShapes() != other->numShapes())
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -317,20 +317,20 @@ class MDefinition : public MNode
 #   undef DEFINE_OPCODES
         Op_Invalid
     };
 
   private:
     InlineList<MUse> uses_;        // Use chain.
     uint32_t id_;                  // Instruction ID, which after block re-ordering
                                    // is sorted within a basic block.
+    uint32_t flags_;               // Bit flags.
     Range *range_;                 // Any computed range for this def.
     MIRType resultType_;           // Representation of result type.
     types::TemporaryTypeSet *resultTypeSet_; // Optional refinement of the result type.
-    uint32_t flags_;                 // Bit flags.
     union {
         MDefinition *dependency_;  // Implicit dependency (store, call, etc.) of this instruction.
                                    // Used by alias analysis, GVN and LICM.
         uint32_t virtualRegister_;   // Used by lowering to map definitions to virtual registers.
     };
 
     // Track bailouts by storing the current pc in MIR instruction. Also used
     // for profiling and keeping track of what the last known pc was.
@@ -355,23 +355,25 @@ class MDefinition : public MNode
         flags_ |= flags;
     }
 
   protected:
     virtual void setBlock(MBasicBlock *block) {
         block_ = block;
     }
 
+    static HashNumber addU32ToHash(HashNumber hash, uint32_t data);
+
   public:
     MDefinition()
       : id_(0),
+        flags_(0),
         range_(nullptr),
         resultType_(MIRType_None),
         resultTypeSet_(nullptr),