Merge last PGO-green changeset of mozilla-inbound to mozilla-central
authorEd Morley <emorley@mozilla.com>
Wed, 14 Nov 2012 14:35:55 +0000
changeset 113232 87928cd21b40
parent 113231 fc1684f4d3a9 (current diff)
parent 113211 83d175cb799d (diff)
child 113233 8d211e5afa8b
child 113319 6ffdbb94c3cc
push id18022
push useremorley@mozilla.com
push dateWed, 14 Nov 2012 16:17:14 +0000
treeherdermozilla-inbound@8d211e5afa8b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone19.0a1
first release with
nightly linux32
87928cd21b40 / 19.0a1 / 20121114102936 / files
nightly linux64
87928cd21b40 / 19.0a1 / 20121114102936 / files
nightly mac
87928cd21b40 / 19.0a1 / 20121114102936 / files
nightly win32
87928cd21b40 / 19.0a1 / 20121114102936 / files
nightly win64
87928cd21b40 / 19.0a1 / 20121114102936 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_geoprompt.js
browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_geoprompt_page.html
browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_openlocation.js
browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_zoomrestore.js
intl/uconv/ucvko/nsEUCKRToUnicode.cpp
intl/uconv/ucvko/nsEUCKRToUnicode.h
intl/uconv/ucvko/nsUnicodeToEUCKR.cpp
intl/uconv/ucvko/nsUnicodeToEUCKR.h
toolkit/devtools/debugger/dbg-transport.js
toolkit/system/windowsproxy/Makefile.in
toolkit/system/windowsproxy/nsWindowsSystemProxySettings.cpp
--- a/accessible/src/generic/BaseAccessibles.cpp
+++ b/accessible/src/generic/BaseAccessibles.cpp
@@ -38,16 +38,37 @@ NS_IMPL_ISUPPORTS_INHERITED0(LeafAccessi
 Accessible*
 LeafAccessible::ChildAtPoint(int32_t aX, int32_t aY,
                              EWhichChildAtPoint aWhichChild)
 {
   // Don't walk into leaf accessibles.
   return this;
 }
 
+bool
+LeafAccessible::AppendChild(Accessible* aChild)
+{
+  NS_NOTREACHED("AppendChild called on leaf accessible!");
+  return false;
+}
+
+bool
+LeafAccessible::InsertChildAt(uint32_t aIndex, Accessible* aChild)
+{
+  NS_NOTREACHED("InsertChildAt called on leaf accessible!");
+  return false;
+}
+
+bool
+LeafAccessible::RemoveChild(Accessible* aChild)
+{
+  NS_NOTREACHED("RemoveChild called on leaf accessible!");
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // LeafAccessible: Accessible private
 
 void
 LeafAccessible::CacheChildren()
 {
   // No children for leaf accessible.
 }
--- a/accessible/src/generic/BaseAccessibles.h
+++ b/accessible/src/generic/BaseAccessibles.h
@@ -29,16 +29,20 @@ public:
   LeafAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // Accessible
   virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY,
                                    EWhichChildAtPoint aWhichChild);
+  
+  virtual bool AppendChild(Accessible* aChild) MOZ_OVERRIDE MOZ_FINAL;
+  virtual bool InsertChildAt(uint32_t aIndex, Accessible* aChild) MOZ_OVERRIDE MOZ_FINAL;
+  virtual bool RemoveChild(Accessible* aChild) MOZ_OVERRIDE MOZ_FINAL;
 
 protected:
 
   // Accessible
   virtual void CacheChildren();
 };
 
 /**
--- a/accessible/tests/mochitest/states/test_link.html
+++ b/accessible/tests/mochitest/states/test_link.html
@@ -18,23 +18,24 @@
   <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
 
   <script type="application/javascript">
     //gA11yEventDumpToConsole = true; // debug stuff
 
+    var gLinkWindow = null;
     function closeDocChecker()
     {
       this.__proto__ = new asyncInvokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE);
 
       this.check = function closeDocChecker_check(aEvent)
       {
-        aEvent.accessible.rootDocument.window.close();
+        gLinkWindow = aEvent.accessible.rootDocument.window;
       }
 
       this.match = function closeDocChecker_match(aEvent)
       {
         return true;
       }
     }
 
@@ -51,18 +52,16 @@
       }
 
       this.getID = function clickLink_getID()
       {
         return "link + '" + aID + "' clicked.";
       }
     }
 
-gA11yEventDumpToConsole = true;
-
     var gQueue = null;
     function doTest()
     {
       // a@href and its text node
       testStates("link_href", STATE_LINKED);
       testStates(getAccessible("link_href").firstChild, STATE_LINKED);
 
       // a@onclick
@@ -84,16 +83,17 @@ gA11yEventDumpToConsole = true;
       testStates("link_notlink", 0, 0, STATE_LINKED);
 
       // a: no traversed state
       testStates("link_traversed", 0, 0, STATE_TRAVERSED);
 
       // a: traversed state
       gQueue = new eventQueue();
       gQueue.push(new clickLink("link_traversed"));
+      gQueue.onFinish = function() { gLinkWindow.close(); }
       gQueue.invoke(); // will call SimpleTest.finsih();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 
 </head>
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -582,8 +582,12 @@ pref("browser.prompt.allowNative", false
 // a restart is required to enable a new value.
 pref("network.activity.blipIntervalMilliseconds", 250);
 
 // Send some sites a custom user-agent.
 pref("general.useragent.override.facebook.com", "\(Mobile#(Android; Mobile");
 pref("general.useragent.override.youtube.com", "\(Mobile#(Android; Mobile");
 
 pref("jsloader.reuseGlobal", true);
+
+// Enable freeing dirty pages when minimizing memory; this reduces memory
+// consumption when applications are sent to the background.
+pref("memory.free_dirty_pages", true);
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -5324,21 +5324,17 @@ function contentAreaClick(event, isPanel
         urlSecurityCheck(href, linkNode.ownerDocument.nodePrincipal);
       }
       catch(ex) {
         // Prevent loading unsecure destinations.
         event.preventDefault();
         return;
       }
 
-      let postData = {};
-      let url = getShortcutOrURI(href, postData);
-      if (!url)
-        return;
-      loadURI(url, null, postData.value, false);
+      loadURI(href, null, null, false);
       event.preventDefault();
       return;
     }
 
     if (linkNode.getAttribute("rel") == "sidebar") {
       // This is the Opera convention for a special link that, when clicked,
       // allows to add a sidebar panel.  The link's title attribute contains
       // the title that should be used for the sidebar panel.
--- a/browser/base/content/test/browser_contentAreaClick.js
+++ b/browser/base/content/test/browser_contentAreaClick.js
@@ -108,17 +108,17 @@ let gTests = [
   },
 
   {
     desc: "Panel click",
     setup: function() {},
     clean: function() {},
     event: {},
     targets: [ "panellink" ],
-    expectedInvokedMethods: [ "urlSecurityCheck", "getShortcutOrURI", "loadURI" ],
+    expectedInvokedMethods: [ "urlSecurityCheck", "loadURI" ],
     preventDefault: true,
   },
 
   {
     desc: "Simple middle click opentab",
     setup: function() {},
     clean: function() {},
     event: { button: 1 },
--- a/browser/components/migration/src/SafariProfileMigrator.js
+++ b/browser/components/migration/src/SafariProfileMigrator.js
@@ -332,19 +332,19 @@ Preferences.prototype = {
         // Allowed, originating site only   --        3
         this._set("WebKitDisplayImagesKey", "permissions.default.image",
                   function(webkitVal) webkitVal ? 1 : 2);
 
         // Default charset migration
         this._set("WebKitDefaultTextEncodingName", "intl.charset.default",
           function(webkitCharset) {
             // We don't support x-mac-korean (see bug 713516), but it mostly matches
-            // x-windows-949.
+            // EUC-KR.
             if (webkitCharset == "x-mac-korean")
-              return "x-windows-949";
+              return "EUC-KR";
 
             // getCharsetAlias throws if an invalid value is passed in.
             try {
               return Cc["@mozilla.org/charset-converter-manager;1"].
                      getService(Ci.nsICharsetConverterManager).
                      getCharsetAlias(webkitCharset);
             }
             catch(ex) {
--- a/browser/components/privatebrowsing/test/browser/perwindow/Makefile.in
+++ b/browser/components/privatebrowsing/test/browser/perwindow/Makefile.in
@@ -23,13 +23,14 @@ MOCHITEST_BROWSER_FILES =  \
 		browser_privatebrowsing_DownloadLastDirWithCPS.js \
 		browser_privatebrowsing_geoprompt.js \
 		browser_privatebrowsing_geoprompt_page.html \
 		browser_privatebrowsing_lastpbcontextexited.js \
 		browser_privatebrowsing_localStorage.js \
 		browser_privatebrowsing_localStorage_page1.html \
 		browser_privatebrowsing_localStorage_page2.html \
 		browser_privatebrowsing_opendir.js \
+		browser_privatebrowsing_openlocation.js \
 		browser_privatebrowsing_theming.js \
 		browser_privatebrowsing_zoomrestore.js \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
copy from browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_openlocation.js
copy to browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_openlocation.js
--- a/browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_openlocation.js
+++ b/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_openlocation.js
@@ -2,30 +2,27 @@
  * 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/. */
 
 // This test makes sure that Open Location dialog is usable inside the private browsing
 // mode without leaving any trace of the URLs visited.
 
 function test() {
   // initialization
-  gPrefService.setBoolPref("browser.privatebrowsing.keep_current_session", true);
-  let pb = Cc["@mozilla.org/privatebrowsing;1"].
-           getService(Ci.nsIPrivateBrowsingService);
   waitForExplicitFinish();
 
-  function openLocation(url, autofilled, callback) {
+  function openLocation(aWindow, url, autofilled, callback) {
     function observer(aSubject, aTopic, aData) {
       switch (aTopic) {
         case "domwindowopened":
           let dialog = aSubject.QueryInterface(Ci.nsIDOMWindow);
           dialog.addEventListener("load", function () {
             dialog.removeEventListener("load", arguments.callee, false);
 
-            let browser = gBrowser.selectedBrowser;
+            let browser = aWindow.gBrowser.selectedBrowser;
             browser.addEventListener("load", function() {
               browser.removeEventListener("load", arguments.callee, true);
 
               is(browser.currentURI.spec, url,
                  "The correct URL should be loaded via the open location dialog");
               executeSoon(callback);
             }, true);
 
@@ -41,38 +38,60 @@ function test() {
           break;
 
         case "domwindowclosed":
           Services.ww.unregisterNotification(arguments.callee);
           break;
       }
     }
 
-    Services.ww.registerNotification(observer);
-    gPrefService.setIntPref("general.open_location.last_window_choice", 0);
-    openDialog("chrome://browser/content/openLocation.xul", "_blank",
-               "chrome,titlebar", window);
+    executeSoon(function() {
+      Services.ww.registerNotification(observer);
+      gPrefService.setIntPref("general.open_location.last_window_choice", 0);
+      aWindow.openDialog("chrome://browser/content/openLocation.xul", "_blank",
+                         "chrome,titlebar", aWindow);
+    });
   }
 
+  let windowsToClose = [];
+  function testOnWindow(options, callback) {
+    let win = OpenBrowserWindow(options);
+    win.addEventListener("load", function onLoad() {
+      win.removeEventListener("load", onLoad, false);
+      windowsToClose.push(win);
+      callback(win);
+    }, false);
+  };
+
+  registerCleanupFunction(function() {
+    windowsToClose.forEach(function(win) {
+      win.close();
+    });
+  });
 
   if (gPrefService.prefHasUserValue("general.open_location.last_url"))
     gPrefService.clearUserPref("general.open_location.last_url");
 
-  openLocation("http://example.com/", "", function() {
-    openLocation("http://example.org/", "http://example.com/", function() {
-      // enter private browsing mode
-      pb.privateBrowsingEnabled = true;
-      openLocation("about:logo", "", function() {
-        openLocation("about:buildconfig", "about:logo", function() {
-          // exit private browsing mode
-          pb.privateBrowsingEnabled = false;
-          openLocation("about:blank", "http://example.org/", function() {
-            gPrefService.clearUserPref("general.open_location.last_url");
-            if (gPrefService.prefHasUserValue("general.open_location.last_window_choice"))
-              gPrefService.clearUserPref("general.open_location.last_window_choice");
-            gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session");
-            finish();
+  testOnWindow({private: false}, function(win) {
+    openLocation(win, "http://example.com/", "", function() {
+      testOnWindow({private: false}, function(win) {
+        openLocation(win, "http://example.org/", "http://example.com/", function() {
+          testOnWindow({private: true}, function(win) {
+            openLocation(win, "about:logo", "", function() {
+                testOnWindow({private: true}, function(win) {
+                  openLocation(win, "about:buildconfig", "about:logo", function() {
+                    testOnWindow({private: false}, function(win) {
+                      openLocation(win, "about:blank", "http://example.org/", function() {
+                        gPrefService.clearUserPref("general.open_location.last_url");
+                        if (gPrefService.prefHasUserValue("general.open_location.last_window_choice"))
+                          gPrefService.clearUserPref("general.open_location.last_window_choice");
+                        finish();
+                       });
+                     });
+                  });
+               });
+            });
           });
         });
       });
     });
   });
 }
--- a/browser/components/sessionstore/src/SessionStore.jsm
+++ b/browser/components/sessionstore/src/SessionStore.jsm
@@ -74,16 +74,17 @@ const TAB_EVENTS = [
 #endif
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 // debug.js adds NS_ASSERT. cf. bug 669196
 Cu.import("resource://gre/modules/debug.js");
 Cu.import("resource:///modules/TelemetryTimestamps.jsm");
 Cu.import("resource://gre/modules/TelemetryStopwatch.jsm");
+Cu.import("resource://gre/modules/osfile.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
   "resource://gre/modules/NetUtil.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ScratchpadManager",
   "resource:///modules/devtools/scratchpad-manager.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DocumentUtils",
   "resource:///modules/sessionstore/DocumentUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SessionStorage",
@@ -436,19 +437,28 @@ let SessionStoreInternal = {
     }
 
     // at this point, we've as good as resumed the session, so we can
     // clear the resume_session_once flag, if it's set
     if (this._loadState != STATE_QUITTING &&
         this._prefBranch.getBoolPref("sessionstore.resume_session_once"))
       this._prefBranch.setBoolPref("sessionstore.resume_session_once", false);
 
+    this._initEncoding();
+
     this._initialized = true;
   },
 
+  _initEncoding : function ssi_initEncoding() {
+    // The (UTF-8) encoder used to write to files.
+    XPCOMUtils.defineLazyGetter(this, "_writeFileEncoder", function () {
+      return new TextEncoder();
+    });
+  },
+
   _initPrefs : function() {
     XPCOMUtils.defineLazyGetter(this, "_prefBranch", function () {
       return Services.prefs.getBranch("browser.");
     });
 
     // minimal interval between two save operations (in milliseconds)
     XPCOMUtils.defineLazyGetter(this, "_interval", function () {
       // used often, so caching/observing instead of fetching on-demand
@@ -4430,37 +4440,31 @@ let SessionStoreInternal = {
    * @param aFile
    *        nsIFile
    * @param aData
    *        String data
    */
   _writeFile: function ssi_writeFile(aFile, aData) {
     let refObj = {};
     TelemetryStopwatch.start("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
-    // Initialize the file output stream.
-    var ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"].
-                  createInstance(Ci.nsIFileOutputStream);
-    ostream.init(aFile, 0x02 | 0x08 | 0x20, 0600, ostream.DEFER_OPEN);
-
-    // Obtain a converter to convert our data to a UTF-8 encoded input stream.
-    var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
-                    createInstance(Ci.nsIScriptableUnicodeConverter);
-    converter.charset = "UTF-8";
-
-    // Asynchronously copy the data to the file.
-    var istream = converter.convertToInputStream(aData);
-    var self = this;
-    NetUtil.asyncCopy(istream, ostream, function(rc) {
-      if (Components.isSuccessCode(rc)) {
+    let path = aFile.path;
+    let encoded = this._writeFileEncoder.encode(aData);
+    let promise = OS.File.writeAtomic(path, encoded, {tmpPath: path + ".tmp"});
+
+    promise.then(
+      function onSuccess() {
         TelemetryStopwatch.finish("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
         Services.obs.notifyObservers(null,
-                                     "sessionstore-state-write-complete",
-                                     "");
-      }
-    });
+                                      "sessionstore-state-write-complete",
+                                      "");
+      },
+      function onFailure(reason) {
+        TelemetryStopwatch.cancel("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
+        Components.reportError("ssi_writeFile failure " + reason);
+      });
   }
 };
 
 // This is used to help meter the number of restoring tabs. This is the control
 // point for telling the next tab to restore. It gets attached to each gBrowser
 // via gBrowser.addTabsProgressListener
 let gRestoreTabsProgressListener = {
   onStateChange: function(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
--- a/browser/installer/windows/nsis/defines.nsi.in
+++ b/browser/installer/windows/nsis/defines.nsi.in
@@ -30,17 +30,17 @@
 !define LSP_CATEGORIES "0x00000000"
 
 # Due to official and beta using the same branding this is needed to
 # differentiante between the url used by the stub for downloading.
 !if "@MOZ_UPDATE_CHANNEL@" == "beta"
 !define BETA_UPDATE_CHANNEL
 !endif
 
-!define BaseURLStubPing "http://download-stats.mozilla.org/stub/v1/"
+!define BaseURLStubPing "http://download-stats.mozilla.org/stub/v2/"
 
 # NO_INSTDIR_FROM_REG is defined for pre-releases which have a PreReleaseSuffix
 # (e.g. Alpha X, Beta X, etc.) to prevent finding a non-default installation
 # directory in the registry and using that as the default. This prevents
 # Beta releases built with official branding from finding an existing install
 # of an official release and defaulting to its installation directory.
 !if "@PRE_RELEASE_SUFFIX@" != ""
 !define NO_INSTDIR_FROM_REG
--- a/browser/installer/windows/nsis/stub.nsi
+++ b/browser/installer/windows/nsis/stub.nsi
@@ -63,16 +63,17 @@ Var ExistingTopDir
 Var SpaceAvailableBytes
 Var InitialInstallDir
 Var HandleDownload
 Var CanSetAsDefault
 Var TmpVal
 Var InstallCounterStep
 
 Var ExitCode
+Var DownloadStartTime
 Var SecondsToDownload
 Var ExistingProfile
 Var ExistingInstall
 Var DownloadedAmount
 Var FirefoxLaunch
 
 Var HEIGHT_PX
 Var CTL_RIGHT_PX
@@ -887,17 +888,17 @@ Function createInstall
   ${EndIf}
 
   GetTempFileName $2
   GetFileTime $2 $1 $0
   Delete $2
   System::Int64Op $1 * 0x100000000
   Pop $1
   System::Int64Op $1 + $0
-  Pop $SecondsToDownload
+  Pop $DownloadStartTime
 
   ${NSD_CreateTimer} StartDownload ${DownloadIntervalMS}
 
   LockWindow off
   nsDialogs::Show
 
   ${NSD_FreeImage} $0
   ${NSD_FreeImage} $1
@@ -905,31 +906,29 @@ Function createInstall
   ${NSD_FreeImage} $HwndBitmapBlurb2
   ${NSD_FreeImage} $HWndBitmapBlurb3
 FunctionEnd
 
 Function leaveInstall
 # Need a ping?
 FunctionEnd
 
-; This function is not idempotent. It calculates the amount of time between now
-; and $SecondsToDownload and stores the results back into $SecondsToDownload.
-; For that reason it should only be called once for the purpose of determining
-; the number of elapsed seconds to download.
+; GetSecondsToDownload calculates the amount of time between $DownloadStartTime
+; and now, and stores the results into $SecondsToDownload.
 Function GetSecondsToDownload
   GetTempFileName $2
   GetFileTime $2 $1 $0
   Delete $2
   System::Int64Op $1 * 0x100000000
   Pop $1
   System::Int64Op $1 + $0
   Pop $0
-  System::Int64Op $0 - $SecondsToDownload
-  Pop $SecondsToDownload
-  System::Int64Op $SecondsToDownload / 10000000
+  System::Int64Op $0 - $DownloadStartTime
+  Pop $4
+  System::Int64Op $4 / 10000000
   Pop $SecondsToDownload
 FunctionEnd
 
 Function StartDownload
   ${NSD_KillTimer} StartDownload
   InetBgDL::Get "${URLStubDownload}" "$PLUGINSDIR\download.exe" /END
   StrCpy $4 ""
   ${NSD_CreateTimer} OnDownload ${DownloadIntervalMS}
--- a/browser/themes/gnomestripe/downloads/downloads.css
+++ b/browser/themes/gnomestripe/downloads/downloads.css
@@ -257,17 +257,18 @@ toolbar[iconsize="large"] #downloads-ind
   border-radius: 2px;
   box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
 }
 
 #downloads-indicator-progress > .progress-bar {
   -moz-appearance: none;
   min-width: 0;
   min-height: 0;
-  background-image: -moz-linear-gradient(#5ab9ff, #37a4ff);
+  background-color: rgb(90, 185, 255);
+  background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px);
   border: 1px solid;
   border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
   border-radius: 2px 0 0 2px;
 }
 
 #downloads-indicator-progress > .progress-remainder {
   -moz-appearance: none;
   min-width: 0;
@@ -275,14 +276,14 @@ toolbar[iconsize="large"] #downloads-ind
   background-image: -moz-linear-gradient(#505050, #575757);
   border: 1px solid;
   border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
   -moz-border-start: none;
   border-radius: 0 2px 2px 0;
 }
 
 #downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
-  background-image: -moz-linear-gradient(#dce651, #dae631);
+  background-color: rgb(220, 230, 81);
 }
 
 #downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
   background-image: -moz-linear-gradient(#4b5000, #515700);
 }
--- a/browser/themes/pinstripe/downloads/downloads.css
+++ b/browser/themes/pinstripe/downloads/downloads.css
@@ -255,17 +255,18 @@ richlistitem[type="download"][state="1"]
   border-radius: 2px;
   box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
 }
 
 #downloads-indicator-progress > .progress-bar {
   -moz-appearance: none;
   min-width: 0;
   min-height: 0;
-  background-image: -moz-linear-gradient(#5ab9ff, #37a4ff);
+  background-color: rgb(90, 185, 255);
+  background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px);
   border: 1px solid;
   border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
   border-radius: 2px 0 0 2px;
 }
 
 #downloads-indicator-progress > .progress-remainder {
   -moz-appearance: none;
   min-width: 0;
@@ -273,14 +274,14 @@ richlistitem[type="download"][state="1"]
   background-image: -moz-linear-gradient(#505050, #575757);
   border: 1px solid;
   border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
   -moz-border-start: none;
   border-radius: 0 2px 2px 0;
 }
 
 #downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
-  background-image: -moz-linear-gradient(#dce651, #dae631);
+  background-color: rgb(220, 230, 81);
 }
 
 #downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
   background-image: -moz-linear-gradient(#4b5000, #515700);
 }
--- a/browser/themes/winstripe/downloads/downloads.css
+++ b/browser/themes/winstripe/downloads/downloads.css
@@ -254,17 +254,18 @@ richlistitem[type="download"][state="1"]
   border-radius: 2px;
   box-shadow: 0 1px 0 hsla(0,0%,100%,.4);
 }
 
 #downloads-indicator-progress > .progress-bar {
   -moz-appearance: none;
   min-width: 0;
   min-height: 0;
-  background-image: -moz-linear-gradient(#5ab9ff, #37a4ff);
+  background-color: rgb(90, 185, 255);
+  background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px);
   border: 1px solid;
   border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
   border-radius: 2px 0 0 2px;
 }
 
 #downloads-indicator-progress > .progress-remainder {
   -moz-appearance: none;
   min-width: 0;
@@ -272,14 +273,14 @@ richlistitem[type="download"][state="1"]
   background-image: -moz-linear-gradient(#505050, #575757);
   border: 1px solid;
   border-color: hsla(0,0%,0%,.6) hsla(0,0%,0%,.4) hsla(0,0%,0%,.4);
   -moz-border-start: none;
   border-radius: 0 2px 2px 0;
 }
 
 #downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-bar {
-  background-image: -moz-linear-gradient(#dce651, #dae631);
+  background-color: rgb(220, 230, 81);
 }
 
 #downloads-indicator[paused] > #downloads-indicator-anchor > #downloads-indicator-progress-area > #downloads-indicator-progress > .progress-remainder {
   background-image: -moz-linear-gradient(#4b5000, #515700);
 }
--- a/config/makefiles/xpcshell.mk
+++ b/config/makefiles/xpcshell.mk
@@ -57,16 +57,17 @@ xpcshell-tests-remote: DM_TRANS?=adb
 xpcshell-tests-remote:
 	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/build \
 	  -I$(topsrcdir)/build/mobile \
 	  -I$(topsrcdir)/testing/mozbase/mozdevice/mozdevice \
 	  $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
 	  --build-info-json=$(DEPTH)/mozinfo.json \
+	  --testing-modules-dir=$(DEPTH)/_tests/modules \
 	  $(EXTRA_TEST_ARGS) \
 	  --dm_trans=$(DM_TRANS) \
 	  --deviceIP=${TEST_DEVICE} \
 	  --objdir=$(DEPTH) \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 
 ###########################################################################
 # Execute a single test, specified in $(SOLO_FILE), but don't automatically
@@ -107,16 +108,17 @@ check-one-remote:
 	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/build \
 	  -I$(topsrcdir)/build/mobile \
 	  -I$(topsrcdir)/testing/mozbase/mozdevice/mozdevice \
 	  $(testxpcsrcdir)/remotexpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  --test-path=$(SOLO_FILE) \
+	  --testing-modules-dir=$(DEPTH)/_tests/modules \
 	  --profile-name=$(MOZ_APP_NAME) \
 	  --verbose \
 	  $(EXTRA_TEST_ARGS) \
 	  --dm_trans=$(DM_TRANS) \
 	  --deviceIP=${TEST_DEVICE} \
 	  --objdir=$(DEPTH) \
           --noSetup \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -112,27 +112,16 @@ using namespace mozilla::gfx;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
 
 namespace mgfx = mozilla::gfx;
 
 #define NS_TEXTMETRICSAZURE_PRIVATE_IID \
   {0x9793f9e7, 0x9dc1, 0x4e9c, {0x81, 0xc8, 0xfc, 0xa7, 0x14, 0xf4, 0x30, 0x79}}
 
-nsresult
-NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult)
-{
-  Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1);
-  nsRefPtr<nsIDOMCanvasRenderingContext2D> ctx =
-    new mozilla::dom::CanvasRenderingContext2D();
-
-  ctx.forget(aResult);
-  return NS_OK;
-}
-
 namespace mozilla {
 namespace dom {
 
 static float kDefaultFontSize = 10.0;
 static NS_NAMED_LITERAL_STRING(kDefaultFontName, "sans-serif");
 static NS_NAMED_LITERAL_STRING(kDefaultFontStyle, "10px sans-serif");
 
 // Cap sigma to avoid overly large temp surfaces.
@@ -529,20 +518,18 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(CanvasRenderingContext2D)
   return nsCCUncollectableMarker::sGeneration && tmp->IsBlack();
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CanvasRenderingContext2D)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(nsIDOMCanvasRenderingContext2D)
   NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports,
-                                   nsICanvasRenderingContextInternal)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 /**
  ** CanvasRenderingContext2D impl
  **/
 
 
 // Initialize our static variables.
@@ -662,43 +649,16 @@ CanvasRenderingContext2D::SetStyleFromSt
   nscolor color;
   if (!ParseColor(str, &color)) {
     return;
   }
 
   CurrentState().SetColorStyle(whichStyle, color);
 }
 
-void
-CanvasRenderingContext2D::SetStyleFromStringOrInterface(const nsAString& aStr,
-                                                        nsISupports *aInterface,
-                                                        Style aWhichStyle)
-{
-  if (!aStr.IsVoid()) {
-    SetStyleFromString(aStr, aWhichStyle);
-    return;
-  }
-
-  if (aInterface) {
-    nsCOMPtr<CanvasGradient> grad(do_QueryInterface(aInterface));
-    if (grad) {
-      SetStyleFromGradient(grad, aWhichStyle);
-      return;
-    }
-
-    nsCOMPtr<CanvasPattern> pattern(do_QueryInterface(aInterface));
-    if (pattern) {
-      SetStyleFromPattern(pattern, aWhichStyle);
-      return;
-    }
-  }
-
-  WarnAboutUnexpectedStyle(mCanvasElement);
-}
-
 nsISupports*
 CanvasRenderingContext2D::GetStyleAsStringOrInterface(nsAString& aStr,
                                                       CanvasMultiGetterType& aType,
                                                       Style aWhichStyle)
 {
   const ContextState &state = CurrentState();
   nsISupports* supports;
   if (state.patternStyles[aWhichStyle]) {
@@ -1062,49 +1022,28 @@ CanvasRenderingContext2D::GetInputStream
 
 SurfaceFormat
 CanvasRenderingContext2D::GetSurfaceFormat() const
 {
   return mOpaque ? FORMAT_B8G8R8X8 : FORMAT_B8G8R8A8;
 }
 
 //
-// CanvasRenderingContext2D impl
-//
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetCanvas(nsIDOMHTMLCanvasElement **canvas)
-{
-  if (mCanvasElement) {
-    NS_IF_ADDREF(*canvas = mCanvasElement->GetOriginalCanvas());
-  }
-
-  return NS_OK;
-}
-
-//
 // state
 //
 
 void
 CanvasRenderingContext2D::Save()
 {
   EnsureTarget();
   mStyleStack[mStyleStack.Length() - 1].transform = mTarget->GetTransform();
   mStyleStack.SetCapacity(mStyleStack.Length() + 1);
   mStyleStack.AppendElement(CurrentState());
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::MozSave()
-{
-  Save();
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::Restore()
 {
   if (mStyleStack.Length() - 1 == 0)
     return;
 
   TransformWillUpdate();
 
@@ -1112,23 +1051,16 @@ CanvasRenderingContext2D::Restore()
     mTarget->PopClip();
   }
 
   mStyleStack.RemoveElementAt(mStyleStack.Length() - 1);
 
   mTarget->SetTransform(CurrentState().transform);
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::MozRestore()
-{
-  Restore();
-  return NS_OK;
-}
-
 //
 // transformations
 //
 
 void
 CanvasRenderingContext2D::Scale(double x, double y, ErrorResult& error)
 {
   if (!FloatValidate(x,y)) {
@@ -1140,24 +1072,16 @@ CanvasRenderingContext2D::Scale(double x
     error.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   Matrix newMatrix = mTarget->GetTransform();
   mTarget->SetTransform(newMatrix.Scale(x, y));
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::Scale(float x, float y)
-{
-  ErrorResult rv;
-  Scale((double)x, (double)y, rv);
-  return rv.ErrorCode();
-}
-
 void
 CanvasRenderingContext2D::Rotate(double angle, ErrorResult& error)
 {
   if (!FloatValidate(angle)) {
     return;
   }
 
   TransformWillUpdate();
@@ -1166,24 +1090,16 @@ CanvasRenderingContext2D::Rotate(double 
     return;
   }
 
 
   Matrix rotation = Matrix::Rotation(angle);
   mTarget->SetTransform(rotation * mTarget->GetTransform());
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::Rotate(float angle)
-{
-  ErrorResult rv;
-  Rotate((double)angle, rv);
-  return rv.ErrorCode();
-}
-
 void
 CanvasRenderingContext2D::Translate(double x, double y, ErrorResult& error)
 {
   if (!FloatValidate(x,y)) {
     return;
   }
 
   TransformWillUpdate();
@@ -1191,24 +1107,16 @@ CanvasRenderingContext2D::Translate(doub
     error.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   Matrix newMatrix = mTarget->GetTransform();
   mTarget->SetTransform(newMatrix.Translate(x, y));
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::Translate(float x, float y)
-{
-  ErrorResult rv;
-  Translate((double)x, (double)y, rv);
-  return rv.ErrorCode();
-}
-
 void
 CanvasRenderingContext2D::Transform(double m11, double m12, double m21,
                                     double m22, double dx, double dy,
                                     ErrorResult& error)
 {
   if (!FloatValidate(m11,m12,m21,m22,dx,dy)) {
     return;
   }
@@ -1218,25 +1126,16 @@ CanvasRenderingContext2D::Transform(doub
     error.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   Matrix matrix(m11, m12, m21, m22, dx, dy);
   mTarget->SetTransform(matrix * mTarget->GetTransform());
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::Transform(float m11, float m12, float m21, float m22, float dx, float dy)
-{
-  ErrorResult rv;
-  Transform((double)m11, (double)m12, (double)m21, (double)m22, (double)dx,
-            (double)dy, rv);
-  return rv.ErrorCode();
-}
-
 void
 CanvasRenderingContext2D::SetTransform(double m11, double m12,
                                        double m21, double m22,
                                        double dx, double dy,
                                        ErrorResult& error)
 {
   if (!FloatValidate(m11,m12,m21,m22,dx,dy)) {
     return;
@@ -1247,25 +1146,16 @@ CanvasRenderingContext2D::SetTransform(d
     error.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   Matrix matrix(m11, m12, m21, m22, dx, dy);
   mTarget->SetTransform(matrix);
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetTransform(float m11, float m12, float m21, float m22, float dx, float dy)
-{
-  ErrorResult rv;
-  SetTransform((double)m11, (double)m12, (double)m21, (double)m22, (double)dx,
-               (double)dy, rv);
-  return rv.ErrorCode();
-}
-
 JSObject*
 MatrixToJSObject(JSContext* cx, const Matrix& matrix, ErrorResult& error)
 {
   jsval elts[] = {
     DOUBLE_TO_JSVAL(matrix._11), DOUBLE_TO_JSVAL(matrix._12),
     DOUBLE_TO_JSVAL(matrix._21), DOUBLE_TO_JSVAL(matrix._22),
     DOUBLE_TO_JSVAL(matrix._31), DOUBLE_TO_JSVAL(matrix._32)
   };
@@ -1322,48 +1212,23 @@ CanvasRenderingContext2D::SetMozCurrentT
   }
 
   Matrix newCTM;
   if (ObjectToMatrix(cx, currentTransform, newCTM, error)) {
     mTarget->SetTransform(newCTM);
   }
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetMozCurrentTransform(JSContext* cx,
-                                                 const jsval& matrix)
-{
-  if (!matrix.isObject()) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  ErrorResult rv;
-  SetMozCurrentTransform(cx, matrix.toObject(), rv);
-  return rv.ErrorCode();
-}
-
 JSObject*
 CanvasRenderingContext2D::GetMozCurrentTransform(JSContext* cx,
                                                  ErrorResult& error) const
 {
   return MatrixToJSObject(cx, mTarget ? mTarget->GetTransform() : Matrix(), error);
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetMozCurrentTransform(JSContext* cx,
-                                                 jsval* matrix)
-{
-  ErrorResult rv;
-  JSObject* obj = GetMozCurrentTransform(cx, rv);
-  if (!rv.Failed()) {
-    *matrix = OBJECT_TO_JSVAL(obj);
-  }
-  return rv.ErrorCode();
-}
-
 void
 CanvasRenderingContext2D::SetMozCurrentTransformInverse(JSContext* cx,
                                                         JSObject& currentTransform,
                                                         ErrorResult& error)
 {
   EnsureTarget();
   if (!IsTargetValid()) {
     error.Throw(NS_ERROR_FAILURE);
@@ -1374,29 +1239,16 @@ CanvasRenderingContext2D::SetMozCurrentT
   if (ObjectToMatrix(cx, currentTransform, newCTMInverse, error)) {
     // XXX ERRMSG we need to report an error to developers here! (bug 329026)
     if (newCTMInverse.Invert()) {
       mTarget->SetTransform(newCTMInverse);
     }
   }
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetMozCurrentTransformInverse(JSContext* cx,
-                                                        const jsval& matrix)
-{
-  if (!matrix.isObject()) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  ErrorResult rv;
-  SetMozCurrentTransformInverse(cx, matrix.toObject(), rv);
-  return rv.ErrorCode();
-}
-
 JSObject*
 CanvasRenderingContext2D::GetMozCurrentTransformInverse(JSContext* cx,
                                                         ErrorResult& error) const
 {
   if (!mTarget) {
     return MatrixToJSObject(cx, Matrix(), error);
   }
 
@@ -1405,46 +1257,20 @@ CanvasRenderingContext2D::GetMozCurrentT
   if (!ctm.Invert()) {
     double NaN = JSVAL_TO_DOUBLE(JS_GetNaNValue(cx));
     ctm = Matrix(NaN, NaN, NaN, NaN, NaN, NaN);
   }
 
   return MatrixToJSObject(cx, ctm, error);
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetMozCurrentTransformInverse(JSContext* cx,
-                                                        jsval* matrix)
-{
-  ErrorResult rv;
-  JSObject* obj = GetMozCurrentTransformInverse(cx, rv);
-  if (!rv.Failed()) {
-    *matrix = OBJECT_TO_JSVAL(obj);
-  }
-  return rv.ErrorCode();
-}
-
 //
 // colors
 //
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetGlobalAlpha(float aGlobalAlpha)
-{
-  SetGlobalAlpha((double)aGlobalAlpha);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetGlobalAlpha(float *aGlobalAlpha)
-{
-  *aGlobalAlpha = GlobalAlpha();
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::SetStyleFromJSValue(JSContext* cx,
                                               JS::Value& value,
                                               Style whichStyle)
 {
   if (value.isString()) {
     nsDependentJSString strokeStyle;
     if (strokeStyle.init(cx, value.toString())) {
@@ -1475,257 +1301,88 @@ CanvasRenderingContext2D::SetStyleFromJS
     }
   }
 
   WarnAboutUnexpectedStyle(mCanvasElement);
 }
 
 static JS::Value
 WrapStyle(JSContext* cx, JSObject* obj,
-          nsIDOMCanvasRenderingContext2D::CanvasMultiGetterType type,
+          CanvasRenderingContext2D::CanvasMultiGetterType type,
           nsAString& str, nsISupports* supports, ErrorResult& error)
 {
   JS::Value v;
   bool ok;
   switch (type) {
-    case nsIDOMCanvasRenderingContext2D::CMG_STYLE_STRING:
+    case CanvasRenderingContext2D::CMG_STYLE_STRING:
     {
       ok = xpc::StringToJsval(cx, str, &v);
       break;
     }
-    case nsIDOMCanvasRenderingContext2D::CMG_STYLE_PATTERN:
-    case nsIDOMCanvasRenderingContext2D::CMG_STYLE_GRADIENT:
+    case CanvasRenderingContext2D::CMG_STYLE_PATTERN:
+    case CanvasRenderingContext2D::CMG_STYLE_GRADIENT:
     {
       ok = dom::WrapObject(cx, obj, supports, &v);
       break;
     }
     default:
       MOZ_NOT_REACHED("unexpected CanvasMultiGetterType");
   }
   if (!ok) {
     error.Throw(NS_ERROR_FAILURE);
   }
   return v;
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetStrokeStyle(nsIVariant *aValue)
-{
-  if (!aValue)
-      return NS_ERROR_FAILURE;
-
-  nsString str;
-
-  nsresult rv;
-  uint16_t vtype;
-  rv = aValue->GetDataType(&vtype);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (vtype == nsIDataType::VTYPE_INTERFACE ||
-      vtype == nsIDataType::VTYPE_INTERFACE_IS)
-  {
-    nsIID *iid;
-    nsCOMPtr<nsISupports> sup;
-    rv = aValue->GetAsInterface(&iid, getter_AddRefs(sup));
-    NS_ENSURE_SUCCESS(rv, rv);
-    if (iid) {
-      NS_Free(iid);
-    }
-
-    str.SetIsVoid(true);
-    return SetStrokeStyle_multi(str, sup);
-  }
-
-  rv = aValue->GetAsAString(str);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return SetStrokeStyle_multi(str, nullptr);
-}
 
 JS::Value
 CanvasRenderingContext2D::GetStrokeStyle(JSContext* cx,
                                          ErrorResult& error)
 {
   nsString str;
   CanvasMultiGetterType t;
   nsISupports* supports = GetStyleAsStringOrInterface(str, t, STYLE_STROKE);
   return WrapStyle(cx, GetWrapper(), t, str, supports, error);
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetStrokeStyle(nsIVariant **aResult)
-{
-  nsCOMPtr<nsIWritableVariant> wv = do_CreateInstance(NS_VARIANT_CONTRACTID);
-
-  nsCOMPtr<nsISupports> sup;
-  nsString str;
-  int32_t t;
-  nsresult rv = GetStrokeStyle_multi(str, getter_AddRefs(sup), &t);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (t == CMG_STYLE_STRING) {
-    rv = wv->SetAsAString(str);
-  } else if (t == CMG_STYLE_PATTERN) {
-    rv = wv->SetAsInterface(NS_GET_IID(nsIDOMCanvasPattern),
-                            sup);
-  } else if (t == CMG_STYLE_GRADIENT) {
-    rv = wv->SetAsInterface(NS_GET_IID(nsIDOMCanvasGradient),
-                            sup);
-  } else {
-    NS_ERROR("Unknown type from GetStroke/FillStyle_multi!");
-    return NS_ERROR_FAILURE;
-  }
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_IF_ADDREF(*aResult = wv.get());
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetFillStyle(nsIVariant *aValue)
-{
-  if (!aValue) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsString str;
-  nsresult rv;
-  uint16_t vtype;
-  rv = aValue->GetDataType(&vtype);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (vtype == nsIDataType::VTYPE_INTERFACE ||
-      vtype == nsIDataType::VTYPE_INTERFACE_IS)
-  {
-    nsIID *iid;
-    nsCOMPtr<nsISupports> sup;
-    rv = aValue->GetAsInterface(&iid, getter_AddRefs(sup));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    str.SetIsVoid(true);
-    return SetFillStyle_multi(str, sup);
-  }
-
-  rv = aValue->GetAsAString(str);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return SetFillStyle_multi(str, nullptr);
-}
-
 JS::Value
 CanvasRenderingContext2D::GetFillStyle(JSContext* cx,
                                        ErrorResult& error)
 {
   nsString str;
   CanvasMultiGetterType t;
   nsISupports* supports = GetStyleAsStringOrInterface(str, t, STYLE_FILL);
   return WrapStyle(cx, GetWrapper(), t, str, supports, error);
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetFillStyle(nsIVariant **aResult)
-{
-  nsCOMPtr<nsIWritableVariant> wv = do_CreateInstance(NS_VARIANT_CONTRACTID);
-
-  nsCOMPtr<nsISupports> sup;
-  nsString str;
-  int32_t t;
-  nsresult rv = GetFillStyle_multi(str, getter_AddRefs(sup), &t);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (t == CMG_STYLE_STRING) {
-    rv = wv->SetAsAString(str);
-  } else if (t == CMG_STYLE_PATTERN) {
-    rv = wv->SetAsInterface(NS_GET_IID(nsIDOMCanvasPattern),
-                            sup);
-  } else if (t == CMG_STYLE_GRADIENT) {
-    rv = wv->SetAsInterface(NS_GET_IID(nsIDOMCanvasGradient),
-                            sup);
-  } else {
-    NS_ERROR("Unknown type from GetStroke/FillStyle_multi!");
-    return NS_ERROR_FAILURE;
-  }
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_IF_ADDREF(*aResult = wv.get());
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::SetFillRule(const nsAString& aString)
 {
   FillRule rule;
 
   if (aString.EqualsLiteral("evenodd"))
     rule = FILL_EVEN_ODD;
   else if (aString.EqualsLiteral("nonzero"))
     rule = FILL_WINDING;
   else
     return;
 
   CurrentState().fillRule = rule;
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetMozFillRule(const nsAString& aString)
-{
-  SetFillRule(aString);
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::GetFillRule(nsAString& aString)
 {
-    switch (CurrentState().fillRule) {
-    case FILL_WINDING:
-      aString.AssignLiteral("nonzero"); break;
-    case FILL_EVEN_ODD:
-      aString.AssignLiteral("evenodd"); break;
-    }
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetMozFillRule(nsAString& aString)
-{
-  GetFillRule(aString);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetStrokeStyle_multi(const nsAString& aStr, nsISupports *aInterface)
-{
-  SetStyleFromStringOrInterface(aStr, aInterface, STYLE_STROKE);
-  return NS_OK;
+  switch (CurrentState().fillRule) {
+  case FILL_WINDING:
+    aString.AssignLiteral("nonzero"); break;
+  case FILL_EVEN_ODD:
+    aString.AssignLiteral("evenodd"); break;
+  }
 }
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetStrokeStyle_multi(nsAString& aStr, nsISupports **aInterface, int32_t *aType)
-{
-  CanvasMultiGetterType type;
-  NS_IF_ADDREF(*aInterface = GetStyleAsStringOrInterface(aStr, type, STYLE_STROKE));
-  *aType = type;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetFillStyle_multi(const nsAString& aStr, nsISupports *aInterface)
-{
-  SetStyleFromStringOrInterface(aStr, aInterface, STYLE_FILL);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetFillStyle_multi(nsAString& aStr, nsISupports **aInterface, int32_t *aType)
-{
-  CanvasMultiGetterType type;
-  NS_IF_ADDREF(*aInterface = GetStyleAsStringOrInterface(aStr, type, STYLE_FILL));
-  *aType = type;
-  return NS_OK;
-}
-
 //
 // gradients and patterns
 //
 already_AddRefed<nsIDOMCanvasGradient>
 CanvasRenderingContext2D::CreateLinearGradient(double x0, double y0, double x1, double y1,
                                                ErrorResult& aError)
 {
   if (!FloatValidate(x0,y0,x1,y1)) {
@@ -1734,25 +1391,16 @@ CanvasRenderingContext2D::CreateLinearGr
   }
 
   nsRefPtr<nsIDOMCanvasGradient> grad =
     new CanvasLinearGradient(Point(x0, y0), Point(x1, y1));
 
   return grad.forget();
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::CreateLinearGradient(float x0, float y0, float x1, float y1,
-                                               nsIDOMCanvasGradient **_retval)
-{
-  ErrorResult rv;
-  *_retval = CreateLinearGradient(x0, y0, x1, y1, rv).get();
-  return rv.ErrorCode();
-}
-
 already_AddRefed<nsIDOMCanvasGradient>
 CanvasRenderingContext2D::CreateRadialGradient(double x0, double y0, double r0,
                                                double x1, double y1, double r1,
                                                ErrorResult& aError)
 {
   if (!FloatValidate(x0,y0,r0,x1,y1,r1)) {
     aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
     return nullptr;
@@ -1764,26 +1412,16 @@ CanvasRenderingContext2D::CreateRadialGr
   }
 
   nsRefPtr<nsIDOMCanvasGradient> grad =
     new CanvasRadialGradient(Point(x0, y0), r0, Point(x1, y1), r1);
 
   return grad.forget();
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::CreateRadialGradient(float x0, float y0, float r0,
-                                               float x1, float y1, float r1,
-                                               nsIDOMCanvasGradient **_retval)
-{
-  ErrorResult rv;
-  *_retval = CreateRadialGradient(x0, y0, r0, x1, y1, r1, rv).get();
-  return rv.ErrorCode();
-}
-
 already_AddRefed<nsIDOMCanvasPattern>
 CanvasRenderingContext2D::CreatePattern(const HTMLImageOrCanvasOrVideoElement& element,
                                         const nsAString& repeat,
                                         ErrorResult& error)
 {
   CanvasPattern::RepeatMode repeatMode =
     CanvasPattern::NOREPEAT;
 
@@ -1850,101 +1488,30 @@ CanvasRenderingContext2D::CreatePattern(
 
   nsRefPtr<CanvasPattern> pat =
     new CanvasPattern(srcSurf, repeatMode, res.mPrincipal,
                              res.mIsWriteOnly, res.mCORSUsed);
 
   return pat.forget();
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::CreatePattern(nsIDOMHTMLElement *image,
-                                        const nsAString& repeat,
-                                        nsIDOMCanvasPattern **_retval)
-{
-  HTMLImageOrCanvasOrVideoElement element;
-  if (!ToHTMLImageOrCanvasOrVideoElement(image, element)) {
-    return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
-  }
-
-  ErrorResult rv;
-  *_retval = CreatePattern(element, repeat, rv).get();
-  return rv.ErrorCode();
-}
-
 //
 // shadows
 //
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetShadowOffsetX(float x)
-{
-  SetShadowOffsetX((double)x);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetShadowOffsetX(float *x)
-{
-  *x = static_cast<float>(ShadowOffsetX());
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetShadowOffsetY(float y)
-{
-  SetShadowOffsetY((double)y);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetShadowOffsetY(float *y)
-{
-  *y = static_cast<float>(ShadowOffsetY());
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetShadowBlur(float blur)
-{
-  SetShadowBlur((double)blur);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetShadowBlur(float *blur)
-{
-  *blur = ShadowBlur();
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::SetShadowColor(const nsAString& shadowColor)
 {
   nscolor color;
   if (!ParseColor(shadowColor, &color)) {
     return;
   }
 
   CurrentState().shadowColor = color;
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetMozShadowColor(const nsAString& colorstr)
-{
-  SetShadowColor(colorstr);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetMozShadowColor(nsAString& color)
-{
-  GetShadowColor(color);
-  return NS_OK;
-}
-
 //
 // rects
 //
 
 void
 CanvasRenderingContext2D::ClearRect(double x, double y, double w,
                                     double h)
 {
@@ -1952,23 +1519,16 @@ CanvasRenderingContext2D::ClearRect(doub
     return;
   }
 
   mTarget->ClearRect(mgfx::Rect(x, y, w, h));
 
   RedrawUser(gfxRect(x, y, w, h));
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::ClearRect(float x, float y, float w, float h)
-{
-  ClearRect((double)x, (double)y, (double)w, (double)h);
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::FillRect(double x, double y, double w,
                                    double h)
 {
   if (!FloatValidate(x,y,w,h)) {
     return;
   }
 
@@ -2031,23 +1591,16 @@ CanvasRenderingContext2D::FillRect(doubl
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
     FillRect(mgfx::Rect(x, y, w, h),
              CanvasGeneralPattern().ForStyle(this, STYLE_FILL, mTarget),
              DrawOptions(state.globalAlpha, UsedOperation()));
 
   RedrawUser(gfxRect(x, y, w, h));
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::FillRect(float x, float y, float w, float h)
-{
-  FillRect((double)x, (double)y, (double)w, (double)h);
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::StrokeRect(double x, double y, double w,
                                      double h)
 {
   if (!FloatValidate(x,y,w,h)) {
     return;
   }
 
@@ -2112,50 +1665,29 @@ CanvasRenderingContext2D::StrokeRect(dou
                               state.dash.Length(),
                               state.dash.Elements(),
                               state.dashOffset),
                 DrawOptions(state.globalAlpha, UsedOperation()));
 
   Redraw();
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::StrokeRect(float x, float y, float w, float h)
-{
-  StrokeRect((double)x, (double)y, (double)w, (double)h);
-  return NS_OK;
-}
-
 //
 // path bits
 //
 
 void
 CanvasRenderingContext2D::BeginPath()
 {
   mPath = nullptr;
   mPathBuilder = nullptr;
   mDSPathBuilder = nullptr;
   mPathTransformWillUpdate = false;
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::MozBeginPath()
-{
-  BeginPath();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::MozClosePath()
-{
-  ClosePath();
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::Fill()
 {
   EnsureUserSpacePath();
 
   if (!mPath) {
     return;
   }
@@ -2168,23 +1700,16 @@ CanvasRenderingContext2D::Fill()
 
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
     Fill(mPath, CanvasGeneralPattern().ForStyle(this, STYLE_FILL, mTarget),
          DrawOptions(CurrentState().globalAlpha, UsedOperation()));
 
   Redraw();
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::MozFill()
-{
-  Fill();
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::Stroke()
 {
   EnsureUserSpacePath();
 
   if (!mPath) {
     return;
   }
@@ -2204,75 +1729,29 @@ CanvasRenderingContext2D::Stroke()
 
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
     Stroke(mPath, CanvasGeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
            strokeOptions, DrawOptions(state.globalAlpha, UsedOperation()));
 
   Redraw();
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::MozStroke()
-{
-  Stroke();
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::Clip()
 {
   EnsureUserSpacePath();
 
   if (!mPath) {
     return;
   }
 
   mTarget->PushClip(mPath);
   CurrentState().clipsPushed.push_back(mPath);
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::MozClip()
-{
-  Clip();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::MoveTo(float x, float y)
-{
-  MoveTo((double)x, (double)y);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::LineTo(float x, float y)
-{
-  LineTo((double)x, (double)y);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::QuadraticCurveTo(float cpx, float cpy, float x,
-                                           float y)
-{
-  QuadraticCurveTo((double)cpx, (double)cpy, (double)x, (double)y);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::BezierCurveTo(float cp1x, float cp1y,
-                                        float cp2x, float cp2y,
-                                        float x, float y)
-{
-  BezierCurveTo((double)cp1x, (double)cp1y, (double)cp2x, (double)cp2y,
-                (double)x, (double)y);
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::ArcTo(double x1, double y1, double x2,
                                 double y2, double radius,
                                 ErrorResult& error)
 {
   if (!FloatValidate(x1, y1, x2, y2, radius)) {
     return;
   }
@@ -2342,25 +1821,17 @@ CanvasRenderingContext2D::ArcTo(double x
   cx = x3 + any*radius*(anticlockwise ? 1 : -1);
   cy = y3 - anx*radius*(anticlockwise ? 1 : -1);
   angle0 = atan2((y3-cy), (x3-cx));
   angle1 = atan2((y4-cy), (x4-cx));
 
 
   LineTo(x3, y3);
 
-  Arc(cx, cy, radius, angle0, angle1, anticlockwise);
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::ArcTo(float x1, float y1, float x2, float y2, float radius)
-{
-  ErrorResult rv;
-  ArcTo(x1, y1, x2, y2, radius, rv);
-  return rv.ErrorCode();
+  Arc(cx, cy, radius, angle0, angle1, anticlockwise, error);
 }
 
 void
 CanvasRenderingContext2D::Arc(double x, double y, double r,
                               double startAngle, double endAngle,
                               bool anticlockwise, ErrorResult& error)
 {
   if (!FloatValidate(x, y, r, startAngle, endAngle)) {
@@ -2372,27 +1843,16 @@ CanvasRenderingContext2D::Arc(double x, 
     return;
   }
 
   EnsureWritablePath();
 
   ArcToBezier(this, Point(x, y), r, startAngle, endAngle, anticlockwise);
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::Arc(float x, float y,
-                              float r,
-                              float startAngle, float endAngle,
-                              bool ccw)
-{
-  ErrorResult rv;
-  Arc(x, y, r, startAngle, endAngle, ccw, rv);
-  return rv.ErrorCode();
-}
-
 void
 CanvasRenderingContext2D::Rect(double x, double y, double w, double h)
 {
   if (!FloatValidate(x, y, w, h)) {
     return;
   }
 
   EnsureWritablePath();
@@ -2407,23 +1867,16 @@ CanvasRenderingContext2D::Rect(double x,
     mDSPathBuilder->MoveTo(mTarget->GetTransform() * Point(x, y));
     mDSPathBuilder->LineTo(mTarget->GetTransform() * Point(x + w, y));
     mDSPathBuilder->LineTo(mTarget->GetTransform() * Point(x + w, y + h));
     mDSPathBuilder->LineTo(mTarget->GetTransform() * Point(x, y + h));
     mDSPathBuilder->Close();
   }
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::Rect(float x, float y, float w, float h)
-{
-  Rect((double)x, (double)y, (double)w, (double)h);
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::EnsureWritablePath()
 {
   if (mDSPathBuilder) {
     return;
   }
 
   FillRule fillRule = CurrentState().fillRule;
@@ -2709,53 +2162,31 @@ CanvasRenderingContext2D::SetFont(const 
 
   // The font getter is required to be reserialized based on what we
   // parsed (including having line-height removed).  (Older drafts of
   // the spec required font sizes be converted to pixels, but that no
   // longer seems to be required.)
   declaration->GetValue(eCSSProperty_font, CurrentState().font);
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetMozFont(const nsAString& font)
-{
-  ErrorResult rv;
-  SetFont(font, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetMozFont(nsAString& font)
-{
-  font = GetFont();
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::SetTextAlign(const nsAString& ta)
 {
   if (ta.EqualsLiteral("start"))
     CurrentState().textAlign = TEXT_ALIGN_START;
   else if (ta.EqualsLiteral("end"))
     CurrentState().textAlign = TEXT_ALIGN_END;
   else if (ta.EqualsLiteral("left"))
     CurrentState().textAlign = TEXT_ALIGN_LEFT;
   else if (ta.EqualsLiteral("right"))
     CurrentState().textAlign = TEXT_ALIGN_RIGHT;
   else if (ta.EqualsLiteral("center"))
     CurrentState().textAlign = TEXT_ALIGN_CENTER;
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetMozTextAlign(const nsAString& ta)
-{
-  SetTextAlign(ta);
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::GetTextAlign(nsAString& ta)
 {
   switch (CurrentState().textAlign)
   {
   case TEXT_ALIGN_START:
     ta.AssignLiteral("start");
     break;
@@ -2769,23 +2200,16 @@ CanvasRenderingContext2D::GetTextAlign(n
     ta.AssignLiteral("right");
     break;
   case TEXT_ALIGN_CENTER:
     ta.AssignLiteral("center");
     break;
   }
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetMozTextAlign(nsAString& ta)
-{
-  GetTextAlign(ta);
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::SetTextBaseline(const nsAString& tb)
 {
   if (tb.EqualsLiteral("top"))
     CurrentState().textBaseline = TEXT_BASELINE_TOP;
   else if (tb.EqualsLiteral("hanging"))
     CurrentState().textBaseline = TEXT_BASELINE_HANGING;
   else if (tb.EqualsLiteral("middle"))
@@ -2793,23 +2217,16 @@ CanvasRenderingContext2D::SetTextBaselin
   else if (tb.EqualsLiteral("alphabetic"))
     CurrentState().textBaseline = TEXT_BASELINE_ALPHABETIC;
   else if (tb.EqualsLiteral("ideographic"))
     CurrentState().textBaseline = TEXT_BASELINE_IDEOGRAPHIC;
   else if (tb.EqualsLiteral("bottom"))
     CurrentState().textBaseline = TEXT_BASELINE_BOTTOM;
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetMozTextBaseline(const nsAString& tb)
-{
-  SetTextBaseline(tb);
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::GetTextBaseline(nsAString& tb)
 {
   switch (CurrentState().textBaseline)
   {
   case TEXT_BASELINE_TOP:
     tb.AssignLiteral("top");
     break;
@@ -2826,23 +2243,16 @@ CanvasRenderingContext2D::GetTextBaselin
     tb.AssignLiteral("ideographic");
     break;
   case TEXT_BASELINE_BOTTOM:
     tb.AssignLiteral("bottom");
     break;
   }
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetMozTextBaseline(nsAString& tb)
-{
-  GetTextBaseline(tb);
-  return NS_OK;
-}
-
 /*
  * Helper function that replaces the whitespace characters in a string
  * with U+0020 SPACE. The whitespace characters are defined as U+0020 SPACE,
  * U+0009 CHARACTER TABULATION (tab), U+000A LINE FEED (LF), U+000B LINE
  * TABULATION, U+000C FORM FEED (FF), and U+000D CARRIAGE RETURN (CR).
  * @param str The string whose whitespace characters to replace.
  */
 static inline void
@@ -2855,72 +2265,41 @@ void
 CanvasRenderingContext2D::FillText(const nsAString& text, double x,
                                    double y,
                                    const Optional<double>& maxWidth,
                                    ErrorResult& error)
 {
   error = DrawOrMeasureText(text, x, y, maxWidth, TEXT_DRAW_OPERATION_FILL, nullptr);
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::FillText(const nsAString& text, float x, float y, float maxWidth)
-{
-  ErrorResult rv;
-  Optional<double> optionalMaxWidth;
-  optionalMaxWidth.Construct();
-  optionalMaxWidth.Value() = maxWidth;
-  FillText(text, x, y, optionalMaxWidth, rv);
-  return rv.ErrorCode();
-}
-
 void
 CanvasRenderingContext2D::StrokeText(const nsAString& text, double x,
                                      double y,
                                      const Optional<double>& maxWidth,
                                      ErrorResult& error)
 {
   error = DrawOrMeasureText(text, x, y, maxWidth, TEXT_DRAW_OPERATION_STROKE, nullptr);
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::StrokeText(const nsAString& text, float x, float y, float maxWidth)
-{
-  ErrorResult rv;
-  Optional<double> optionalMaxWidth;
-  optionalMaxWidth.Construct();
-  optionalMaxWidth.Value() = maxWidth;
-  StrokeText(text, x, y, optionalMaxWidth, rv);
-  return rv.ErrorCode();
-}
-
 already_AddRefed<nsIDOMTextMetrics>
 CanvasRenderingContext2D::MeasureText(const nsAString& rawText,
                                       ErrorResult& error)
 {
   float width;
   Optional<double> maxWidth;
   error = DrawOrMeasureText(rawText, 0, 0, maxWidth, TEXT_DRAW_OPERATION_MEASURE, &width);
   if (error.Failed()) {
     return NULL;
   }
 
   nsRefPtr<nsIDOMTextMetrics> textMetrics = new TextMetrics(width);
 
   return textMetrics.forget();
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::MeasureText(const nsAString& rawText,
-                                      nsIDOMTextMetrics** _retval)
-{
-  ErrorResult rv;
-  *_retval = MeasureText(rawText, rv).get();
-  return rv.ErrorCode();
-}
-
 /**
  * Used for nsBidiPresUtils::ProcessText
  */
 struct NS_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcessor
 {
   typedef CanvasRenderingContext2D::ContextState ContextState;
 
   virtual void SetText(const PRUnichar* text, int32_t length, nsBidiDirection direction)
@@ -3381,75 +2760,45 @@ CanvasRenderingContext2D::DrawOrMeasureT
     RedrawUser(boundingBox);
     return NS_OK;
   }
 
   Redraw();
   return NS_OK;
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetTextStyle(const nsAString& textStyle)
-{
-  ErrorResult rv;
-  SetMozTextStyle(textStyle, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetTextStyle(nsAString& textStyle)
-{
-  GetMozTextStyle(textStyle);
-  return NS_OK;
-}
-
 gfxFontGroup *CanvasRenderingContext2D::GetCurrentFontStyle()
 {
   // use lazy initilization for the font group since it's rather expensive
   if (!CurrentState().fontGroup) {
-    nsresult rv = SetMozFont(kDefaultFontStyle);
-    if (NS_FAILED(rv)) {
+    ErrorResult err;
+    SetFont(kDefaultFontStyle, err);
+    if (err.Failed()) {
       gfxFontStyle style;
       style.size = kDefaultFontSize;
       CurrentState().fontGroup =
         gfxPlatform::GetPlatform()->CreateFontGroup(kDefaultFontName,
                                                     &style,
                                                     nullptr);
       if (CurrentState().fontGroup) {
         CurrentState().font = kDefaultFontStyle;
-        rv = NS_OK;
       } else {
-        rv = NS_ERROR_OUT_OF_MEMORY;
+        NS_ERROR("Default canvas font is invalid");
       }
     }
 
-    NS_ASSERTION(NS_SUCCEEDED(rv), "Default canvas font is invalid");
   }
 
   return CurrentState().fontGroup;
 }
 
 //
 // line caps/joins
 //
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetLineWidth(float width)
-{
-  SetLineWidth((double)width);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetLineWidth(float *width)
-{
-  *width = LineWidth();
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::SetLineCap(const nsAString& capstyle)
 {
   CapStyle cap;
 
   if (capstyle.EqualsLiteral("butt")) {
     cap = CAP_BUTT;
   } else if (capstyle.EqualsLiteral("round")) {
@@ -3459,46 +2808,32 @@ CanvasRenderingContext2D::SetLineCap(con
   } else {
     // XXX ERRMSG we need to report an error to developers here! (bug 329026)
     return;
   }
 
   CurrentState().lineCap = cap;
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetMozLineCap(const nsAString& capstyle)
-{
-  SetLineCap(capstyle);
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::GetLineCap(nsAString& capstyle)
 {
   switch (CurrentState().lineCap) {
   case CAP_BUTT:
     capstyle.AssignLiteral("butt");
     break;
   case CAP_ROUND:
     capstyle.AssignLiteral("round");
     break;
   case CAP_SQUARE:
     capstyle.AssignLiteral("square");
     break;
   }
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetMozLineCap(nsAString& capstyle)
-{
-  GetLineCap(capstyle);
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::SetLineJoin(const nsAString& joinstyle)
 {
   JoinStyle j;
 
   if (joinstyle.EqualsLiteral("round")) {
     j = JOIN_ROUND;
   } else if (joinstyle.EqualsLiteral("bevel")) {
@@ -3508,23 +2843,16 @@ CanvasRenderingContext2D::SetLineJoin(co
   } else {
     // XXX ERRMSG we need to report an error to developers here! (bug 329026)
     return;
   }
 
   CurrentState().lineJoin = j;
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetMozLineJoin(const nsAString& joinstyle)
-{
-  SetLineJoin(joinstyle);
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::GetLineJoin(nsAString& joinstyle, ErrorResult& error)
 {
   switch (CurrentState().lineJoin) {
   case JOIN_ROUND:
     joinstyle.AssignLiteral("round");
     break;
   case JOIN_BEVEL:
@@ -3533,100 +2861,51 @@ CanvasRenderingContext2D::GetLineJoin(ns
   case JOIN_MITER_OR_BEVEL:
     joinstyle.AssignLiteral("miter");
     break;
   default:
     error.Throw(NS_ERROR_FAILURE);
   }
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetMozLineJoin(nsAString& joinstyle)
-{
-  ErrorResult rv;
-  nsString linejoin;
-  GetLineJoin(linejoin, rv);
-  if (!rv.Failed()) {
-    joinstyle = linejoin;
-  }
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetMiterLimit(float miter)
-{
-  SetMiterLimit((double)miter);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetMiterLimit(float *miter)
-{
-  *miter = MiterLimit();
-  return NS_OK;
-}
-
 void
 CanvasRenderingContext2D::SetMozDash(JSContext* cx,
                                      const JS::Value& mozDash,
                                      ErrorResult& error)
 {
   FallibleTArray<Float> dash;
   error = JSValToDashArray(cx, mozDash, dash);
   if (!error.Failed()) {
     ContextState& state = CurrentState();
     state.dash = dash;
     if (state.dash.IsEmpty()) {
       state.dashOffset = 0;
     }
   }
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetMozDash(JSContext *cx, const jsval& patternArray)
-{
-  ErrorResult rv;
-  SetMozDash(cx, patternArray, rv);
-  return rv.ErrorCode();
-}
-
 JS::Value
 CanvasRenderingContext2D::GetMozDash(JSContext* cx, ErrorResult& error)
 {
   JS::Value mozDash;
   error = DashArrayToJSVal(CurrentState().dash, cx, &mozDash);
   return mozDash;
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetMozDash(JSContext* cx, jsval* dashArray)
-{
-  ErrorResult rv;
-  *dashArray = GetMozDash(cx, rv);
-  return rv.ErrorCode();
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetMozDashOffset(float offset)
+void
+CanvasRenderingContext2D::SetMozDashOffset(double mozDashOffset)
 {
-  if (!FloatValidate(offset)) {
-    return NS_ERROR_ILLEGAL_VALUE;
-  }
-  ContextState& state = CurrentState();
-  if (!state.dash.IsEmpty()) {
-    state.dashOffset = offset;
+  if (!FloatValidate(mozDashOffset)) {
+    return;
   }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetMozDashOffset(float* offset)
-{
-  *offset = MozDashOffset();
-  return NS_OK;
+
+  ContextState& state = CurrentState();
+  if (!state.dash.IsEmpty()) {
+    state.dashOffset = mozDashOffset;
+  }
 }
 
 bool
 CanvasRenderingContext2D::IsPointInPath(double x, double y)
 {
   if (!FloatValidate(x,y)) {
     return false;
   }
@@ -3636,23 +2915,16 @@ CanvasRenderingContext2D::IsPointInPath(
     return false;
   }
   if (mPathTransformWillUpdate) {
     return mPath->ContainsPoint(Point(x, y), mPathToDS);
   }
   return mPath->ContainsPoint(Point(x, y), mTarget->GetTransform());
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::IsPointInPath(float x, float y, bool *retVal)
-{
-  *retVal = IsPointInPath(x, y);
-  return NS_OK;
-}
-
 bool
 CanvasRenderingContext2D::MozIsPointInStroke(double x, double y)
 {
   if (!FloatValidate(x,y)) {
     return false;
   }
 
   EnsureUserSpacePath(false);
@@ -3671,23 +2943,16 @@ CanvasRenderingContext2D::MozIsPointInSt
                               state.dashOffset);
 
   if (mPathTransformWillUpdate) {
     return mPath->StrokeContainsPoint(strokeOptions, Point(x, y), mPathToDS);
   }
   return mPath->StrokeContainsPoint(strokeOptions, Point(x, y), mTarget->GetTransform());
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::MozIsPointInStroke(float x, float y, bool *retVal)
-{
-  *retVal = MozIsPointInStroke(x, y);
-  return NS_OK;
-}
-
 //
 // image
 //
 
 // drawImage(in HTMLImageElement image, in float dx, in float dy);
 //   -- render image from 0,0 at dx,dy top-left coords
 // drawImage(in HTMLImageElement image, in float dx, in float dy, in float sw, in float sh);
 //   -- render image from 0,0 at dx,dy top-left coords clipping it to sw,sh
@@ -3846,51 +3111,16 @@ CanvasRenderingContext2D::DrawImage(cons
                 mgfx::Rect(dx, dy, dw, dh),
                 mgfx::Rect(sx, sy, sw, sh),
                 DrawSurfaceOptions(filter),
                 DrawOptions(CurrentState().globalAlpha, UsedOperation()));
 
   RedrawUser(gfxRect(dx, dy, dw, dh));
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1,
-                                    float a2, float a3, float a4, float a5,
-                                    float a6, float a7, float a8,
-                                    uint8_t optional_argc)
-{
-  if (!(optional_argc == 0 || optional_argc == 2 || optional_argc == 6)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  HTMLImageOrCanvasOrVideoElement element;
-  if (!ToHTMLImageOrCanvasOrVideoElement(imgElt, element)) {
-    return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
-  }
-
-  ErrorResult rv;
-  if (optional_argc == 0) {
-    if (!FloatValidate(a1, a2)) {
-      return NS_OK;
-    }
-    DrawImage(element, 0, 0, 0, 0, a1, a2, 0, 0, 0, rv);
-  } else if (optional_argc == 2) {
-    if (!FloatValidate(a1, a2, a3, a4)) {
-      return NS_OK;
-    }
-    DrawImage(element, 0, 0, 0, 0, a1, a2, a3, a4, 2, rv);
-  } else if (optional_argc == 6) {
-    if (!FloatValidate(a1, a2, a3, a4) || !FloatValidate(a5, a6, a7, a8)) {
-      return NS_OK;
-    }
-    DrawImage(element, a1, a2, a3, a4, a5, a6, a7, a8, 6, rv);
-  }
-  return rv.ErrorCode();
-}
-
 void
 CanvasRenderingContext2D::SetGlobalCompositeOperation(const nsAString& op,
                                                       ErrorResult& error)
 {
   CompositionOp comp_op;
 
 #define CANVAS_OP_TO_GFX_OP(cvsop, op2d) \
   if (op.EqualsLiteral(cvsop))   \
@@ -3909,24 +3139,16 @@ CanvasRenderingContext2D::SetGlobalCompo
   else CANVAS_OP_TO_GFX_OP("xor", XOR)
   // XXX ERRMSG we need to report an error to developers here! (bug 329026)
   else return;
 
 #undef CANVAS_OP_TO_GFX_OP
   CurrentState().op = comp_op;
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetGlobalCompositeOperation(const nsAString& op)
-{
-  ErrorResult rv;
-  SetGlobalCompositeOperation(op, rv);
-  return rv.ErrorCode();
-}
-
 void
 CanvasRenderingContext2D::GetGlobalCompositeOperation(nsAString& op,
                                                       ErrorResult& error)
 {
   CompositionOp comp_op = CurrentState().op;
 
 #define CANVAS_OP_TO_GFX_OP(cvsop, op2d) \
   if (comp_op == OP_##op2d) \
@@ -3945,28 +3167,16 @@ CanvasRenderingContext2D::GetGlobalCompo
   else CANVAS_OP_TO_GFX_OP("xor", XOR)
   else {
     error.Throw(NS_ERROR_FAILURE);
   }
 
 #undef CANVAS_OP_TO_GFX_OP
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetGlobalCompositeOperation(nsAString& op)
-{
-  nsString globalCompositeOperation;
-  ErrorResult rv;
-  GetGlobalCompositeOperation(globalCompositeOperation, rv);
-  if (!rv.Failed()) {
-    op = globalCompositeOperation;
-  }
-  return rv.ErrorCode();
-}
-
 void
 CanvasRenderingContext2D::DrawWindow(nsIDOMWindow* window, double x,
                                      double y, double w, double h,
                                      const nsAString& bgColor,
                                      uint32_t flags, ErrorResult& error)
 {
   // protect against too-large surfaces that will cause allocation
   // or overflow issues
@@ -4052,29 +3262,16 @@ CanvasRenderingContext2D::DrawWindow(nsI
   mTarget->SetTransform(matrix);
 
   // note that x and y are coordinates in the document that
   // we're drawing; x and y are drawn to 0,0 in current user
   // space.
   RedrawUser(gfxRect(0, 0, w, h));
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, float aX, float aY,
-                                     float aW, float aH,
-                                     const nsAString& aBGColor,
-                                     uint32_t flags)
-{
-  NS_ENSURE_ARG(aWindow);
-
-  ErrorResult rv;
-  DrawWindow(aWindow, aX, aY, aW, aH, aBGColor, flags, rv);
-  return rv.ErrorCode();
-}
-
 void
 CanvasRenderingContext2D::AsyncDrawXULElement(nsIDOMXULElement* elem,
                                               double x, double y,
                                               double w, double h,
                                               const nsAString& bgColor,
                                               uint32_t flags,
                                               ErrorResult& error)
 {
@@ -4151,30 +3348,16 @@ CanvasRenderingContext2D::AsyncDrawXULEl
     DocumentRendererParent *docrender =
       static_cast<DocumentRendererParent *>(pdocrender);
 
     docrender->SetCanvasContext(this, mThebes);
   }
 #endif
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::AsyncDrawXULElement(nsIDOMXULElement* aElem,
-                                              float aX, float aY,
-                                              float aW, float aH,
-                                              const nsAString& aBGColor,
-                                              uint32_t flags)
-{
-  NS_ENSURE_ARG(aElem);
-
-  ErrorResult rv;
-  AsyncDrawXULElement(aElem, aX, aY, aW, aH, aBGColor, flags, rv);
-  return rv.ErrorCode();
-}
-
 //
 // device pixel getting/setting
 //
 
 void
 CanvasRenderingContext2D::EnsureUnpremultiplyTable() {
   if (sUnpremultiplyTable)
     return;
@@ -4273,27 +3456,16 @@ CanvasRenderingContext2D::GetImageData(J
     return NULL;
   }
   MOZ_ASSERT(array);
 
   nsRefPtr<ImageData> imageData = new ImageData(w, h, *array);
   return imageData.forget();
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetImageData(double aSx, double aSy,
-                                       double aSw, double aSh,
-                                       JSContext* aCx,
-                                       nsISupports** aRetval)
-{
-  ErrorResult rv;
-  *aRetval = GetImageData(aCx, aSx, aSy, aSw, aSh, rv).get();
-  return rv.ErrorCode();
-}
-
 nsresult
 CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
                                             int32_t aX,
                                             int32_t aY,
                                             uint32_t aWidth,
                                             uint32_t aHeight,
                                             JSObject** aRetval)
 {
@@ -4461,27 +3633,18 @@ CanvasRenderingContext2D::PutImageData(J
                                 JS_DoubleToInt32(dirtyX),
                                 JS_DoubleToInt32(dirtyY),
                                 JS_DoubleToInt32(dirtyWidth),
                                 JS_DoubleToInt32(dirtyHeight));
 }
 
 // void putImageData (in ImageData d, in float x, in float y);
 // void putImageData (in ImageData d, in double x, in double y, in double dirtyX, in double dirtyY, in double dirtyWidth, in double dirtyHeight);
-NS_IMETHODIMP
-CanvasRenderingContext2D::PutImageData(const JS::Value&, double, double,
-                                       double, double, double, double,
-                                       JSContext*, uint8_t)
-{
-  /* Should never be called -- the new binding code handles it, and
-     C++ callers should call PutImageData_explicit */
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
+
+nsresult
 CanvasRenderingContext2D::PutImageData_explicit(int32_t x, int32_t y, uint32_t w, uint32_t h,
                                                 unsigned char *aData, uint32_t aDataLen,
                                                 bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY,
                                                 int32_t dirtyWidth, int32_t dirtyHeight)
 {
   if (w == 0 || h == 0) {
     return NS_ERROR_DOM_SYNTAX_ERR;
   }
@@ -4666,41 +3829,16 @@ already_AddRefed<ImageData>
 CanvasRenderingContext2D::CreateImageData(JSContext* cx,
                                           ImageData& imagedata,
                                           ErrorResult& error)
 {
   return mozilla::dom::CreateImageData(cx, this, imagedata.Width(),
                                        imagedata.Height(), error);
 }
 
-NS_IMETHODIMP
-CanvasRenderingContext2D::CreateImageData(const JS::Value &arg1,
-                                          const JS::Value &arg2,
-                                          JSContext* cx,
-                                          uint8_t optional_argc,
-                                          nsISupports** retval)
-{
-  /* Should never be called; handled entirely in new bindings */
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::GetMozImageSmoothingEnabled(bool *retVal)
-{
-  *retVal = ImageSmoothingEnabled();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-CanvasRenderingContext2D::SetMozImageSmoothingEnabled(bool val)
-{
-  SetImageSmoothingEnabled(val);
-  return NS_OK;
-}
-
 static uint8_t g2DContextLayerUserData;
 
 already_AddRefed<CanvasLayer>
 CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                          CanvasLayer *aOldLayer,
                                          LayerManager *aManager)
 {
   // Don't call EnsureTarget() ... if there isn't already a surface, then
--- a/content/canvas/src/CanvasRenderingContext2D.h
+++ b/content/canvas/src/CanvasRenderingContext2D.h
@@ -6,29 +6,30 @@
 #define CanvasRenderingContext2D_h
 
 #include <vector>
 #include "nsIDOMCanvasRenderingContext2D.h"
 #include "nsICanvasRenderingContextInternal.h"
 #include "mozilla/RefPtr.h"
 #include "nsColor.h"
 #include "nsHTMLCanvasElement.h"
+#include "nsHTMLVideoElement.h"
 #include "CanvasUtils.h"
-#include "nsHTMLImageElement.h"
-#include "nsHTMLVideoElement.h"
 #include "gfxFont.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/UnionTypes.h"
 
 #define NS_CANVASGRADIENTAZURE_PRIVATE_IID \
     {0x28425a6a, 0x90e0, 0x4d42, {0x9c, 0x75, 0xff, 0x60, 0x09, 0xb3, 0x10, 0xa8}}
 #define NS_CANVASPATTERNAZURE_PRIVATE_IID \
     {0xc9bacc25, 0x28da, 0x421e, {0x9a, 0x4b, 0xbb, 0xd6, 0x93, 0x05, 0x12, 0xbc}}
 
+class nsIDOMXULElement;
+
 namespace mozilla {
 namespace gfx {
 struct Rect;
 class SourceSurface;
 }
 
 namespace dom {
 extern const mozilla::gfx::Float SIGMA_MAX;
@@ -122,17 +123,16 @@ public:
 
 struct CanvasBidiProcessor;
 class CanvasRenderingContext2DUserData;
 
 /**
  ** CanvasRenderingContext2D
  **/
 class CanvasRenderingContext2D :
-  public nsIDOMCanvasRenderingContext2D,
   public nsICanvasRenderingContextInternal,
   public nsWrapperCache
 {
 typedef mozilla::dom::HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement
   HTMLImageOrCanvasOrVideoElement;
 
 public:
   CanvasRenderingContext2D();
@@ -423,18 +423,17 @@ public:
   JS::Value GetMozDash(JSContext* cx, mozilla::ErrorResult& error);
   void SetMozDash(JSContext* cx, const JS::Value& mozDash,
                   mozilla::ErrorResult& error);
 
   double MozDashOffset()
   {
     return CurrentState().dashOffset;
   }
-
-  void SetMozDashOffset(double mozDashOffset, mozilla::ErrorResult& error);
+  void SetMozDashOffset(double mozDashOffset);
 
   void GetMozTextStyle(nsAString& mozTextStyle)
   {
     GetFont(mozTextStyle);
   }
 
   void SetMozTextStyle(const nsAString& mozTextStyle,
                        mozilla::ErrorResult& error)
@@ -491,21 +490,23 @@ public:
   NS_IMETHOD Redraw(const gfxRect &r) { Redraw(ToRect(r)); return NS_OK; }
 
   // this rect is in mTarget's current user space
   void RedrawUser(const gfxRect &r);
 
   // nsISupports interface + CC
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
-  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(CanvasRenderingContext2D,
-                                                                   nsIDOMCanvasRenderingContext2D)
+  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(CanvasRenderingContext2D)
 
-  // nsIDOMCanvasRenderingContext2D interface
-  NS_DECL_NSIDOMCANVASRENDERINGCONTEXT2D
+  enum CanvasMultiGetterType {
+    CMG_STYLE_STRING = 0,
+    CMG_STYLE_PATTERN = 1,
+    CMG_STYLE_GRADIENT = 2
+  };
 
   enum Style {
     STYLE_STROKE = 0,
     STYLE_FILL,
     STYLE_MAX
   };
 
   nsINode* GetParentObject()
@@ -538,16 +539,21 @@ public:
 
   friend class CanvasRenderingContext2DUserData;
 
 protected:
   nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY,
                              uint32_t aWidth, uint32_t aHeight,
                              JSObject** aRetval);
 
+  nsresult PutImageData_explicit(int32_t x, int32_t y, uint32_t w, uint32_t h,
+                                 unsigned char *aData, uint32_t aDataLen,
+                                 bool hasDirtyRect, int32_t dirtyX, int32_t dirtyY,
+                                 int32_t dirtyWidth, int32_t dirtyHeight);
+
   /**
    * Internal method to complete initialisation, expects mTarget to have been set
    */
   nsresult Initialize(int32_t width, int32_t height);
 
   nsresult InitializeWithTarget(mozilla::gfx::DrawTarget *surface,
                                 int32_t width, int32_t height);
 
@@ -578,17 +584,16 @@ protected:
     CurrentState().SetGradientStyle(whichStyle, gradient);
   }
 
   void SetStyleFromPattern(CanvasPattern *pattern, Style whichStyle)
   {
     CurrentState().SetPatternStyle(whichStyle, pattern);
   }
 
-  void SetStyleFromStringOrInterface(const nsAString& aStr, nsISupports *aInterface, Style aWhichStyle);
   nsISupports* GetStyleAsStringOrInterface(nsAString& aStr, CanvasMultiGetterType& aType, Style aWhichStyle);
 
   // Returns whether a color was successfully parsed.
   bool ParseColor(const nsAString& aString, nscolor* aColor);
 
   static void StyleColorToString(const nscolor& aColor, nsAString& aStr);
 
   /**
@@ -659,42 +664,16 @@ protected:
   nsString& GetFont()
   {
     /* will initilize the value if not set, else does nothing */
     GetCurrentFontStyle();
 
     return CurrentState().font;
   }
 
-  static bool
-  ToHTMLImageOrCanvasOrVideoElement(nsIDOMElement* html,
-                                    HTMLImageOrCanvasOrVideoElement& element)
-  {
-    nsCOMPtr<nsIContent> content = do_QueryInterface(html);
-    if (content) {
-      if (content->IsHTML(nsGkAtoms::canvas)) {
-        element.SetAsHTMLCanvasElement() =
-          static_cast<nsHTMLCanvasElement*>(html);
-        return true;
-      }
-      if (content->IsHTML(nsGkAtoms::img)) {
-        element.SetAsHTMLImageElement() =
-          static_cast<nsHTMLImageElement*>(html);
-        return true;
-      }
-      if (content->IsHTML(nsGkAtoms::video)) {
-        element.SetAsHTMLVideoElement() =
-          static_cast<nsHTMLVideoElement*>(html);
-        return true;
-      }
-    }
-
-    return false;
-  }
-
   // Member vars
   int32_t mWidth, mHeight;
 
   // This is true when the canvas is valid, but of zero size, this requires
   // specific behavior on some operations.
   bool mZero;
 
   bool mOpaque;
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -14,16 +14,17 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 LIBRARY_NAME	= gkconcvs_s
 LIBXUL_LIBRARY  = 1
 
 EXPORTS_NAMESPACES = mozilla/dom
 
 EXPORTS_mozilla/dom = \
+	CanvasUtils.h \
 	CanvasRenderingContext2D.h \
   ImageData.h \
   $(NULL)
 
 CPPSRCS	= \
 	CanvasImageCache.cpp \
 	CanvasRenderingContext2D.cpp \
 	CanvasUtils.cpp \
--- a/content/canvas/test/Makefile.in
+++ b/content/canvas/test/Makefile.in
@@ -55,16 +55,17 @@ MOCHITEST_FILES = \
 	test_mozGetAsFile.html \
 	test_mozIsPointInStroke.html \
 	test_canvas_strokeStyle_getter.html \
 	test_bug613794.html \
 	test_bug753758.html \
 	test_bug764125.html \
 	test_drawImage_edge_cases.html \
 	test_drawImage_document_domain.html \
+  test_mozDashOffset.html \
 	file_drawImage_document_domain.html \
 	$(NULL)
 
 ifneq (1_Linux,$(MOZ_SUITE)_$(OS_ARCH))
 # This test fails in Suite on Linux for some reason, disable it there
 MOCHITEST_FILES += test_2d.composite.uncovered.image.destination-atop.html
 endif
 
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_mozDashOffset.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for mozDashOffset</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display">
+<canvas id="c" width="100" height="100"><p class="fallback">FAIL (fallback content)</p></canvas>
+</p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script>
+try {
+  var canvas = document.getElementById('c');
+  var ctx = canvas.getContext('2d');
+
+  ctx.mozDash = [1, 1];
+  
+  ctx.mozDashOffset = 1;
+  ctx.mozDashOffset = Infinity;
+  ok(ctx.mozDashOffset === 1, "ctx.mozDashOffset === 1");
+
+  ctx.mozDashOffset = 1;
+  ctx.mozDashOffset = -Infinity;
+  ok(ctx.mozDashOffset === 1, "ctx.mozDashOffset === 1");
+
+  ctx.mozDashOffset = 1;
+  ctx.mozDashOffset = NaN;
+  ok(ctx.mozDashOffset === 1, "ctx.mozDashOffset === 1");
+} catch(e) {
+  ok(false, "unexpected exception thrown in: test_mozDashOffset.html");
+}
+</script>
+</pre>
+</body>
+</html>
--- a/content/canvas/test/webgl/conformance/textures/tex-image-and-sub-image-2d-with-video.html
+++ b/content/canvas/test/webgl/conformance/textures/tex-image-and-sub-image-2d-with-video.html
@@ -102,16 +102,17 @@ function runTest(videoElement)
     var red = [255, 0, 0];
     var green = [0, 255, 0];
     runOneIteration(videoElement, false, true, red, green);
     runOneIteration(videoElement, false, false, green, red);
     runOneIteration(videoElement, true, true, red, green);
     runOneIteration(videoElement, true, false, green, red);
 
     glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+    videoElement.removeEventListener("playing", runTest);
     finishTest();
 }
 </script>
 </head>
 <body onload="init()">
 <canvas id="example" width="32px" height="32px"></canvas>
 <div id="description"></div>
 <div id="console"></div>
--- a/content/canvas/test/webgl/conformance/textures/texture-npot-video.html
+++ b/content/canvas/test/webgl/conformance/textures/texture-npot-video.html
@@ -134,16 +134,17 @@ function runTest(videoElement)
     runOneIteration(videoElement, false, true, black, black, false, true, false);
     runOneIteration(videoElement, false, true, black, black, true, true, false);
     runOneIteration(videoElement, false, true, green, red, false, false, false);
     runOneIteration(videoElement, false, false, red, green, false, false, false);
     runOneIteration(videoElement, true, true, green, red, false, false, false);
     runOneIteration(videoElement, true, false, red, green, false, false, false);
 
     glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+    videoElement.removeEventListener("playing", runTest);
     finishTest();
 }
 </script>
 </head>
 <body onload="init()">
 <canvas id="example" width="64px" height="48px"></canvas>
 <div id="description"></div>
 <div id="console"></div>
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -770,28 +770,29 @@ void
 nsTextStateManager::Destroy(void)
 {
   if (nsIMEStateManager::sIsTestingIME && mEditableNode) {
     nsIDocument* doc = mEditableNode->OwnerDoc();
     (new nsAsyncDOMEvent(doc, NS_LITERAL_STRING("MozIMEFocusOut"),
                          false, false))->RunDOMEventWhenSafe();
   }
   mWidget->OnIMEFocusChange(false);
+  // Even if there are some pending notification, it'll never notify the widget.
+  mWidget = nullptr;
   if (mObserving && mSel) {
     nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSel));
     if (selPrivate)
       selPrivate->RemoveSelectionListener(this);
   }
   mSel = nullptr;
   if (mObserving && mRootContent) {
     mRootContent->RemoveMutationObserver(this);
   }
   mRootContent = nullptr;
   mEditableNode = nullptr;
-  mWidget = nullptr;
   mObserving = false;
 }
 
 bool
 nsTextStateManager::IsManaging(nsPresContext* aPresContext,
                                nsIContent* aContent)
 {
   if (!mSel || !mRootContent || !mEditableNode) {
@@ -806,69 +807,69 @@ nsTextStateManager::IsManaging(nsPresCon
 
 NS_IMPL_ISUPPORTS2(nsTextStateManager,
                    nsIMutationObserver,
                    nsISelectionListener)
 
 // Helper class, used for selection change notification
 class SelectionChangeEvent : public nsRunnable {
 public:
-  SelectionChangeEvent(nsIWidget *widget)
-    : mWidget(widget)
+  SelectionChangeEvent(nsTextStateManager *aDispatcher)
+    : mDispatcher(aDispatcher)
   {
-    MOZ_ASSERT(mWidget);
+    MOZ_ASSERT(mDispatcher);
   }
 
   NS_IMETHOD Run() {
-    if(mWidget) {
-        mWidget->OnIMESelectionChange();
+    if (mDispatcher->mWidget) {
+      mDispatcher->mWidget->OnIMESelectionChange();
     }
     return NS_OK;
   }
 
 private:
-  nsCOMPtr<nsIWidget> mWidget;
+  nsRefPtr<nsTextStateManager> mDispatcher;
 };
 
 nsresult
 nsTextStateManager::NotifySelectionChanged(nsIDOMDocument* aDoc,
                                            nsISelection* aSel,
                                            int16_t aReason)
 {
   int32_t count = 0;
   nsresult rv = aSel->GetRangeCount(&count);
   NS_ENSURE_SUCCESS(rv, rv);
   if (count > 0 && mWidget) {
-    nsContentUtils::AddScriptRunner(new SelectionChangeEvent(mWidget));
+    nsContentUtils::AddScriptRunner(new SelectionChangeEvent(this));
   }
   return NS_OK;
 }
 
 // Helper class, used for text change notification
 class TextChangeEvent : public nsRunnable {
 public:
-  TextChangeEvent(nsIWidget *widget,
+  TextChangeEvent(nsTextStateManager* aDispatcher,
                   uint32_t start, uint32_t oldEnd, uint32_t newEnd)
-    : mWidget(widget)
+    : mDispatcher(aDispatcher)
     , mStart(start)
     , mOldEnd(oldEnd)
     , mNewEnd(newEnd)
   {
-    MOZ_ASSERT(mWidget);
+    MOZ_ASSERT(mDispatcher);
   }
 
   NS_IMETHOD Run() {
-    if(mWidget) {
-        mWidget->OnIMETextChange(mStart, mOldEnd, mNewEnd);
+    if (mDispatcher->mWidget) {
+      mDispatcher->mWidget->OnIMETextChange(mStart, mOldEnd, mNewEnd);
     }
     return NS_OK;
   }
 
 private:
-  nsCOMPtr<nsIWidget> mWidget;
+  nsRefPtr<nsTextStateManager> mDispatcher;
   uint32_t mStart, mOldEnd, mNewEnd;
 };
 
 void
 nsTextStateManager::CharacterDataChanged(nsIDocument* aDocument,
                                          nsIContent* aContent,
                                          CharacterDataChangeInfo* aInfo)
 {
@@ -880,17 +881,17 @@ nsTextStateManager::CharacterDataChanged
   if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
                     mRootContent, aContent, aInfo->mChangeStart, &offset)))
     return;
 
   uint32_t oldEnd = offset + aInfo->mChangeEnd - aInfo->mChangeStart;
   uint32_t newEnd = offset + aInfo->mReplaceLength;
 
   nsContentUtils::AddScriptRunner(
-      new TextChangeEvent(mWidget, offset, oldEnd, newEnd));
+      new TextChangeEvent(this, offset, oldEnd, newEnd));
 }
 
 void
 nsTextStateManager::NotifyContentAdded(nsINode* aContainer,
                                        int32_t aStartIndex,
                                        int32_t aEndIndex)
 {
   uint32_t offset = 0, newOffset = 0;
@@ -902,17 +903,17 @@ nsTextStateManager::NotifyContentAdded(n
   if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
                     aContainer->GetChildAt(aStartIndex),
                     aContainer, aEndIndex, &newOffset)))
     return;
 
   // fire notification
   if (newOffset)
     nsContentUtils::AddScriptRunner(
-        new TextChangeEvent(mWidget, offset, offset, offset + newOffset));
+        new TextChangeEvent(this, offset, offset, offset + newOffset));
 }
 
 void
 nsTextStateManager::ContentAppended(nsIDocument* aDocument,
                                     nsIContent* aContainer,
                                     nsIContent* aFirstNewContent,
                                     int32_t aNewIndexInContainer)
 {
@@ -951,17 +952,17 @@ nsTextStateManager::ContentRemoved(nsIDo
 
   if (NS_FAILED(nsContentEventHandler::GetFlatTextOffsetOfRange(
                     aChild, aChild, childOffset, &childOffset)))
     return;
 
   // fire notification
   if (childOffset)
     nsContentUtils::AddScriptRunner(
-        new TextChangeEvent(mWidget, offset, offset + childOffset, offset));
+        new TextChangeEvent(this, offset, offset + childOffset, offset));
 }
 
 bool
 nsIMEStateManager::IsEditable(nsINode* node)
 {
   if (node->IsEditable()) {
     return true;
   }
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -17,16 +17,17 @@
 #include "nsILoadGroup.h"
 #include "nsIObserver.h"
 #include "nsAudioStream.h"
 #include "VideoFrameContainer.h"
 #include "mozilla/CORSMode.h"
 #include "nsDOMMediaStream.h"
 #include "mozilla/Mutex.h"
 #include "nsTimeRanges.h"
+#include "nsIDOMWakeLock.h"
 
 // Define to output information on decoding and painting framerate
 /* #define DEBUG_FRAME_RATE 1 */
 
 typedef uint16_t nsMediaNetworkState;
 typedef uint16_t nsMediaReadyState;
 
 namespace mozilla {
@@ -383,16 +384,29 @@ public:
     NS_ASSERTION(mSrcStream, "Don't call this when not playing a stream");
     return mSrcStream->GetStream();
   }
 
 protected:
   class MediaLoadListener;
   class StreamListener;
 
+  class WakeLockBoolWrapper {
+  public:
+    WakeLockBoolWrapper(bool val = false) : mValue(val), mOuter(NULL), mWakeLock(NULL) {}
+    void SetOuter(nsHTMLMediaElement* outer) { mOuter = outer; }
+    operator bool() { return mValue; }
+    WakeLockBoolWrapper& operator=(bool val);
+    bool operator !() const { return !mValue; }
+  private:
+    bool mValue;
+    nsHTMLMediaElement* mOuter;
+    nsCOMPtr<nsIDOMMozWakeLock> mWakeLock;
+  };
+
   /**
    * Logs a warning message to the web console to report various failures.
    * aMsg is the localized message identifier, aParams is the parameters to
    * be substituted into the localized message, and aParamCount is the number
    * of parameters in aParams.
    */
   void ReportLoadError(const char* aMsg,
                        const PRUnichar** aParams = nullptr,
@@ -809,17 +823,17 @@ protected:
   bool mAutoplaying;
 
   // Indicates whether |autoplay| will actually autoplay based on the pref
   // media.autoplay.enabled
   bool mAutoplayEnabled;
 
   // Playback of the video is paused either due to calling the
   // 'Pause' method, or playback not yet having started.
-  bool mPaused;
+  WakeLockBoolWrapper mPaused;
 
   // True if the sound is muted.
   bool mMuted;
 
   // True if the sound is being captured.
   bool mAudioCaptured;
 
   // If TRUE then the media element was actively playing before the currently
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -9,18 +9,17 @@
 #include "mozilla/Base64.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "nsNetUtil.h"
 #include "nsDOMFile.h"
 
-#include "nsICanvasRenderingContextInternal.h"
-#include "nsIDOMCanvasRenderingContext2D.h"
+#include "mozilla/dom/CanvasRenderingContext2D.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIXPConnect.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "nsContentUtils.h"
 #include "nsJSUtils.h"
 #include "nsMathUtils.h"
 #include "nsStreamUtils.h"
@@ -38,16 +37,19 @@
 #define DEFAULT_CANVAS_HEIGHT 150
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 
 namespace {
 
+typedef mozilla::dom::HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement
+HTMLImageOrCanvasOrVideoElement;
+
 class ToBlobRunnable : public nsRunnable
 {
 public:
   ToBlobRunnable(nsIFileCallback* aCallback,
                  nsIDOMBlob* aBlob)
     : mCallback(aCallback),
       mBlob(aBlob)
   {
@@ -306,33 +308,37 @@ nsHTMLCanvasElement::IsPrintCallbackDone
 }
 
 nsIDOMHTMLCanvasElement*
 nsHTMLCanvasElement::GetOriginalCanvas()
 {
   return mOriginalCanvas ? mOriginalCanvas.get() : this;
 }
 
-
 nsresult
 nsHTMLCanvasElement::CopyInnerTo(nsGenericElement* aDest)
 {
   nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
   NS_ENSURE_SUCCESS(rv, rv);
   if (aDest->OwnerDoc()->IsStaticDocument()) {
     nsHTMLCanvasElement* dest = static_cast<nsHTMLCanvasElement*>(aDest);
     nsHTMLCanvasElement* self = const_cast<nsHTMLCanvasElement*>(this);
     dest->mOriginalCanvas = self;
 
+    HTMLImageOrCanvasOrVideoElement element;
+    element.SetAsHTMLCanvasElement() = this;
     nsCOMPtr<nsISupports> cxt;
     dest->GetContext(NS_LITERAL_STRING("2d"), JSVAL_VOID, getter_AddRefs(cxt));
-    nsCOMPtr<nsIDOMCanvasRenderingContext2D> context2d = do_QueryInterface(cxt);
+    nsRefPtr<CanvasRenderingContext2D> context2d =
+      static_cast<CanvasRenderingContext2D*>(cxt.get());
     if (context2d && !self->mPrintCallback) {
-      context2d->DrawImage(self,
-                           0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0);
+      ErrorResult err;
+      context2d->DrawImage(element,
+                           0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, err);
+      rv = err.ErrorCode();
     }
   }
   return rv;
 }
 
 nsChangeHint
 nsHTMLCanvasElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                             int32_t aModType) const
@@ -686,16 +692,26 @@ nsHTMLCanvasElement::MozGetAsFileImpl(co
 }
 
 nsresult
 nsHTMLCanvasElement::GetContextHelper(const nsAString& aContextId,
                                       nsICanvasRenderingContextInternal **aContext)
 {
   NS_ENSURE_ARG(aContext);
 
+  if (aContextId.EqualsLiteral("2d")) {
+    Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1);
+    nsRefPtr<CanvasRenderingContext2D> ctx =
+      new CanvasRenderingContext2D();
+
+    ctx->SetCanvasElement(this);
+    ctx.forget(aContext);
+    return NS_OK;
+  }
+
   NS_ConvertUTF16toUTF8 ctxId(aContextId);
 
   // check that ctxId is clamped to A-Za-z0-9_-
   for (uint32_t i = 0; i < ctxId.Length(); i++) {
     if ((ctxId[i] < 'A' || ctxId[i] > 'Z') &&
         (ctxId[i] < 'a' || ctxId[i] > 'z') &&
         (ctxId[i] < '0' || ctxId[i] > '9') &&
         (ctxId[i] != '-') &&
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -65,16 +65,17 @@
 #include "nsDOMMediaStream.h"
 #include "nsIScriptError.h"
 #include "nsHostObjectProtocolHandler.h"
 
 #include "nsCSSParser.h"
 #include "nsIMediaList.h"
 
 #include "ImageContainer.h"
+#include "nsIPowerManagerService.h"
 
 #ifdef MOZ_OGG
 #include "nsOggDecoder.h"
 #endif
 #ifdef MOZ_WAVE
 #include "nsWaveDecoder.h"
 #endif
 #ifdef MOZ_WEBM
@@ -1742,16 +1743,18 @@ nsHTMLMediaElement::nsHTMLMediaElement(a
   if (!gMediaElementLog) {
     gMediaElementLog = PR_NewLogModule("nsMediaElement");
   }
   if (!gMediaElementEventsLog) {
     gMediaElementEventsLog = PR_NewLogModule("nsMediaElementEvents");
   }
 #endif
 
+  mPaused.SetOuter(this);
+
   RegisterFreezableElement();
   NotifyOwnerDocumentActivityChanged();
 }
 
 nsHTMLMediaElement::~nsHTMLMediaElement()
 {
   NS_ASSERTION(!mHasSelfReference,
                "How can we be destroyed if we're still holding a self reference?");
@@ -1864,16 +1867,33 @@ NS_IMETHODIMP nsHTMLMediaElement::Play()
   // We changed mPaused and mAutoplaying which can affect AddRemoveSelfReference
   // and our preload status.
   AddRemoveSelfReference();
   UpdatePreloadAction();
 
   return NS_OK;
 }
 
+nsHTMLMediaElement::WakeLockBoolWrapper& nsHTMLMediaElement::WakeLockBoolWrapper::operator=(bool val) {
+  if (mValue == val)
+    return *this;
+  if (!mWakeLock && !val && mOuter) {
+    nsCOMPtr<nsIPowerManagerService> pmService =
+      do_GetService(POWERMANAGERSERVICE_CONTRACTID);
+    NS_ENSURE_TRUE(pmService, *this);
+
+    pmService->NewWakeLock(NS_LITERAL_STRING("Playing_media"), mOuter->OwnerDoc()->GetWindow(), getter_AddRefs(mWakeLock));
+  } else if (mWakeLock && val) {
+    mWakeLock->Unlock();
+    mWakeLock = NULL;
+  }
+  mValue = val;
+  return *this;
+}
+
 bool nsHTMLMediaElement::ParseAttribute(int32_t aNamespaceID,
                                           nsIAtom* aAttribute,
                                           const nsAString& aValue,
                                           nsAttrValue& aResult)
 {
   // Mappings from 'preload' attribute strings to an enumeration.
   static const nsAttrValue::EnumTable kPreloadTable[] = {
     { "",         nsHTMLMediaElement::PRELOAD_ATTR_EMPTY },
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -725,17 +725,16 @@ static uint64_t gDocshellIDCounter = 0;
 nsDocShell::nsDocShell():
     nsDocLoader(),
     mDefaultScrollbarPref(Scrollbar_Auto, Scrollbar_Auto),
     mTreeOwner(nullptr),
     mChromeEventHandler(nullptr),
     mCharsetReloadState(eCharsetReloadInit),
     mChildOffset(0),
     mBusyFlags(BUSY_FLAGS_NONE),
-    mFrameType(eFrameTypeRegular),
     mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
     mLoadType(0),
     mMarginWidth(-1),
     mMarginHeight(-1),
     mItemType(typeContent),
     mPreviousTransIndex(-1),
     mLoadedTransIndex(-1),
     mSandboxFlags(0),
@@ -763,16 +762,17 @@ nsDocShell::nsDocShell():
     mURIResultedInDocument(false),
     mIsBeingDestroyed(false),
     mIsExecutingOnLoadHandler(false),
     mIsPrintingOrPP(false),
     mSavingOldViewer(false),
 #ifdef DEBUG
     mInEnsureScriptEnv(false),
 #endif
+    mFrameType(eFrameTypeRegular),
     mOwnOrContainingAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID),
     mParentCharsetSource(0)
 {
     mHistoryID = ++gDocshellIDCounter;
     if (gDocShellCount++ == 0) {
         NS_ASSERTION(sURIFixup == nullptr,
                      "Huh, sURIFixup not null in first nsDocShell ctor!");
 
--- a/docshell/test/chrome/test_bug454235.xul
+++ b/docshell/test/chrome/test_bug454235.xul
@@ -16,17 +16,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   </body>
 
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
 
     /** Test for Bug 454235 **/
 SimpleTest.waitForExplicitFinish();
 
-addLoadEvent(doTest);
+SimpleTest.waitForFocus(doTest);
 
 function doTest() {
   var shownBrowser = document.getElementById("shownBrowser");
   var hiddenBrowser = document.getElementById("hiddenBrowser");
   var offScreenBrowser = document.getElementById("offScreenBrowser");
   var offScreenSubBrowser = offScreenBrowser.contentDocument.getElementById("topBrowser");
   var offScreenBurriedBrowser = offScreenBrowser.contentDocument.getElementById("burriedBrowser");
   
--- a/dom/base/nsContentPermissionHelper.cpp
+++ b/dom/base/nsContentPermissionHelper.cpp
@@ -20,21 +20,23 @@ nsContentPermissionRequestProxy::nsConte
 
 nsContentPermissionRequestProxy::~nsContentPermissionRequestProxy()
 {
   MOZ_COUNT_DTOR(nsContentPermissionRequestProxy);
 }
 
 nsresult
 nsContentPermissionRequestProxy::Init(const nsACString & type,
+                                      const nsACString & access,
                                       ContentPermissionRequestParent* parent)
 {
   NS_ASSERTION(parent, "null parent");
   mParent = parent;
   mType   = type;
+  mAccess = access;
 
   nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
   if (!prompt) {
     return NS_ERROR_FAILURE;
   }
 
   prompt->Prompt(this);
   return NS_OK;
@@ -51,16 +53,23 @@ NS_IMPL_ISUPPORTS1(nsContentPermissionRe
 NS_IMETHODIMP
 nsContentPermissionRequestProxy::GetType(nsACString & aType)
 {
   aType = mType;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsContentPermissionRequestProxy::GetAccess(nsACString & aAccess)
+{
+  aAccess = mAccess;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsContentPermissionRequestProxy::GetWindow(nsIDOMWindow * *aRequestingWindow)
 {
   NS_ENSURE_ARG_POINTER(aRequestingWindow);
   *aRequestingWindow = nullptr; // ipc doesn't have a window
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -109,37 +118,39 @@ nsContentPermissionRequestProxy::Allow()
   mParent = nullptr;
   return NS_OK;
 }
 
 namespace mozilla {
 namespace dom {
 
 ContentPermissionRequestParent::ContentPermissionRequestParent(const nsACString& aType,
+                                                               const nsACString& aAccess,
                                                                nsIDOMElement *aElement,
                                                                const IPC::Principal& aPrincipal)
 {
   MOZ_COUNT_CTOR(ContentPermissionRequestParent);
 
   mPrincipal = aPrincipal;
   mElement   = aElement;
   mType      = aType;
+  mAccess    = aAccess;
 }
 
 ContentPermissionRequestParent::~ContentPermissionRequestParent()
 {
   MOZ_COUNT_DTOR(ContentPermissionRequestParent);
 }
 
 bool
 ContentPermissionRequestParent::Recvprompt()
 {
   mProxy = new nsContentPermissionRequestProxy();
   NS_ASSERTION(mProxy, "Alloc of request proxy failed");
-  if (NS_FAILED(mProxy->Init(mType, this))) {
+  if (NS_FAILED(mProxy->Init(mType, mAccess, this))) {
     mProxy->Cancel();
   }
   return true;
 }
 
 void
 ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
 {
--- a/dom/base/nsContentPermissionHelper.h
+++ b/dom/base/nsContentPermissionHelper.h
@@ -17,43 +17,45 @@
 class nsContentPermissionRequestProxy;
 
 namespace mozilla {
 namespace dom {
 
 class ContentPermissionRequestParent : public PContentPermissionRequestParent
 {
  public:
-  ContentPermissionRequestParent(const nsACString& type, nsIDOMElement *element, const IPC::Principal& principal);
+  ContentPermissionRequestParent(const nsACString& type, const nsACString& access, nsIDOMElement *element, const IPC::Principal& principal);
   virtual ~ContentPermissionRequestParent();
 
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsIDOMElement>    mElement;
   nsCOMPtr<nsContentPermissionRequestProxy> mProxy;
   nsCString mType;
+  nsCString mAccess;
 
  private:
   virtual bool Recvprompt();
   virtual void ActorDestroy(ActorDestroyReason why);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 class nsContentPermissionRequestProxy : public nsIContentPermissionRequest
 {
  public:
   nsContentPermissionRequestProxy();
   virtual ~nsContentPermissionRequestProxy();
 
-  nsresult Init(const nsACString& type, mozilla::dom::ContentPermissionRequestParent* parent);
+  nsresult Init(const nsACString& type, const nsACString& access, mozilla::dom::ContentPermissionRequestParent* parent);
   void OnParentDestroyed();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTENTPERMISSIONREQUEST
 
  private:
   // Non-owning pointer to the ContentPermissionRequestParent object which owns this proxy.
   mozilla::dom::ContentPermissionRequestParent* mParent;
   nsCString mType;
+  nsCString mAccess;
 };
 #endif // nsContentPermissionHelper_h
 
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -1750,16 +1750,18 @@ nsFocusManager::Focus(nsPIDOMWindow* aWi
       if (widget)
         widget->SetFocus(false);
     }
   }
 
   // if switching to a new document, first fire the focus event on the
   // document and then the window.
   if (aIsNewDocument) {
+    nsIMEStateManager::OnChangeFocus(presShell->GetPresContext(), nullptr,
+                                     GetFocusMoveActionCause(aFlags));
     nsIDocument* doc = aWindow->GetExtantDoc();
     if (doc)
       SendFocusOrBlurEvent(NS_FOCUS_CONTENT, presShell, doc,
                            doc, aFlags & FOCUSMETHOD_MASK, aWindowRaised);
     if (mFocusedWindow == aWindow && mFocusedContent == nullptr)
       SendFocusOrBlurEvent(NS_FOCUS_CONTENT, presShell, doc,
                            aWindow, aFlags & FOCUSMETHOD_MASK, aWindowRaised);
   }
--- a/dom/bluetooth/BluetoothOppManager.cpp
+++ b/dom/bluetooth/BluetoothOppManager.cpp
@@ -186,42 +186,54 @@ BluetoothOppManager::Get()
 }
 
 bool
 BluetoothOppManager::Connect(const nsAString& aDeviceObjectPath,
                              BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
+  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED ||
+      GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTING) {
+    NS_WARNING("BluetoothOppManager has been already connected");
+    return false;
+  }
+
+  CloseSocket();
+
   BluetoothService* bs = BluetoothService::Get();
   if (!bs) {
     NS_WARNING("BluetoothService not available!");
     return false;
   }
 
   nsString serviceUuidStr =
     NS_ConvertUTF8toUTF16(BluetoothServiceUuidStr::ObjectPush);
 
-  nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
+  mRunnable = aRunnable;
 
   nsresult rv = bs->GetSocketViaService(aDeviceObjectPath,
                                         serviceUuidStr,
                                         BluetoothSocketType::RFCOMM,
                                         true,
                                         true,
                                         this,
-                                        runnable);
+                                        mRunnable);
 
-  runnable.forget();
   return NS_FAILED(rv) ? false : true;
 }
 
 void
 BluetoothOppManager::Disconnect()
 {
+  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_DISCONNECTED) {
+    NS_WARNING("BluetoothOppManager has been disconnected!");
+    return;
+  }
+
   CloseSocket();
 }
 
 nsresult
 BluetoothOppManager::HandleShutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   sInShutdown = true;
@@ -264,16 +276,25 @@ BluetoothOppManager::SendFile(BlobParent
   /*
    * Process of sending a file:
    *  - Keep blob because OPP connection has not been established yet.
    *  - Create an OPP connection by SendConnectRequest()
    *  - After receiving the response, start to read file and send.
    */
   mBlob = aActor->GetBlob();
 
+  nsCOMPtr<nsIDOMFile> file = do_QueryInterface(mBlob);
+  if (file) {
+    file->GetName(sFileName);
+  }
+
+  if (sFileName.IsEmpty()) {
+    sFileName.AssignLiteral("Unknown");
+  }
+
   SendConnectRequest();
 
   return true;
 }
 
 bool
 BluetoothOppManager::StopSendingFile()
 {
@@ -458,109 +479,113 @@ BluetoothOppManager::ReceiveSocketData(U
       AfterOppConnected();
 
       // Keep remote information
       mRemoteObexVersion = aMessage->mData[3];
       mRemoteConnectionFlags = aMessage->mData[4];
       mRemoteMaxPacketLength =
         (((int)(aMessage->mData[5]) << 8) | aMessage->mData[6]);
 
-      if (mBlob) {
-        /*
-         * Before sending content, we have to send a header including
-         * information such as file name, file length and content type.
-         */
-        nsresult rv;
-        nsCOMPtr<nsIDOMFile> file = do_QueryInterface(mBlob);
-        if (file) {
-          rv = file->GetName(sFileName);
-        }
+      MOZ_ASSERT(!sFileName.IsEmpty());
+      MOZ_ASSERT(mBlob);
+      /*
+       * Before sending content, we have to send a header including
+       * information such as file name, file length and content type.
+       */
+      nsresult rv = mBlob->GetType(sContentType);
+      if (NS_FAILED(rv)) {
+        NS_WARNING("Can't get content type");
+        SendDisconnectRequest();
+        return;
+      }
 
-        if (!file || sFileName.IsEmpty()) {
-          sFileName.AssignLiteral("Unknown");
-        }
-
-        rv = mBlob->GetType(sContentType);
-        if (NS_FAILED(rv)) {
-          NS_WARNING("Can't get content type");
-          return;
-        }
+      uint64_t fileLength;
+      rv = mBlob->GetSize(&fileLength);
+      if (NS_FAILED(rv)) {
+        NS_WARNING("Can't get file size");
+        SendDisconnectRequest();
+        return;
+      }
 
-        uint64_t fileLength;
-        rv = mBlob->GetSize(&fileLength);
-        if (NS_FAILED(rv)) {
-          NS_WARNING("Can't get file size");
-          return;
-        }
+      // Currently we keep the size of files which were sent/received via
+      // Bluetooth not exceed UINT32_MAX because the Length header in OBEX
+      // is only 4-byte long. Although it is possible to transfer a file
+      // larger than UINT32_MAX, it needs to parse another OBEX Header
+      // and I would like to leave it as a feature.
+      if (fileLength > (uint64_t)UINT32_MAX) {
+        NS_WARNING("The file size is too large for now");
+        SendDisconnectRequest();
+        return;
+      }
 
-        // Currently we keep the size of files which were sent/received via
-        // Bluetooth not exceed UINT32_MAX because the Length header in OBEX
-        // is only 4-byte long. Although it is possible to transfer a file
-        // larger than UINT32_MAX, it needs to parse another OBEX Header
-        // and I would like to leave it as a feature.
-        if (fileLength <= UINT32_MAX) {
-          NS_WARNING("The file size is too large for now");
-          SendDisconnectRequest();
-          return;
-        }
+      sFileLength = fileLength;
 
-        sFileLength = fileLength;
+      if (NS_FAILED(NS_NewThread(getter_AddRefs(mReadFileThread)))) {
+        NS_WARNING("Can't create thread");
+        SendDisconnectRequest();
+        return;
+      }
 
-        if (NS_FAILED(NS_NewThread(getter_AddRefs(mReadFileThread)))) {
-          NS_WARNING("Can't create thread");
-          SendDisconnectRequest();
-          return;
-        }
-
-        sInstance->SendPutHeaderRequest(sFileName, sFileLength);
-        StartFileTransfer(mConnectedDeviceAddress, false,
-                          sFileName, sFileLength, sContentType);
-      }
+      sInstance->SendPutHeaderRequest(sFileName, sFileLength);
+      StartFileTransfer(mConnectedDeviceAddress, false,
+                        sFileName, sFileLength, sContentType);
+    } else {
+      SendDisconnectRequest();
     }
   } else if (mLastCommand == ObexRequestCode::Disconnect) {
     if (opCode != ObexResponseCode::Success) {
       // FIXME: Needs error handling here
       NS_WARNING("[OPP] Disconnect failed");
     }
 
     AfterOppDisconnected();
   } else if (mLastCommand == ObexRequestCode::Put) {
     if (opCode != ObexResponseCode::Continue) {
-      // FIXME: Needs error handling here
       NS_WARNING("[OPP] Put failed");
+      FileTransferComplete(mConnectedDeviceAddress, false, false, sFileName,
+                           sSentFileLength, sContentType);
+      SendDisconnectRequest();
       return;
     }
 
-    if (mAbortFlag || mReadFileThread) {
+    if (mAbortFlag) {
       SendAbortRequest();
       return;
     }
 
     if (kUpdateProgressBase * mUpdateProgressCounter < sSentFileLength) {
       UpdateProgress(mConnectedDeviceAddress, false,
                      sSentFileLength, sFileLength);
       mUpdateProgressCounter = sSentFileLength / kUpdateProgressBase + 1;
     }
 
-    if (mInputStream) {
+    if (!mInputStream) {
       nsresult rv = mBlob->GetInternalStream(getter_AddRefs(mInputStream));
       if (NS_FAILED(rv)) {
         NS_WARNING("Can't get internal stream of blob");
+        FileTransferComplete(mConnectedDeviceAddress, false, false, sFileName,
+                             sSentFileLength, sContentType);
+        SendDisconnectRequest();
         return;
       }
     }
 
     nsRefPtr<ReadFileTask> task = new ReadFileTask(mInputStream);
     if (NS_FAILED(mReadFileThread->Dispatch(task, NS_DISPATCH_NORMAL))) {
       NS_WARNING("Cannot dispatch ring task!");
+      FileTransferComplete(mConnectedDeviceAddress, false, false, sFileName,
+                           sSentFileLength, sContentType);
+      SendDisconnectRequest();
     }
   } else if (mLastCommand == ObexRequestCode::PutFinal) {
     if (opCode != ObexResponseCode::Success) {
-      // FIXME: Needs error handling here
       NS_WARNING("[OPP] PutFinal failed");
+      FileTransferComplete(mConnectedDeviceAddress, false, false, sFileName,
+                           sSentFileLength, sContentType);
+      SendDisconnectRequest();
       return;
     }
 
     FileTransferComplete(mConnectedDeviceAddress, true, false, sFileName,
                          sSentFileLength, sContentType);
     SendDisconnectRequest();
   } else if (mLastCommand == ObexRequestCode::Abort) {
     if (opCode != ObexResponseCode::Success) {
@@ -1036,26 +1061,46 @@ BluetoothOppManager::ReceivingFileConfir
     NS_WARNING("Failed to send [bluetooth-opp-receiving-file-confirmation]");
     return;
   }
 }
 
 void
 BluetoothOppManager::OnConnectSuccess()
 {
+  if (mRunnable) {
+    BluetoothReply* reply = new BluetoothReply(BluetoothReplySuccess(true));
+    mRunnable->SetReply(reply);
+    if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
+      NS_WARNING("Failed to dispatch to main thread!");
+    }
+    mRunnable.forget();
+  }
+
   // Cache device address since we can't get socket address when a remote
   // device disconnect with us.
   GetSocketAddr(mConnectedDeviceAddress);
 
   mSocketStatus = GetConnectionStatus();
 }
 
 void
 BluetoothOppManager::OnConnectError()
 {
+  if (mRunnable) {
+    nsString errorStr;
+    errorStr.AssignLiteral("Failed to connect with a bluetooth opp manager!");
+    BluetoothReply* reply = new BluetoothReply(BluetoothReplyError(errorStr));
+    mRunnable->SetReply(reply);
+    if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
+      NS_WARNING("Failed to dispatch to main thread!");
+    }
+    mRunnable.forget();
+  }
+
   CloseSocket();
   mSocketStatus = GetConnectionStatus();
   Listen();
 }
 
 void
 BluetoothOppManager::OnDisconnect()
 {
--- a/dom/bluetooth/BluetoothOppManager.h
+++ b/dom/bluetooth/BluetoothOppManager.h
@@ -113,13 +113,15 @@ private:
 
   nsAutoPtr<uint8_t> mBodySegment;
   nsAutoPtr<uint8_t> mReceivedDataBuffer;
 
   nsCOMPtr<nsIDOMBlob> mBlob;
   nsCOMPtr<nsIThread> mReadFileThread;
   nsCOMPtr<nsIOutputStream> mOutputStream;
   nsCOMPtr<nsIInputStream> mInputStream;
+
+  nsRefPtr<BluetoothReplyRunnable> mRunnable;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/bluetooth/ObexBase.h
+++ b/dom/bluetooth/ObexBase.h
@@ -143,18 +143,24 @@ public:
   void GetName(nsString& aRetName)
   {
     aRetName.Truncate();
 
     int length = mHeaders.Length();
 
     for (int i = 0; i < length; ++i) {
       if (mHeaders[i]->mId == ObexHeaderId::Name) {
+        /*
+         * According to section 2.2.2 [Name] of IrOBEX spec, we know that
+         * the Name header is "a null terminated Unicode text string describing
+         * the name of the object.", and that's the reason why we need to minus
+         * 1 to get the real length of the file name.
+         */
+        int nameLength = mHeaders[i]->mDataLength / 2 - 1;
         uint8_t* ptr = mHeaders[i]->mData.get();
-        int nameLength = mHeaders[i]->mDataLength / 2;
 
         for (int j = 0; j < nameLength; ++j) {
           PRUnichar c = ((((uint32_t)ptr[j * 2]) << 8) | ptr[j * 2 + 1]);
           aRetName += c;
         }
 
         break;
       }
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -195,16 +195,35 @@ DeviceStorageTypeChecker::GetPermissionF
     return NS_ERROR_FAILURE;
   }
 
   aPermissionResult.AssignLiteral("device-storage:");
   aPermissionResult.Append(NS_ConvertUTF16toUTF8(aType));
   return NS_OK;
 }
 
+nsresult
+DeviceStorageTypeChecker::GetAccessForRequest(const DeviceStorageRequestType aRequestType, nsACString& aAccessResult)
+{
+  switch(aRequestType) {
+    case DEVICE_STORAGE_REQUEST_READ:
+    case DEVICE_STORAGE_REQUEST_WATCH:
+    case DEVICE_STORAGE_REQUEST_STAT:
+      aAccessResult.AssignLiteral("read");
+      break;
+    case DEVICE_STORAGE_REQUEST_WRITE:
+    case DEVICE_STORAGE_REQUEST_DELETE:
+      aAccessResult.AssignLiteral("write");
+      break;
+    default:
+      aAccessResult.AssignLiteral("undefined");
+  }
+  return NS_OK;
+}
+
 class IOEventComplete : public nsRunnable
 {
 public:
   IOEventComplete(DeviceStorageFile *aFile, const char *aType)
     : mFile(aFile)
     , mType(aType)
   {
   }
@@ -1035,16 +1054,23 @@ nsDOMDeviceStorageCursor::GetStorageType
 
 NS_IMETHODIMP
 nsDOMDeviceStorageCursor::GetType(nsACString & aType)
 {
   return DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, aType);
 }
 
 NS_IMETHODIMP
+nsDOMDeviceStorageCursor::GetAccess(nsACString & aAccess)
+{
+  aAccess = NS_LITERAL_CSTRING("read");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMDeviceStorageCursor::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
 {
   NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorageCursor::GetWindow(nsIDOMWindow * *aRequestingWindow)
@@ -1387,24 +1413,16 @@ private:
 
 class DeviceStorageRequest MOZ_FINAL
   : public nsIContentPermissionRequest
   , public nsIRunnable
   , public PCOMContentPermissionRequestChild
 {
 public:
 
-    enum DeviceStorageRequestType {
-        DEVICE_STORAGE_REQUEST_READ,
-        DEVICE_STORAGE_REQUEST_WRITE,
-        DEVICE_STORAGE_REQUEST_DELETE,
-        DEVICE_STORAGE_REQUEST_WATCH,
-        DEVICE_STORAGE_REQUEST_STAT
-    };
-
     DeviceStorageRequest(const DeviceStorageRequestType aRequestType,
                          nsPIDOMWindow *aWindow,
                          nsIPrincipal *aPrincipal,
                          DeviceStorageFile *aFile,
                          DOMRequest* aRequest,
                          nsDOMDeviceStorage *aDeviceStorage,
                          nsIDOMEventListener *aListener)
       : mRequestType(aRequestType)
@@ -1451,17 +1469,22 @@ public:
       // Corresponding release occurs in DeallocPContentPermissionRequest.
       AddRef();
 
       nsCString type;
       nsresult rv = DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, type);
       if (NS_FAILED(rv)) {
         return rv;
       }
-      child->SendPContentPermissionRequestConstructor(this, type, IPC::Principal(mPrincipal));
+      nsCString access;
+      rv = DeviceStorageTypeChecker::GetAccessForRequest(DeviceStorageRequestType(mRequestType), access);
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+      child->SendPContentPermissionRequestConstructor(this, type, access, IPC::Principal(mPrincipal));
 
       Sendprompt();
       return NS_OK;
     }
 
     nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
     if (prompt) {
       prompt->Prompt(this);
@@ -1474,16 +1497,25 @@ public:
     nsCString type;
     nsresult rv = DeviceStorageTypeChecker::GetPermissionForType(mFile->mStorageType, aType);
     if (NS_FAILED(rv)) {
       return rv;
     }
     return NS_OK;
   }
 
+  NS_IMETHOD GetAccess(nsACString & aAccess)
+  {
+    nsresult rv = DeviceStorageTypeChecker::GetAccessForRequest(DeviceStorageRequestType(mRequestType), aAccess);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
   NS_IMETHOD GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
   {
     NS_IF_ADDREF(*aRequestingPrincipal = mPrincipal);
     return NS_OK;
   }
 
   NS_IMETHOD GetWindow(nsIDOMWindow * *aRequestingWindow)
   {
@@ -1809,17 +1841,17 @@ nsDOMDeviceStorage::AddNamed(nsIDOMBlob 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory, aPath);
   if (!dsf->IsSafePath()) {
     r = new PostErrorEvent(request, POST_ERROR_EVENT_PERMISSION_DENIED);
   } else if (!typeChecker->Check(mStorageType, dsf->mFile) ||
       !typeChecker->Check(mStorageType, aBlob)) {
     r = new PostErrorEvent(request, POST_ERROR_EVENT_ILLEGAL_TYPE);
   }
   else {
-    r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_WRITE,
+    r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_WRITE,
                                  win, mPrincipal, dsf, request, aBlob);
   }
 
   NS_DispatchToMainThread(r);
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -1862,17 +1894,17 @@ nsDOMDeviceStorage::GetInternal(const JS
     return NS_OK;
   }
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory, path);
   dsf->SetEditable(aEditable);
   if (!dsf->IsSafePath()) {
     r = new PostErrorEvent(request, POST_ERROR_EVENT_PERMISSION_DENIED);
   } else {
-    r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_READ,
+    r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_READ,
                                  win, mPrincipal, dsf, request);
   }
   NS_DispatchToMainThread(r);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::Delete(const JS::Value & aPath, JSContext* aCx, nsIDOMDOMRequest * *_retval)
@@ -1896,17 +1928,17 @@ nsDOMDeviceStorage::Delete(const JS::Val
   }
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory, path);
 
   if (!dsf->IsSafePath()) {
     r = new PostErrorEvent(request, POST_ERROR_EVENT_PERMISSION_DENIED);
   }
   else {
-    r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_DELETE,
+    r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_DELETE,
                                  win, mPrincipal, dsf, request);
   }
   NS_DispatchToMainThread(r);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::Stat(nsIDOMDOMRequest** aRetval)
@@ -1915,17 +1947,17 @@ nsDOMDeviceStorage::Stat(nsIDOMDOMReques
   if (!win) {
     return NS_ERROR_UNEXPECTED;
   }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   NS_ADDREF(*aRetval = request);
 
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory);
-  nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_STAT,
+  nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_STAT,
                                                      win,
                                                      mPrincipal,
                                                      dsf,
                                                      request);
   NS_DispatchToMainThread(r);
   return NS_OK;
 }
 
@@ -2037,17 +2069,17 @@ nsDOMDeviceStorage::EnumerateInternal(co
     // Corresponding release occurs in DeallocPContentPermissionRequest.
     r->AddRef();
 
     nsCString type;
     nsresult rv = DeviceStorageTypeChecker::GetPermissionForType(mStorageType, type);
     if (NS_FAILED(rv)) {
       return rv;
     }
-    child->SendPContentPermissionRequestConstructor(r, type, IPC::Principal(mPrincipal));
+    child->SendPContentPermissionRequestConstructor(r, type, NS_LITERAL_CSTRING("read"), IPC::Principal(mPrincipal));
 
     r->Sendprompt();
 
     return NS_OK;
   }
 
   nsCOMPtr<nsIContentPermissionPrompt> prompt = do_CreateInstance(NS_CONTENT_PERMISSION_PROMPT_CONTRACTID);
   if (prompt) {
@@ -2224,17 +2256,17 @@ nsDOMDeviceStorage::AddEventListener(con
 {
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
     return NS_ERROR_UNEXPECTED;
   }
 
   nsRefPtr<DOMRequest> request = new DOMRequest(win);
   nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory);
-  nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_WATCH,
+  nsCOMPtr<nsIRunnable> r = new DeviceStorageRequest(DEVICE_STORAGE_REQUEST_WATCH,
                                                      win, mPrincipal, dsf, request, this, aListener);
   NS_DispatchToMainThread(r);
   return nsDOMEventTargetHelper::AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted, aArgc);
 }
 
 NS_IMETHODIMP
 nsDOMDeviceStorage::AddSystemEventListener(const nsAString & aType,
                                            nsIDOMEventListener *aListener,
--- a/dom/devicestorage/nsDeviceStorage.h
+++ b/dom/devicestorage/nsDeviceStorage.h
@@ -38,30 +38,39 @@ class nsPIDOMWindow;
 #define POST_ERROR_EVENT_PERMISSION_DENIED           "SecurityError"
 #define POST_ERROR_EVENT_ILLEGAL_TYPE                "TypeMismatchError"
 #define POST_ERROR_EVENT_UNKNOWN                     "Unknown"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::dom::devicestorage;
 
+enum DeviceStorageRequestType {
+    DEVICE_STORAGE_REQUEST_READ,
+    DEVICE_STORAGE_REQUEST_WRITE,
+    DEVICE_STORAGE_REQUEST_DELETE,
+    DEVICE_STORAGE_REQUEST_WATCH,
+    DEVICE_STORAGE_REQUEST_STAT
+};
+
 class DeviceStorageTypeChecker MOZ_FINAL
 {
 public:
   static DeviceStorageTypeChecker* CreateOrGet();
 
   DeviceStorageTypeChecker();
   ~DeviceStorageTypeChecker();
 
   void InitFromBundle(nsIStringBundle* aBundle);
 
   bool Check(const nsAString& aType, nsIDOMBlob* aBlob);
   bool Check(const nsAString& aType, nsIFile* aFile);
 
   static nsresult GetPermissionForType(const nsAString& aType, nsACString& aPermissionResult);
+  static nsresult GetAccessForRequest(const DeviceStorageRequestType aRequestType, nsACString& aAccessResult);
 
 private:
   nsString mPicturesExtensions;
   nsString mVideosExtensions;
   nsString mMusicExtensions;
 
   static nsAutoPtr<DeviceStorageTypeChecker> sDeviceStorageTypeChecker;
 };
--- a/dom/encoding/TextDecoder.cpp
+++ b/dom/encoding/TextDecoder.cpp
@@ -201,23 +201,16 @@ TextDecoder::GetEncoding(nsAString& aEnc
   // "utf-16".
   // This workaround should not be exposed to the public API and so "utf-16"
   // is returned by GetEncoding() if the internal encoding name is "utf-16le".
   if (mEncoding.EqualsLiteral("UTF-16LE")) {
     aEncoding.AssignLiteral("utf-16");
     return;
   }
 
-  // Similarly, "x-windows-949" is used for the "euc-kr" family. Therefore, if
-  // the internal encoding name is "x-windows-949", "euc-kr" is returned.
-  if (mEncoding.EqualsLiteral("x-windows-949")) {
-    aEncoding.AssignLiteral("euc-kr");
-    return;
-  }
-
   CopyASCIItoUTF16(mEncoding, aEncoding);
   nsContentUtils::ASCIIToLower(aEncoding);
 }
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(TextDecoder)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(TextDecoder)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TextDecoder)
--- a/dom/encoding/labelsencodings.properties
+++ b/dom/encoding/labelsencodings.properties
@@ -200,24 +200,24 @@ csiso2022jp=ISO-2022-JP
 iso-2022-jp=ISO-2022-JP
 csshiftjis=Shift_JIS
 ms_kanji=Shift_JIS
 shift-jis=Shift_JIS
 shift_jis=Shift_JIS
 sjis=Shift_JIS
 windows-31j=Shift_JIS
 x-sjis=Shift_JIS
-cseuckr=x-windows-949
-csksc56011987=x-windows-949
-euc-kr=x-windows-949
-iso-ir-149=x-windows-949
-korean=x-windows-949
-ks_c_5601-1987=x-windows-949
-ks_c_5601-1989=x-windows-949
-ksc5601=x-windows-949
-ksc_5601=x-windows-949
-windows-949=x-windows-949
+cseuckr=EUC-KR
+csksc56011987=EUC-KR
+euc-kr=EUC-KR
+iso-ir-149=EUC-KR
+korean=EUC-KR
+ks_c_5601-1987=EUC-KR
+ks_c_5601-1989=EUC-KR
+ksc5601=EUC-KR
+ksc_5601=EUC-KR
+windows-949=EUC-KR
 csiso2022kr=ISO-2022-KR
 iso-2022-kr=ISO-2022-KR
 utf-16=UTF-16LE
 utf-16le=UTF-16LE
 utf-16be=UTF-16BE
 x-user-defined=x-user-defined
--- a/dom/interfaces/base/nsIContentPermissionPrompt.idl
+++ b/dom/interfaces/base/nsIContentPermissionPrompt.idl
@@ -8,26 +8,32 @@ interface nsIPrincipal;
 interface nsIDOMWindow;
 interface nsIDOMElement;
 
 /**
  * Interface allows access to a content to request
  * permission to perform a privileged operation such as
  * geolocation.
  */
-[scriptable, uuid(E1F3796C-ADFA-414B-B2A7-AC62F29395EE)]
+[scriptable, uuid(1de67000-2de8-11e2-81c1-0800200c9a66)]
 interface nsIContentPermissionRequest : nsISupports {
 
   /**
    *  The type of the permission request, such as
    *  "geolocation".
    */
   readonly attribute ACString type;
 
   /**
+   *  The access of the permission request, such as
+   *  "read".
+   */
+  readonly attribute ACString access;
+
+  /**
    *  The principal of the permission request.
    */
   readonly attribute nsIPrincipal principal;
 
   /**
    *  The window or element that the permission request was
    *  originated in.  Typically the element will be non-null
    *  in when using out of process content.  window or
--- a/dom/interfaces/canvas/nsIDOMCanvasRenderingContext2D.idl
+++ b/dom/interfaces/canvas/nsIDOMCanvasRenderingContext2D.idl
@@ -1,22 +1,14 @@
 /* -*- 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/. */
 
 #include "nsISupports.idl"
-#include "nsIVariant.idl"
-
-interface nsIDOMWindow;
-interface nsIDOMElement;
-interface nsIDOMHTMLElement;
-interface nsIDOMHTMLImageElement;
-interface nsIDOMHTMLCanvasElement;
-interface nsIDOMXULElement;
 
 [scriptable, uuid(bbb20a59-524e-4662-981e-5e142814b20c)]
 interface nsIDOMCanvasGradient : nsISupports
 {
   void addColorStop(in float offset, in DOMString color);
 };
 
 [scriptable, uuid(21dea65c-5c08-4eb1-ac82-81fe95be77b8)]
@@ -25,237 +17,34 @@ interface nsIDOMCanvasPattern : nsISuppo
 };
 
 [scriptable, uuid(2d01715c-ec7d-424a-ab85-e0fd70c8665c)]
 interface nsIDOMTextMetrics : nsISupports
 {
   readonly attribute float width;
 };
 
-[scriptable, uuid(438fe14d-6501-40ab-b6c2-130fa38bd2c9)]
+/**
+ * This interface remains only for the constants, for a context, use the
+ * WebIDL/Paris bindings instead (CanvasRenderingContext2D.webidl).
+ * The constants are used by CanvasRenderingContext2D::DrawWindow and are
+ * used in WindowsPreviewPerTab.jsm and some extensions. The constants can
+ * be referenced directly via a canvas context 2d rather than this interface,
+ * and that should be preferred in new code. 
+ */
+[scriptable, uuid(4417cab7-c7eb-4e0c-b00a-c43842f0cba8)]
 interface nsIDOMCanvasRenderingContext2D : nsISupports
 {
-  // back-reference to the canvas element for which
-  // this context was created
-  readonly attribute nsIDOMHTMLCanvasElement canvas;
-
-  // state
-  [binaryname(MozSave)]
-  void save();
-  [binaryname(MozRestore)]
-  void restore();
-
-  // transformations
-  void scale(in float x, in float y);
-  void rotate(in float angle);
-  void translate(in float x, in float y);
-  void transform(in float m11, in float m12, in float m21, in float m22, in float dx, in float dy);
-  void setTransform(in float m11, in float m12, in float m21, in float m22, in float dx, in float dy);
-  [implicit_jscontext]
-  attribute jsval mozCurrentTransform; // [ m11, m12, m21, m22, dx, dy ], i.e. row major
-  [implicit_jscontext]
-  attribute jsval mozCurrentTransformInverse;
-
-  // compositing
-  attribute float globalAlpha; /* default 1.0 -- opaque */
-  attribute DOMString globalCompositeOperation; /* default "over" */
-
-  // Colors and Styles
-
-  // These attributes work, but are quickstubbed for JS code.  Native
-  // code should use the _multi variants below.
-  attribute nsIVariant strokeStyle;
-  attribute nsIVariant fillStyle;
-
-  // These do the actual work.  Use these from c++ -- only one of str or iface
-  // should be specified; the one that's not null/void is used.  For the getter,
-  // ifaceType is 0 if it's a string, 1 if it's a pattern, or 2 if it's a gradient
-%{C++
-enum CanvasMultiGetterType {
-      CMG_STYLE_STRING = 0,
-      CMG_STYLE_PATTERN = 1,
-      CMG_STYLE_GRADIENT = 2
-};
-%}
-  [noscript] void setStrokeStyle_multi(in DOMString str, in nsISupports iface);
-  [noscript] void getStrokeStyle_multi(out DOMString str, out nsISupports iface, out long type);
-  [noscript] void setFillStyle_multi(in DOMString str, in nsISupports iface);
-  [noscript] void getFillStyle_multi(out DOMString str, out nsISupports iface, out long type);
-
-  //attribute DOMString fillRule;
-  attribute DOMString mozFillRule; /* "evenodd", "nonzero" (default) */
-
-  nsIDOMCanvasGradient createLinearGradient (in float x0, in float y0, in float x1, in float y1);
-  nsIDOMCanvasGradient createRadialGradient(in float x0, in float y0, in float r0, in float x1, in float y1, in float r1);
-  nsIDOMCanvasPattern createPattern(in nsIDOMHTMLElement image, in DOMString repetition);
-  attribute float lineWidth; /* default 1 */
-  [binaryname(MozLineCap)]
-  attribute DOMString lineCap; /* "butt", "round", "square" (default) */
-  [binaryname(MozLineJoin)]
-  attribute DOMString lineJoin; /* "round", "bevel", "miter" (default) */
-  attribute float miterLimit; /* default 10 */
-
-  [implicit_jscontext]
-  attribute jsval mozDash; /* default |null| */
-  attribute float mozDashOffset; /* default 0.0 */
-
-  // shadows
-  attribute float shadowOffsetX;
-  attribute float shadowOffsetY;
-  attribute float shadowBlur;
-  [binaryname(MozShadowColor)]
-  attribute DOMString shadowColor;
-
-  // rects
-  void clearRect(in float x, in float y, in float w, in float h);
-  void fillRect(in float x, in float y, in float w, in float h);
-  void strokeRect(in float x, in float y, in float w, in float h);
-
-  // path API
-  [binaryname(MozBeginPath)]
-  void beginPath();
-  [binaryname(MozClosePath)]
-  void closePath();
-
-  void moveTo(in float x, in float y);
-  void lineTo(in float x, in float y);
-  void quadraticCurveTo(in float cpx, in float cpy, in float x, in float y);
-  void bezierCurveTo(in float cp1x, in float cp1y, in float cp2x, in float cp2y, in float x, in float y);
-  void arcTo(in float x1, in float y1, in float x2, in float y2, in float radius);
-  void arc(in float x, in float y, in float r, in float startAngle, in float endAngle, [optional] in boolean anticlockwise);
-  void rect(in float x, in float y, in float w, in float h);
-
-  [binaryname(MozFill)]
-  void fill();
-  [binaryname(MozStroke)]
-  void stroke();
-  [binaryname(MozClip)]
-  void clip();
-
-  // text api
-  [binaryname(MozFont)]
-  attribute DOMString font; /* default "10px sans-serif" */
-  [binaryname(MozTextAlign)]
-  attribute DOMString textAlign; /* "start" (default), "end", "left", "right",
-                                 "center" */
-  [binaryname(MozTextBaseline)]
-  attribute DOMString textBaseline; /* "alphabetic" (default), "top", "hanging",
-                                    "middle", "ideographic", "bottom" */
-
-  void fillText(in DOMString text, in float x, in float y, [optional] in float maxWidth);
-  void strokeText(in DOMString text, in float x, in float y, [optional] in float maxWidth);
-  nsIDOMTextMetrics measureText(in DOMString text);
-
-  [binaryname(TextStyle)]
-  attribute DOMString mozTextStyle;
-
-  // image api
-
-  [optional_argc] void drawImage(in nsIDOMElement image,
-                                 in float a1, in float a2,
-                                 [optional] in float a3,
-                                 [optional] in float a4,
-                                 [optional] in float a5,
-                                 [optional] in float a6,
-                                 [optional] in float a7,
-                                 [optional] in float a8);
-
-/*
-  void drawImage(in HTMLImageElement image, in float dx, in float dy);
-  void drawImage(in HTMLImageElement image, in float dx, in float dy, in float sw, in float sh);
-  void drawImage(in HTMLImageElement image, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh);
-*/
-
-  // point-membership test
-  boolean isPointInPath(in float x, in float y);
-  boolean mozIsPointInStroke(in float x, in float y);
-
-  // pixel manipulation
-  // ImageData getImageData (in float x, in float y, in float width, in float height);
-  // void putImageData (in ImageData d, in float x, in float y);
-  // ImageData = { width: #, height: #, data: [r, g, b, a, ...] }
-
-  // nsISupports is OK, because the binding code will deal correctly
-  [implicit_jscontext]
-  nsISupports getImageData(in double sx, in double sy, in double sw, in double sh);
-
-
-  // void putImageData(ImageData imagedata, double dx, double dy);
-  // void putImageDataHD(ImageData imagedata, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight);
-  // We use jsval for the imageData because that's what our C++ code wants
-  [implicit_jscontext, optional_argc]
-  void putImageData(in jsval imageData, in double dx, in double dy,
-                    [optional] in double dirtyX, [optional] in double dirtyY,
-                    [optional] in double dirtyWidth,
-                    [optional] in double dirtyHeight);
-
-  // dataLen must be == width*height*4 in this call
-  [noscript] void putImageData_explicit(in long x, in long y, in unsigned long width, in unsigned long height,
-                                        [array, size_is(dataLen)] in octet dataPtr, in unsigned long dataLen, in boolean hasDirtyRect,
-                                        in long dirtyX, in long dirtyY, in long dirtyWidth, in long dirtyHeight);
-
-  // ImageData createImageData(double w, double h);
-  // ImageData createImageData(ImageData data);
-  // nsISupports is OK, because the binding code will deal correctly
-  [implicit_jscontext, optional_argc]
-  nsISupports createImageData(in jsval arg1, [optional] in jsval arg2);
-
-  // image smoothing mode -- if disabled, images won't be smoothed
-  // if scaled.
-  attribute boolean mozImageSmoothingEnabled;
-
   // Show the caret if appropriate when drawing
   const unsigned long DRAWWINDOW_DRAW_CARET   = 0x01;
   // Don't flush pending layout notifications that could otherwise
   // be batched up
   const unsigned long DRAWWINDOW_DO_NOT_FLUSH = 0x02;
   // Draw scrollbars and scroll the viewport if they are present
   const unsigned long DRAWWINDOW_DRAW_VIEW    = 0x04;
   // Use the widget layer manager if available. This means hardware
   // acceleration may be used, but it might actually be slower or
   // lower quality than normal. It will however more accurately reflect
   // the pixels rendered to the screen.
   const unsigned long DRAWWINDOW_USE_WIDGET_LAYERS = 0x08;
   // Don't synchronously decode images - draw what we have
   const unsigned long DRAWWINDOW_ASYNC_DECODE_IMAGES = 0x10;
-
-  /**
-   * Renders a region of a window into the canvas.  The contents of
-   * the window's viewport are rendered, ignoring viewport clipping
-   * and scrolling.
-   *
-   * @param x
-   * @param y
-   * @param w
-   * @param h specify the area of the window to render, in CSS
-   * pixels.
-   *
-   * @param backgroundColor the canvas is filled with this color
-   * before we render the window into it. This color may be
-   * transparent/translucent. It is given as a CSS color string
-   * (e.g., rgb() or rgba()).
-   *
-   * @param flags Used to better control the drawWindow call.
-   * Flags can be ORed together.
-   *
-   * Of course, the rendering obeys the current scale, transform and
-   * globalAlpha values.
-   *
-   * Hints:
-   * -- If 'rgba(0,0,0,0)' is used for the background color, the
-   * drawing will be transparent wherever the window is transparent.
-   * -- Top-level browsed documents are usually not transparent
-   * because the user's background-color preference is applied,
-   * but IFRAMEs are transparent if the page doesn't set a background.
-   * -- If an opaque color is used for the background color, rendering
-   * will be faster because we won't have to compute the window's
-   * transparency.
-   *
-   * This API cannot currently be used by Web content. It is chrome
-   * only.
-   */
-  void drawWindow(in nsIDOMWindow window, in float x, in float y,
-                  in float w, in float h, in DOMString bgColor,
-                  [optional] in unsigned long flags);
-  void asyncDrawXULElement(in nsIDOMXULElement elem, in float x, in float y,
-                  in float w, in float h, in DOMString bgColor,
-                  [optional] in unsigned long flags);
 };
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -181,24 +181,26 @@ parent:
     SetBackgroundColor(nscolor color);
 
     /**
      * Initiates an asynchronous request for permission for the
      * provided principal.
      *
      * @param aType
      *   The type of permission to request.
+     * @param aAccess
+     *   Access type. "read" for example.
      * @param aPrincipal
      *   The principal of the request.
      *
      * NOTE: The principal is untrusted in the parent process. Only
      *       principals that can live in the content process should
      *       provided.
      */
-    PContentPermissionRequest(nsCString aType, Principal principal);
+    PContentPermissionRequest(nsCString aType, nsCString aAccess, Principal principal);
 
     PContentDialog(uint32_t aType, nsCString aName, nsCString aFeatures,
                    int32_t[] aIntParams, nsString[] aStringParams);
 
     /**
      * Create a layout frame (encapsulating a remote layer tree) for
      * the page that is currently loaded in the <browser>.
      */
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1495,17 +1495,17 @@ TabChild::AllocPContentDialog(const uint
 bool
 TabChild::DeallocPContentDialog(PContentDialogChild* aDialog)
 {
   delete aDialog;
   return true;
 }
 
 PContentPermissionRequestChild*
-TabChild::AllocPContentPermissionRequest(const nsCString& aType, const IPC::Principal&)
+TabChild::AllocPContentPermissionRequest(const nsCString& aType, const nsCString& aAccess, const IPC::Principal&)
 {
   NS_RUNTIMEABORT("unused");
   return nullptr;
 }
 
 bool
 TabChild::DeallocPContentPermissionRequest(PContentPermissionRequestChild* actor)
 {
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -253,26 +253,29 @@ public:
                                InfallibleTArray<nsString>& aStringParams);
     static void ArraysToParams(const InfallibleTArray<int>& aIntParams,
                                const InfallibleTArray<nsString>& aStringParams,
                                nsIDialogParamBlock* aParams);
 
 #ifdef DEBUG
     virtual PContentPermissionRequestChild* SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
                                                                                      const nsCString& aType,
+                                                                                     const nsCString& aAccess,
                                                                                      const IPC::Principal& aPrincipal)
     {
       PCOMContentPermissionRequestChild* child = static_cast<PCOMContentPermissionRequestChild*>(aActor);
-      PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aType, aPrincipal);
+      PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aType, aAccess, aPrincipal);
       child->mIPCOpen = true;
       return request;
     }
 #endif /* DEBUG */
 
-    virtual PContentPermissionRequestChild* AllocPContentPermissionRequest(const nsCString& aType, const IPC::Principal& aPrincipal);
+    virtual PContentPermissionRequestChild* AllocPContentPermissionRequest(const nsCString& aType,
+                                                                           const nsCString& aAccess,
+                                                                           const IPC::Principal& aPrincipal);
     virtual bool DeallocPContentPermissionRequest(PContentPermissionRequestChild* actor);
 
     virtual POfflineCacheUpdateChild* AllocPOfflineCacheUpdate(
             const URIParams& manifestURI,
             const URIParams& documentURI,
             const bool& isInBrowserElement,
             const uint32_t& appId,
             const bool& stickDocument);
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -318,19 +318,19 @@ TabParent::AllocPDocumentRenderer(const 
 bool
 TabParent::DeallocPDocumentRenderer(PDocumentRendererParent* actor)
 {
     delete actor;
     return true;
 }
 
 PContentPermissionRequestParent*
-TabParent::AllocPContentPermissionRequest(const nsCString& type, const IPC::Principal& principal)
+TabParent::AllocPContentPermissionRequest(const nsCString& type, const nsCString& access, const IPC::Principal& principal)
 {
-  return new ContentPermissionRequestParent(type, mFrameElement, principal);
+  return new ContentPermissionRequestParent(type, access, mFrameElement, principal);
 }
 
 bool
 TabParent::DeallocPContentPermissionRequest(PContentPermissionRequestParent* actor)
 {
   delete actor;
   return true;
 }
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -179,17 +179,17 @@ public:
     virtual PDocumentRendererParent*
     AllocPDocumentRenderer(const nsRect& documentRect, const gfxMatrix& transform,
                            const nsString& bgcolor,
                            const uint32_t& renderFlags, const bool& flushLayout,
                            const nsIntSize& renderSize);
     virtual bool DeallocPDocumentRenderer(PDocumentRendererParent* actor);
 
     virtual PContentPermissionRequestParent*
-    AllocPContentPermissionRequest(const nsCString& aType, const IPC::Principal& aPrincipal);
+    AllocPContentPermissionRequest(const nsCString& aType, const nsCString& aAccess, const IPC::Principal& aPrincipal);
     virtual bool DeallocPContentPermissionRequest(PContentPermissionRequestParent* actor);
 
     virtual POfflineCacheUpdateParent* AllocPOfflineCacheUpdate(
             const URIParams& aManifestURI,
             const URIParams& aDocumentURI,
             const bool& isInBrowserElement,
             const uint32_t& appId,
             const bool& stickDocument);
--- a/dom/locales/en-US/chrome/charsetTitles.properties
+++ b/dom/locales/en-US/chrome/charsetTitles.properties
@@ -38,17 +38,16 @@ big5.title = Chinese Traditional (Big5)
 big5-hkscs.title = Chinese Traditional (Big5-HKSCS)
 x-euc-tw.title = Chinese Traditional (EUC-TW)
 gb2312.title = Chinese Simplified (GB2312)
 hz-gb-2312.title = Chinese Simplified (HZ)
 gbk.title = Chinese Simplified (GBK)
 iso-2022-cn.title = Chinese Simplified (ISO-2022-CN)
 euc-kr.title = Korean (EUC-KR)
 x-johab.title = Korean (JOHAB)
-x-windows-949.title = Korean (UHC)
 iso-2022-kr.title = Korean (ISO-2022-KR)
 utf-7.title = Unicode (UTF-7)
 utf-8.title = Unicode (UTF-8)
 utf-16.title = Unicode (UTF-16)
 utf-16le.title = Unicode (UTF-16LE)
 utf-16be.title = Unicode (UTF-16BE)
 iso-8859-5.title = Cyrillic (ISO-8859-5)
 iso-ir-111.title = Cyrillic (ISO-IR-111)
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -224,57 +224,55 @@ MediaDevice::GetSource()
  * one call, to simplify handling of constraints.
  */
 class GetUserMediaStreamRunnable : public nsRunnable
 {
 public:
   GetUserMediaStreamRunnable(
     already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
     already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
-    StreamListeners* aListeners,
     uint64_t aWindowID,
     MediaEngineSource* aAudioSource,
     MediaEngineSource* aVideoSource)
     : mSuccess(aSuccess)
     , mError(aError)
     , mAudioSource(aAudioSource)
     , mVideoSource(aVideoSource)
-    , mListeners(aListeners)
     , mWindowID(aWindowID) {}
 
   ~GetUserMediaStreamRunnable() {}
 
   NS_IMETHOD
   Run()
   {
     NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
+    // We're on main-thread, and the windowlist can only
+    // be invalidated from the main-thread (see OnNavigation)
+    StreamListeners* listeners = MediaManager::Get()->GetWindowListeners(mWindowID);
+    if (!listeners) {
+      // This window is no longer live.
+      return NS_OK;
+    }
+
     // Create a media stream.
     nsRefPtr<nsDOMLocalMediaStream> stream;
     uint32_t hints = (mAudioSource ? nsDOMMediaStream::HINT_CONTENTS_AUDIO : 0);
     hints |= (mVideoSource ? nsDOMMediaStream::HINT_CONTENTS_VIDEO : 0);
 
     stream = nsDOMLocalMediaStream::CreateSourceStream(hints);
+    if (!stream) {
+      nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
+      LOG(("Returning error for getUserMedia() - no stream"));
+      error->OnError(NS_LITERAL_STRING("NO_STREAM"));
+      return NS_OK;
+    }
 
     nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
       (nsGlobalWindow::GetInnerWindowWithId(mWindowID));
-    {
-      if (!stream) {
-        if (!(MediaManager::Get()->IsWindowStillActive(mWindowID))) {
-          return NS_OK;
-        }
-        // This is safe since we're on main-thread, and the windowlist can only
-        // be invalidated from the main-thread (see OnNavigation)
-        nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
-        LOG(("Returning error for getUserMedia() - no stream"));
-        error->OnError(NS_LITERAL_STRING("NO_STREAM"));
-        return NS_OK;
-      }
-    }
-
     if (window && window->GetExtantDoc()) {
       stream->CombineWithPrincipal(window->GetExtantDoc()->NodePrincipal());
     }
 
     // Ensure there's a thread for gum to proxy to off main thread
     nsIThread *mediaThread = MediaManager::GetThread();
 
     // Add our listener. We'll call Start() on the source when get a callback
@@ -282,17 +280,17 @@ public:
     // when the page is invalidated (on navigation or close).
     GetUserMediaCallbackMediaStreamListener* listener =
       new GetUserMediaCallbackMediaStreamListener(mediaThread, stream,
                                                   mAudioSource,
                                                   mVideoSource);
     stream->GetStream()->AddListener(listener);
 
     // No need for locking because we always do this in the main thread.
-    mListeners->AppendElement(listener);
+    listeners->AppendElement(listener);
 
     // Dispatch to the media thread to ask it to start the sources,
     // because that can take a while
     nsRefPtr<MediaOperationRunnable> runnable(
       new MediaOperationRunnable(MEDIA_START, stream,
                                  mAudioSource, mVideoSource));
     mediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
 
@@ -311,17 +309,16 @@ public:
     return NS_OK;
   }
 
 private:
   already_AddRefed<nsIDOMGetUserMediaSuccessCallback> mSuccess;
   already_AddRefed<nsIDOMGetUserMediaErrorCallback> mError;
   nsRefPtr<MediaEngineSource> mAudioSource;
   nsRefPtr<MediaEngineSource> mVideoSource;
-  StreamListeners* mListeners;
   uint64_t mWindowID;
 };
 
 /**
  * Runs on a seperate thread and is responsible for enumerating devices.
  * Depending on whether a picture or stream was asked for, either
  * ProcessGetUserMedia or ProcessGetUserMediaSnapshot is called, and the results
  * are sent back to the DOM.
@@ -334,64 +331,60 @@ class GetUserMediaRunnable : public nsRu
 public:
   /**
    * The caller can choose to provide a MediaDevice as the last argument,
    * if one is not provided, a default device is automatically chosen.
    */
   GetUserMediaRunnable(bool aAudio, bool aVideo, bool aPicture,
     already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
     already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
-    StreamListeners* aListeners, uint64_t aWindowID,
-    MediaDevice* aAudioDevice, MediaDevice* aVideoDevice)
+    uint64_t aWindowID, MediaDevice* aAudioDevice, MediaDevice* aVideoDevice)
     : mAudio(aAudio)
     , mVideo(aVideo)
     , mPicture(aPicture)
     , mSuccess(aSuccess)
     , mError(aError)
-    , mListeners(aListeners)
     , mWindowID(aWindowID)
     , mDeviceChosen(true)
     , mBackendChosen(false)
     {
       if (mAudio) {
         mAudioDevice = aAudioDevice;
       }
       if (mVideo) {
         mVideoDevice = aVideoDevice;
       }
     }
 
   GetUserMediaRunnable(bool aAudio, bool aVideo, bool aPicture,
     already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
     already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
-    StreamListeners* aListeners, uint64_t aWindowID)
+    uint64_t aWindowID)
     : mAudio(aAudio)
     , mVideo(aVideo)
     , mPicture(aPicture)
     , mSuccess(aSuccess)
     , mError(aError)
-    , mListeners(aListeners)
     , mWindowID(aWindowID)
     , mDeviceChosen(false)
     , mBackendChosen(false) {}
 
   /**
    * The caller can also choose to provide their own backend instead of
    * using the one provided by MediaManager::GetBackend.
    */
   GetUserMediaRunnable(bool aAudio, bool aVideo,
     already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
     already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
-    StreamListeners* aListeners, uint64_t aWindowID, MediaEngine* aBackend)
+    uint64_t aWindowID, MediaEngine* aBackend)
     : mAudio(aAudio)
     , mVideo(aVideo)
     , mPicture(false)
     , mSuccess(aSuccess)
     , mError(aError)
-    , mListeners(aListeners)
     , mWindowID(aWindowID)
     , mDeviceChosen(false)
     , mBackendChosen(true)
     , mBackend(aBackend) {}
 
   ~GetUserMediaRunnable() {
     if (mBackendChosen) {
       delete mBackend;
@@ -566,17 +559,17 @@ public:
         NS_DispatchToMainThread(new ErrorCallbackRunnable(
           mSuccess, mError, NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID
                                                           ));
         return;
       }
     }
 
     NS_DispatchToMainThread(new GetUserMediaStreamRunnable(
-      mSuccess, mError, mListeners, mWindowID, aAudioSource, aVideoSource
+      mSuccess, mError, mWindowID, aAudioSource, aVideoSource
     ));
     return;
   }
 
   /**
    * Allocates a video device, takes a snapshot and returns a DOMFile via
    * a SuccessRunnable or an error via the ErrorRunnable. Off the main thread.
    */
@@ -606,17 +599,16 @@ public:
 
 private:
   bool mAudio;
   bool mVideo;
   bool mPicture;
 
   already_AddRefed<nsIDOMGetUserMediaSuccessCallback> mSuccess;
   already_AddRefed<nsIDOMGetUserMediaErrorCallback> mError;
-  StreamListeners* mListeners;
   uint64_t mWindowID;
   nsRefPtr<MediaDevice> mAudioDevice;
   nsRefPtr<MediaDevice> mVideoDevice;
 
   bool mDeviceChosen;
   bool mBackendChosen;
 
   MediaEngine* mBackend;
@@ -819,32 +811,30 @@ MediaManager::GetUserMedia(bool aPrivile
    * selected by the user via the UI, or was provided by privileged code
    * via the device: attribute via nsIMediaStreamOptions.
    *
    * If a fake stream was requested, we force the use of the default backend.
    */
   if (fake) {
     // Fake stream from default backend.
     gUMRunnable = new GetUserMediaRunnable(
-      audio, video, onSuccess.forget(), onError.forget(), listeners,
-      windowID, new MediaEngineDefault()
+      audio, video, onSuccess.forget(), onError.forget(), windowID,
+      new MediaEngineDefault()
                                            );
   } else if (audiodevice || videodevice) {
     // Stream from provided device.
     gUMRunnable = new GetUserMediaRunnable(
-      audio, video, picture, onSuccess.forget(), onError.forget(), listeners,
-      windowID,
+      audio, video, picture, onSuccess.forget(), onError.forget(), windowID,
       static_cast<MediaDevice*>(audiodevice.get()),
       static_cast<MediaDevice*>(videodevice.get())
                                            );
   } else {
     // Stream from default device from WebRTC backend.
     gUMRunnable = new GetUserMediaRunnable(
-      audio, video, picture, onSuccess.forget(), onError.forget(), listeners,
-      windowID
+      audio, video, picture, onSuccess.forget(), onError.forget(), windowID
                                            );
   }
 
 #ifdef ANDROID
   if (picture) {
     // ShowFilePickerForMimeType() must run on the Main Thread! (on Android)
     NS_DispatchToMainThread(gUMRunnable);
   }
@@ -943,17 +933,17 @@ MediaManager::OnNavigation(uint64_t aWin
 {
   NS_ASSERTION(NS_IsMainThread(), "OnNavigation called off main thread");
 
   // Invalidate this window. The runnables check this value before making
   // a call to content.
 
   // This is safe since we're on main-thread, and the windowlist can only
   // be added to from the main-thread (see OnNavigation)
-  StreamListeners* listeners = GetActiveWindows()->Get(aWindowID);
+  StreamListeners* listeners = GetWindowListeners(aWindowID);
   if (!listeners) {
     return;
   }
 
   uint32_t length = listeners->Length();
   for (uint32_t i = 0; i < length; i++) {
     nsRefPtr<GetUserMediaCallbackMediaStreamListener> listener =
       listeners->ElementAt(i);
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -289,20 +289,23 @@ public:
   static nsIThread* GetThread() {
     return Get()->mMediaThread;
   }
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   MediaEngine* GetBackend();
-  bool IsWindowStillActive(uint64_t aWindowId) {
+  StreamListeners *GetWindowListeners(uint64_t aWindowId) {
     NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
 
-    return !!mActiveWindows.Get(aWindowId);
+    return mActiveWindows.Get(aWindowId);
+  }
+  bool IsWindowStillActive(uint64_t aWindowId) {
+    return !!GetWindowListeners(aWindowId);
   }
 
   nsresult GetUserMedia(bool aPrivileged, nsPIDOMWindow* aWindow,
     nsIMediaStreamOptions* aParams,
     nsIDOMGetUserMediaSuccessCallback* onSuccess,
     nsIDOMGetUserMediaErrorCallback* onError);
   nsresult GetUserMediaDevices(nsPIDOMWindow* aWindow,
     nsIGetUserMediaDevicesSuccessCallback* onSuccess,
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -959,17 +959,17 @@ static const moz2javaCharset charsets[] 
     {"windows-1251",    "Cp1251"},
     {"windows-1253",    "Cp1253"},
     {"windows-1254",    "Cp1254"},
     {"windows-1255",    "Cp1255"},
     {"windows-1256",    "Cp1256"},
     {"windows-1257",    "Cp1257"},
     {"windows-1258",    "Cp1258"},
     {"EUC-JP",          "EUC_JP"},
-    {"EUC-KR",          "EUC_KR"},
+    {"EUC-KR",          "MS949"},
     {"x-euc-tw",        "EUC_TW"},
     {"gb18030",         "GB18030"},
     {"gbk",             "GBK"},
     {"ISO-2022-JP",     "ISO2022JP"},
     {"ISO-2022-KR",     "ISO2022KR"},
     {"ISO-8859-2",      "ISO8859_2"},
     {"ISO-8859-3",      "ISO8859_3"},
     {"ISO-8859-4",      "ISO8859_4"},
@@ -977,17 +977,16 @@ static const moz2javaCharset charsets[] 
     {"ISO-8859-6",      "ISO8859_6"},
     {"ISO-8859-7",      "ISO8859_7"},
     {"ISO-8859-8",      "ISO8859_8"},
     {"ISO-8859-9",      "ISO8859_9"},
     {"ISO-8859-13",     "ISO8859_13"},
     {"x-johab",         "Johab"},
     {"KOI8-R",          "KOI8_R"},
     {"TIS-620",         "MS874"},
-    {"x-windows-949",   "MS949"},
     {"x-mac-arabic",    "MacArabic"},
     {"x-mac-croatian",  "MacCroatia"},
     {"x-mac-cyrillic",  "MacCyrillic"},
     {"x-mac-greek",     "MacGreek"},
     {"x-mac-hebrew",    "MacHebrew"},
     {"x-mac-icelandic", "MacIceland"},
     {"macintosh",       "MacRoman"},
     {"x-mac-romanian",  "MacRomania"},
--- a/dom/sms/tests/marionette/manifest.ini
+++ b/dom/sms/tests/marionette/manifest.ini
@@ -6,8 +6,11 @@ qemu = true
 ;[test_between_emulators.py]
 [test_incoming.js]
 [test_outgoing.js]
 [test_message_classes.js]
 [test_incoming_delete.js]
 [test_outgoing_delete.js]
 [test_getmessage.js]
 [test_getmessage_notfound.js]
+[test_filter_read.js]
+[test_filter_unread.js]
+[test_number_of_messages.js]
new file mode 100644
--- /dev/null
+++ b/dom/sms/tests/marionette/test_filter_read.js
@@ -0,0 +1,229 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 20000;
+
+SpecialPowers.addPermission("sms", true, document);
+SpecialPowers.setBoolPref("dom.sms.enabled", true);
+
+let sms = window.navigator.mozSms;
+let numberMsgs = 10;
+let smsList = new Array();
+
+function verifyInitialState() {
+  log("Verifying initial state.");
+  ok(sms, "mozSms");
+  // Ensure test is starting clean with no existing sms messages
+  deleteAllMsgs(simulateIncomingSms);
+}
+
+function deleteAllMsgs(nextFunction) {
+  let msgList = new Array();
+  let filter = new MozSmsFilter;
+
+  let request = sms.getMessages(filter, false);
+  ok(request instanceof MozSmsRequest,
+      "request is instanceof " + request.constructor);
+
+  request.onsuccess = function(event) {
+    ok(event.target.result, "smsrequest event.target.result");
+    cursor = event.target.result;
+    // Check if message was found
+    if (cursor.message) {
+      msgList.push(cursor.message.id);
+      // Now get next message in the list
+      cursor.continue();
+    } else {
+      // No (more) messages found
+      if (msgList.length) {
+        log("Found " + msgList.length + " SMS messages to delete.");
+        deleteMsgs(msgList, nextFunction);
+      } else {
+        log("No SMS messages found.");
+        nextFunction();
+      }
+    }
+  };
+
+  request.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    log("sms.getMessages error: " + event.target.error.name);
+    ok(false,"Could not get SMS messages");
+    cleanUp();
+  };
+}
+
+function deleteMsgs(msgList, nextFunction) {
+  let smsId = msgList.shift();
+
+  log("Deleting SMS (id: " + smsId + ").");
+  let request = sms.delete(smsId);
+  ok(request instanceof MozSmsRequest,
+      "request is instanceof " + request.constructor);
+
+  request.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    if (event.target.result) {
+      // Message deleted, continue until none are left
+      if (msgList.length) {
+        deleteMsgs(msgList, nextFunction);
+      } else {
+        log("Finished deleting SMS messages.");
+        nextFunction();
+      }
+    } else {
+      log("SMS delete failed.");
+      ok(false,"sms.delete request returned false");
+      cleanUp();
+    }
+  };
+
+  request.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    ok(false, "sms.delete request returned unexpected error: "
+        + event.target.error.name );
+    cleanUp();
+  };
+}
+
+function simulateIncomingSms() {
+  let text = "Incoming SMS number " + (smsList.length + 1);
+  let remoteNumber = "5552229797";
+
+  log("Simulating incoming SMS number " + (smsList.length + 1) + " of "
+      + numberMsgs + ".");
+
+  // Simulate incoming sms sent from remoteNumber to our emulator
+  rcvdEmulatorCallback = false;
+  runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
+    is(result[0], "OK", "emulator callback");
+    rcvdEmulatorCallback = true;
+  });
+}
+
+// Callback for incoming sms
+sms.onreceived = function onreceived(event) {
+  log("Received 'onreceived' sms event.");
+  let incomingSms = event.message;
+  log("Received SMS (id: " + incomingSms.id + ").");
+
+  // Add newly received message to array of received msgs
+  smsList.push(incomingSms);
+
+  // Wait for emulator to catch up before continuing
+  waitFor(nextRep,function() {
+    return(rcvdEmulatorCallback);
+  });
+};
+
+function nextRep() {
+  if (smsList.length < numberMsgs) {
+    simulateIncomingSms();
+  } else {
+    // Marking all messages except first as read
+    // Can remove first one from smsList array
+    smsList.shift();
+    markMsgRead(smsList.slice(0));
+  }
+}
+
+function markMsgRead(smsMsgs) {  
+  nextSms = smsMsgs.shift();
+  log("Marking SMS (id: " + nextSms.id + ") as read.");
+  let request = sms.markMessageRead(nextSms.id, true);
+  ok(request instanceof MozSmsRequest,
+      "request is instanceof " + request.constructor);
+
+  request.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    if (event.target.result) {
+      // Message marked as read, continue until none are left
+      if (smsMsgs.length) {
+        markMsgRead(smsMsgs);
+      } else {
+        // Done, now test the filter
+        getMsgs();
+      }
+    } else {
+      log("SMS markMessageRead failed.");
+      ok(false,"sms.markMessageRead request returned false");
+      cleanUp();
+    }
+  };
+
+  request.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    ok(false, "sms.markMessageRead request returned unexpected error: "
+        + event.target.error.name );
+    cleanUp();
+  };
+}
+
+function getMsgs() {
+  var filter = new MozSmsFilter();
+  let foundSmsList = new Array();
+
+  // Set filter for read messages
+  filter.read = true;
+
+  log("Getting the read SMS messages.");
+  let request = sms.getMessages(filter, false);
+  ok(request instanceof MozSmsRequest,
+      "request is instanceof " + request.constructor);
+
+  request.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    ok(event.target.result, "smsrequest event.target.result");
+    cursor = event.target.result;
+
+    if (cursor.message) {
+      // Another message found
+      log("Got SMS (id: " + cursor.message.id + ").");
+      // Store found message
+      foundSmsList.push(cursor.message);
+      // Now get next message in the list
+      cursor.continue();
+    } else {
+      // No more messages; ensure correct number found
+      if (foundSmsList.length == smsList.length) {
+        log("SMS getMessages returned " + foundSmsList.length +
+            " messages as expected.");
+        verifyFoundMsgs(foundSmsList);
+      } else {
+        log("SMS getMessages returned " + foundSmsList.length +
+            " messages, but expected " + smsList.length + ".");
+        ok(false, "Incorrect number of messages returned by sms.getMessages");
+        deleteAllMsgs(cleanUp);
+      }
+    }
+  };
+
+  request.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    log("sms.getMessages error: " + event.target.error.name);
+    ok(false,"Could not get SMS messages");
+    cleanUp();
+  };
+}
+
+function verifyFoundMsgs(foundSmsList) {
+  for (var x = 0; x < foundSmsList.length; x++) {
+    is(foundSmsList[x].id, smsList[x].id, "id");
+    is(foundSmsList[x].read, true, "read");
+  }
+  deleteAllMsgs(cleanUp);
+}
+
+function cleanUp() {
+  sms.onreceived = null;
+  SpecialPowers.removePermission("sms", document);
+  SpecialPowers.clearUserPref("dom.sms.enabled");
+  finish();
+}
+
+// Start the test
+verifyInitialState();
new file mode 100644
--- /dev/null
+++ b/dom/sms/tests/marionette/test_filter_unread.js
@@ -0,0 +1,223 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 20000;
+
+SpecialPowers.addPermission("sms", true, document);
+SpecialPowers.setBoolPref("dom.sms.enabled", true);
+
+let sms = window.navigator.mozSms;
+let numberMsgs = 10;
+let smsList = new Array();
+
+function verifyInitialState() {
+  log("Verifying initial state.");
+  ok(sms, "mozSms");
+  // Ensure test is starting clean with no existing sms messages
+  deleteAllMsgs(simulateIncomingSms);
+}
+
+function deleteAllMsgs(nextFunction) {
+  let msgList = new Array();
+  let filter = new MozSmsFilter;
+
+  let request = sms.getMessages(filter, false);
+  ok(request instanceof MozSmsRequest,
+      "request is instanceof " + request.constructor);
+
+  request.onsuccess = function(event) {
+    ok(event.target.result, "smsrequest event.target.result");
+    cursor = event.target.result;
+    // Check if message was found
+    if (cursor.message) {
+      msgList.push(cursor.message.id);
+      // Now get next message in the list
+      cursor.continue();
+    } else {
+      // No (more) messages found
+      if (msgList.length) {
+        log("Found " + msgList.length + " SMS messages to delete.");
+        deleteMsgs(msgList, nextFunction);
+      } else {
+        log("No SMS messages found.");
+        nextFunction();
+      }
+    }
+  };
+
+  request.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    log("sms.getMessages error: " + event.target.error.name);
+    ok(false,"Could not get SMS messages");
+    cleanUp();
+  };
+}
+
+function deleteMsgs(msgList, nextFunction) {
+  let smsId = msgList.shift();
+
+  log("Deleting SMS (id: " + smsId + ").");
+  let request = sms.delete(smsId);
+  ok(request instanceof MozSmsRequest,
+      "request is instanceof " + request.constructor);
+
+  request.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    if (event.target.result) {
+      // Message deleted, continue until none are left
+      if (msgList.length) {
+        deleteMsgs(msgList, nextFunction);
+      } else {
+        log("Finished deleting SMS messages.");
+        nextFunction();
+      }
+    } else {
+      log("SMS delete failed.");
+      ok(false,"sms.delete request returned false");
+      cleanUp();
+    }
+  };
+
+  request.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    ok(false, "sms.delete request returned unexpected error: "
+        + event.target.error.name );
+    cleanUp();
+  };
+}
+
+function simulateIncomingSms() {
+  let text = "Incoming SMS number " + (smsList.length + 1);
+  let remoteNumber = "5552229797";
+
+  log("Simulating incoming SMS number " + (smsList.length + 1) + " of "
+      + numberMsgs + ".");
+
+  // Simulate incoming sms sent from remoteNumber to our emulator
+  rcvdEmulatorCallback = false;
+  runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
+    is(result[0], "OK", "emulator callback");
+    rcvdEmulatorCallback = true;
+  });
+}
+
+// Callback for incoming sms
+sms.onreceived = function onreceived(event) {
+  log("Received 'onreceived' sms event.");
+  let incomingSms = event.message;
+  log("Received SMS (id: " + incomingSms.id + ").");
+
+  // Add newly received message to array of received msgs
+  smsList.push(incomingSms);
+
+  // Wait for emulator to catch up before continuing
+  waitFor(nextRep,function() {
+    return(rcvdEmulatorCallback);
+  });
+};
+
+function nextRep() {
+  if (smsList.length < numberMsgs) {
+    simulateIncomingSms();
+  } else {
+    markMsgRead();
+  }
+}
+
+function markMsgRead() {
+  // Mark first message read so not all will be found by filter
+  log("Marking SMS (id: " + smsList[0].id + ") as read.");
+  let request = sms.markMessageRead(smsList[0].id, true);
+  ok(request instanceof MozSmsRequest,
+      "request is instanceof " + request.constructor);
+
+  request.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    if (event.target.result) {
+      // First message was marked read, so remove from expected smsList
+      smsList.shift();
+      // Now test the filter
+      getMsgs();
+    } else {
+      log("SMS markMessageRead failed.");
+      ok(false,"sms.markMessageRead request returned false");
+      cleanUp();
+    }
+  };
+
+  request.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    ok(false, "sms.markMessageRead request returned unexpected error: "
+        + event.target.error.name );
+    cleanUp();
+  };
+}
+
+function getMsgs() {
+  var filter = new MozSmsFilter();
+  let foundSmsList = new Array();
+
+  // Set filter for read messages
+  filter.read = false;
+
+  log("Getting the unread SMS messages.");
+  let request = sms.getMessages(filter, false);
+  ok(request instanceof MozSmsRequest,
+      "request is instanceof " + request.constructor);
+
+  request.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    ok(event.target.result, "smsrequest event.target.result");
+    cursor = event.target.result;
+
+    if (cursor.message) {
+      // Another message found
+      log("Got SMS (id: " + cursor.message.id + ").");
+      // Store found message
+      foundSmsList.push(cursor.message);
+      // Now get next message in the list
+      cursor.continue();
+    } else {
+      // No more messages; ensure correct number found
+      if (foundSmsList.length == smsList.length) {
+        log("SMS getMessages returned " + foundSmsList.length +
+            " messages as expected.");
+        verifyFoundMsgs(foundSmsList);
+      } else {
+        log("SMS getMessages returned " + foundSmsList.length +
+            " messages, but expected " + smsList.length + ".");
+        ok(false, "Incorrect number of messages returned by sms.getMessages");
+        deleteAllMsgs(cleanUp);
+      }
+    }
+  };
+
+  request.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    log("sms.getMessages error: " + event.target.error.name);
+    ok(false,"Could not get SMS messages");
+    cleanUp();
+  };
+}
+
+function verifyFoundMsgs(foundSmsList) {
+  for (var x = 0; x < foundSmsList.length; x++) {
+    is(foundSmsList[x].id, smsList[x].id, "id");
+    is(foundSmsList[x].read, false, "read");
+  }
+  deleteAllMsgs(cleanUp);
+}
+
+function cleanUp() {
+  sms.onreceived = null;
+  SpecialPowers.removePermission("sms", document);
+  SpecialPowers.clearUserPref("dom.sms.enabled");
+  finish();
+}
+
+// Start the test
+verifyInitialState();
new file mode 100644
--- /dev/null
+++ b/dom/sms/tests/marionette/test_number_of_messages.js
@@ -0,0 +1,76 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 10000;
+
+SpecialPowers.addPermission("sms", true, document);
+SpecialPowers.setBoolPref("dom.sms.enabled", true);
+
+let sms = window.navigator.mozSms;
+
+// Specified here: https://developer.mozilla.org/en-US/docs/DOM/SmsManager
+let maxCharsPerSms = 160;
+
+function verifyInitialState() {
+  log("Verifying initial state.");
+  ok(sms, "mozSms");
+  // Ensure test is starting clean with no existing SMS messages
+  startTest();
+}
+
+function startTest() {
+  // Build test data strings
+  let testData = ["", "a",
+                  buildString("b", maxCharsPerSms / 2),
+                  buildString("c", maxCharsPerSms - 1),
+                  buildString("d", maxCharsPerSms),
+                  buildString("e", maxCharsPerSms + 1),
+                  buildString("f", maxCharsPerSms * 1.5),
+                  buildString("g", maxCharsPerSms * 10.5)];
+
+  // Test with each data string
+  testData.forEach(function(text){ testGetNumberOfMsgs(text); });
+
+  // We're done
+  cleanUp();
+}
+
+function buildString(char, numChars) {
+  // Build string that contains the specified character repeated x times
+  let string = new Array(numChars + 1).join(char);
+  return string;
+}
+
+function testGetNumberOfMsgs(text) {
+  // Test that getNumberOfMessagesForText returns expected value for given txt
+  log("getNumberOfMessagesForText length " + text.length + ".");
+
+  if (text.length) {
+    if (text.length > maxCharsPerSms) {
+      expNumSms = Math.ceil(text.length / maxCharsPerSms);
+    } else {
+      expNumSms = 1;
+    }
+  } else {
+    expNumSms = 0;
+  }
+
+  numMultiPartSms = sms.getNumberOfMessagesForText(text);
+
+  if (numMultiPartSms == expNumSms) {
+    log("Returned " + expNumSms + " as expected.");
+    ok(true, "getNumberOfMessagesForText returned expected value");
+  } else {
+    log("Returned " + numMultiPartSms + " but expected " + expNumSms + ".");
+    ok(false, "getNumberOfMessagesForText returned unexpected value");
+  }
+}
+
+function cleanUp() {
+  SpecialPowers.removePermission("sms", document);
+  SpecialPowers.clearUserPref("dom.sms.enabled");
+  finish();
+}
+
+// Start the test
+verifyInitialState();
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -349,16 +349,23 @@ nsGeolocationRequest::GetPrincipal(nsIPr
 NS_IMETHODIMP
 nsGeolocationRequest::GetType(nsACString & aType)
 {
   aType = "geolocation";
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsGeolocationRequest::GetAccess(nsACString & aAccess)
+{
+  aAccess = "unused";
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsGeolocationRequest::GetWindow(nsIDOMWindow * *aRequestingWindow)
 {
   NS_ENSURE_ARG_POINTER(aRequestingWindow);
 
   nsCOMPtr<nsIDOMWindow> window = do_QueryReferent(mLocator->GetOwner());
   window.forget(aRequestingWindow);
 
   return NS_OK;
@@ -741,21 +748,20 @@ nsGeolocationService::HandleMozsettingVa
       Update(nullptr);
       mLastPosition = nullptr;
       sGeoEnabled = false;
     } else {
       sGeoEnabled = true;
     }
 
     if (sGeoInitPending) {
+      sGeoInitPending = false;
       for (uint32_t i = 0, length = mGeolocators.Length(); i < length; ++i) {
         mGeolocators[i]->ServiceReady();
       }
-
-      sGeoInitPending = false;
     }
 }
 
 NS_IMETHODIMP
 nsGeolocationService::Observe(nsISupports* aSubject,
                               const char* aTopic,
                               const PRUnichar* aData)
 {
@@ -1407,19 +1413,20 @@ nsGeolocation::RegisterRequestWithPrompt
     TabChild* child = GetTabChildFrom(window->GetDocShell());
     if (!child) {
       return false;
     }
 
     // Retain a reference so the object isn't deleted without IPDL's knowledge.
     // Corresponding release occurs in DeallocPContentPermissionRequest.
     request->AddRef();
-
-    nsCString type = NS_LITERAL_CSTRING("geolocation");
-    child->SendPContentPermissionRequestConstructor(request, type, IPC::Principal(mPrincipal));
+    child->SendPContentPermissionRequestConstructor(request,
+                                                    NS_LITERAL_CSTRING("geolocation"),
+                                                    NS_LITERAL_CSTRING("unused"),
+                                                    IPC::Principal(mPrincipal));
 
     request->Sendprompt();
     return true;
   }
 
   nsCOMPtr<nsIRunnable> ev  = new RequestPromptEvent(request);
   NS_DispatchToMainThread(ev);
   return true;
--- a/dom/src/notification/nsDesktopNotification.cpp
+++ b/dom/src/notification/nsDesktopNotification.cpp
@@ -101,18 +101,20 @@ nsDOMDesktopNotification::nsDOMDesktopNo
     // because owner implements nsITabChild, we can assume that it is
     // the one and only TabChild for this docshell.
     TabChild* child = GetTabChildFrom(GetOwner()->GetDocShell());
 
     // Retain a reference so the object isn't deleted without IPDL's knowledge.
     // Corresponding release occurs in DeallocPContentPermissionRequest.
     nsRefPtr<nsDesktopNotificationRequest> copy = request;
 
-    nsCString type = NS_LITERAL_CSTRING("desktop-notification");
-    child->SendPContentPermissionRequestConstructor(copy.forget().get(), type, IPC::Principal(mPrincipal));
+    child->SendPContentPermissionRequestConstructor(request,
+                                                    NS_LITERAL_CSTRING("desktop-notification"),
+                                                    NS_LITERAL_CSTRING("unused"),
+                                                    IPC::Principal(mPrincipal));
 
     request->Sendprompt();
     return;
   }
 
   // otherwise, dispatch it
   NS_DispatchToMainThread(request);
 
@@ -266,8 +268,14 @@ nsDesktopNotificationRequest::Allow()
 
 NS_IMETHODIMP
 nsDesktopNotificationRequest::GetType(nsACString & aType)
 {
   aType = "desktop-notification";
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDesktopNotificationRequest::GetAccess(nsACString & aAccess)
+{
+  aAccess = "unused";
+  return NS_OK;
+}
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -276,16 +276,18 @@ function RadioInterfaceLayer() {
   Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
   Services.obs.addObserver(this, kSysMsgListenerReadyObserverTopic, false);
   Services.obs.addObserver(this, kSysClockChangeObserverTopic, false);
 
   this._sentSmsEnvelopes = {};
 
   this.portAddressedSmsApps = {};
   this.portAddressedSmsApps[WAP.WDP_PORT_PUSH] = this.handleSmsWdpPortPush.bind(this);
+
+  this._targetMessageQueue = [];
 }
 RadioInterfaceLayer.prototype = {
 
   classID:   RADIOINTERFACELAYER_CID,
   classInfo: XPCOMUtils.generateCI({classID: RADIOINTERFACELAYER_CID,
                                     classDescription: "RadioInterfaceLayer",
                                     interfaces: [Ci.nsIWorkerHolder,
                                                  Ci.nsIRadioInterfaceLayer]}),
@@ -652,16 +654,22 @@ RadioInterfaceLayer.prototype = {
     let index = targets.indexOf(target);
     if (index != -1) {
       targets.splice(index, 1);
       debug("Unregistered " + permission + " target: " + target);
     }
   },
 
   _sendTargetMessage: function _sendTargetMessage(permission, message, options) {
+
+    if (!this._sysMsgListenerReady) {
+      this._enqueueTargetMessage(permission, message, options);
+      return;
+    }
+
     let targets = this._messageManagerByPermission[permission];
     if (!targets) {
       return;
     }
 
     for each (let target in targets) {
       target.sendAsyncMessage(message, options);
     }
@@ -919,16 +927,46 @@ RadioInterfaceLayer.prototype = {
       return;
     }
     this.rilContext.radioState = newState;
     //TODO Should we notify this change as a card state change?
 
     this._ensureRadioState();
   },
 
+  _enqueueTargetMessage: function _enqueueTargetMessage(permission, message, options) {
+    let msg = { permission : permission,
+                message : message,
+                options : options };
+    // Remove previous queued message of same message type, only one message
+    // per message type is allowed in queue.
+    let messageQueue = this._targetMessageQueue;
+    for(let i = 0; i < messageQueue.length; i++) {
+      if (messageQueue[i].message === message) {
+        messageQueue.splice(i, 1);
+        break;
+      }
+    }
+
+    messageQueue.push(msg);
+  },
+
+  _resendQueuedTargetMessage: function _resendQueuedTargetMessage() {
+    // Here uses this._sendTargetMessage() to resend message, which will
+    // enqueue message if listener is not ready.
+    // So only resend after listener is ready, or it will cause infinate loop and
+    // hang the system.
+
+    // Dequeue and resend messages.
+    for each (let msg in this._targetMessageQueue) {
+      this._sendTargetMessage(msg.permission, msg.message, msg.options);
+    }
+    this._targetMessageQueue = null;
+  },
+
   _ensureRadioState: function _ensureRadioState() {
     debug("Reported radio state is " + this.rilContext.radioState +
           ", desired radio enabled state is " + this._radioEnabled);
     if (this._radioEnabled == null) {
       // We haven't read the initial value from the settings DB yet.
       // Wait for that.
       return;
     }
@@ -1485,16 +1523,17 @@ RadioInterfaceLayer.prototype = {
 
   // nsIObserver
 
   observe: function observe(subject, topic, data) {
     switch (topic) {
       case kSysMsgListenerReadyObserverTopic:
         Services.obs.removeObserver(this, kSysMsgListenerReadyObserverTopic);
         this._sysMsgListenerReady = true;
+        this._resendQueuedTargetMessage();
         this._ensureRadioState();
         break;
       case kMozSettingsChangedObserverTopic:
         let setting = JSON.parse(data);
         this.handle(setting.key, setting.value);
         break;
       case "xpcom-shutdown":
         ppmm.removeMessageListener("child-process-shutdown", this);
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -582,73 +582,118 @@ BasicBufferOGL::BeginPaint(ContentType a
   }
 
   if (destBuffer) {
     if (mTexImage && (mode != Layer::SURFACE_COMPONENT_ALPHA || mTexImageOnWhite)) {
       // BlitTextureImage depends on the FBO texture target being
       // TEXTURE_2D.  This isn't the case on some older X1600-era Radeons.
       if (mOGLLayer->OGLManager()->FBOTextureTarget() == LOCAL_GL_TEXTURE_2D) {
         nsIntRect overlap;
+
+        // The buffer looks like:
+        //  ______
+        // |1  |2 |  Where the center point is offset by mBufferRotation from the top-left corner.
+        // |___|__|
+        // |3  |4 |
+        // |___|__|
+        //
+        // This is drawn to the screen as:
+        //  ______
+        // |4  |3 |  Where the center point is { width - mBufferRotation.x, height - mBufferRotation.y } from
+        // |___|__|  from the top left corner - rotationPoint.
+        // |2  |1 |
+        // |___|__|
+        //
+
+        // The basic idea below is to take all quadrant rectangles from the src and transform them into rectangles
+        // in the destination. Unfortunately, it seems it is overly complex and could perhaps be simplified.
+
+        nsIntRect srcBufferSpaceBottomRight(mBufferRotation.x, mBufferRotation.y, mBufferRect.width - mBufferRotation.x, mBufferRect.height - mBufferRotation.y);
+        nsIntRect srcBufferSpaceTopRight(mBufferRotation.x, 0, mBufferRect.width - mBufferRotation.x, mBufferRotation.y);
+        nsIntRect srcBufferSpaceTopLeft(0, 0, mBufferRotation.x, mBufferRotation.y);
+        nsIntRect srcBufferSpaceBottomLeft(0, mBufferRotation.y, mBufferRotation.x, mBufferRect.height - mBufferRotation.y);
+
         overlap.IntersectRect(mBufferRect, destBufferRect);
 
         nsIntRect srcRect(overlap), dstRect(overlap);
         srcRect.MoveBy(- mBufferRect.TopLeft() + mBufferRotation);
-        dstRect.MoveBy(- destBufferRect.TopLeft());
-        
-        if (mBufferRotation != nsIntPoint(0, 0)) {
-          // If mBuffer is rotated, then BlitTextureImage will only be copying the bottom-right section
-          // of the buffer. We need to invalidate the remaining sections so that they get redrawn too.
-          // Alternatively we could teach BlitTextureImage to rearrange the rotated segments onto
-          // the new buffer.
-          
-          // When the rotated buffer is reorganised, the bottom-right section will be drawn in the top left.
-          // Find the point where this content ends.
-          nsIntPoint rotationPoint(mBufferRect.x + mBufferRect.width - mBufferRotation.x, 
-                                   mBufferRect.y + mBufferRect.height - mBufferRotation.y);
+
+        nsIntRect srcRectDrawTopRight(srcRect);
+        nsIntRect srcRectDrawTopLeft(srcRect);
+        nsIntRect srcRectDrawBottomLeft(srcRect);
+        // transform into the different quadrants
+        srcRectDrawTopRight  .MoveBy(-nsIntPoint(0, mBufferRect.height));
+        srcRectDrawTopLeft   .MoveBy(-nsIntPoint(mBufferRect.width, mBufferRect.height));
+        srcRectDrawBottomLeft.MoveBy(-nsIntPoint(mBufferRect.width, 0));
+
+        // Intersect with the quadrant
+        srcRect               = srcRect              .Intersect(srcBufferSpaceBottomRight);
+        srcRectDrawTopRight   = srcRectDrawTopRight  .Intersect(srcBufferSpaceTopRight);
+        srcRectDrawTopLeft    = srcRectDrawTopLeft   .Intersect(srcBufferSpaceTopLeft);
+        srcRectDrawBottomLeft = srcRectDrawBottomLeft.Intersect(srcBufferSpaceBottomLeft);
 
-          // The buffer looks like:
-          //  ______
-          // |1  |2 |  Where the center point is offset by mBufferRotation from the top-left corner.
-          // |___|__|
-          // |3  |4 |
-          // |___|__|
-          //
-          // This is drawn to the screen as:
-          //  ______
-          // |4  |3 |  Where the center point is { width - mBufferRotation.x, height - mBufferRotation.y } from
-          // |___|__|  from the top left corner - rotationPoint. Since only quadrant 4 will actually be copied, 
-          // |2  |1 |  we need to invalidate the others.
-          // |___|__|
-          //
-          // Quadrants 2 and 1
-          nsIntRect bottom(mBufferRect.x, rotationPoint.y, mBufferRect.width, mBufferRotation.y);
-          // Quadrant 3
-          nsIntRect topright(rotationPoint.x, mBufferRect.y, mBufferRotation.x, rotationPoint.y - mBufferRect.y);
+        dstRect = srcRect;
+        nsIntRect dstRectDrawTopRight(srcRectDrawTopRight);
+        nsIntRect dstRectDrawTopLeft(srcRectDrawTopLeft);
+        nsIntRect dstRectDrawBottomLeft(srcRectDrawBottomLeft);
+
+        // transform back to src buffer space
+        dstRect              .MoveBy(-mBufferRotation);
+        dstRectDrawTopRight  .MoveBy(-mBufferRotation + nsIntPoint(0, mBufferRect.height));
+        dstRectDrawTopLeft   .MoveBy(-mBufferRotation + nsIntPoint(mBufferRect.width, mBufferRect.height));
+        dstRectDrawBottomLeft.MoveBy(-mBufferRotation + nsIntPoint(mBufferRect.width, 0));
 
-          if (!bottom.IsEmpty()) {
-            nsIntRegion temp;
-            temp.And(destBufferRect, bottom);
-            result.mRegionToDraw.Or(result.mRegionToDraw, temp);
-          }
-          if (!topright.IsEmpty()) {
-            nsIntRegion temp;
-            temp.And(destBufferRect, topright);
-            result.mRegionToDraw.Or(result.mRegionToDraw, temp);
-          }
-        }
+        // transform back to draw coordinates
+        dstRect              .MoveBy(mBufferRect.TopLeft());
+        dstRectDrawTopRight  .MoveBy(mBufferRect.TopLeft());
+        dstRectDrawTopLeft   .MoveBy(mBufferRect.TopLeft());
+        dstRectDrawBottomLeft.MoveBy(mBufferRect.TopLeft());
+
+        // transform to destBuffer space
+        dstRect              .MoveBy(-destBufferRect.TopLeft());
+        dstRectDrawTopRight  .MoveBy(-destBufferRect.TopLeft());
+        dstRectDrawTopLeft   .MoveBy(-destBufferRect.TopLeft());
+        dstRectDrawBottomLeft.MoveBy(-destBufferRect.TopLeft());
 
         destBuffer->Resize(destBufferRect.Size());
 
         gl()->BlitTextureImage(mTexImage, srcRect,
                                destBuffer, dstRect);
+        if (mBufferRotation != nsIntPoint(0, 0)) {
+          // Draw the remaining quadrants. We call BlitTextureImage 3 extra
+          // times instead of doing a single draw call because supporting that
+          // with a tiled source is quite tricky.
+          if (!srcRectDrawTopRight.IsEmpty())
+            gl()->BlitTextureImage(mTexImage, srcRectDrawTopRight,
+                                   destBuffer, dstRectDrawTopRight);
+          if (!srcRectDrawTopLeft.IsEmpty())
+            gl()->BlitTextureImage(mTexImage, srcRectDrawTopLeft,
+                                   destBuffer, dstRectDrawTopLeft);
+          if (!srcRectDrawBottomLeft.IsEmpty())
+            gl()->BlitTextureImage(mTexImage, srcRectDrawBottomLeft,
+                                   destBuffer, dstRectDrawBottomLeft);
+        }
         destBuffer->MarkValid();
         if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
           destBufferOnWhite->Resize(destBufferRect.Size());
           gl()->BlitTextureImage(mTexImageOnWhite, srcRect,
                                  destBufferOnWhite, dstRect);
+          if (mBufferRotation != nsIntPoint(0, 0)) {
+            // draw the remaining quadrants
+            if (!srcRectDrawTopRight.IsEmpty())
+              gl()->BlitTextureImage(mTexImageOnWhite, srcRectDrawTopRight,
+                                     destBufferOnWhite, dstRectDrawTopRight);
+            if (!srcRectDrawTopLeft.IsEmpty())
+              gl()->BlitTextureImage(mTexImageOnWhite, srcRectDrawTopLeft,
+                                     destBufferOnWhite, dstRectDrawTopLeft);
+            if (!srcRectDrawBottomLeft.IsEmpty())
+              gl()->BlitTextureImage(mTexImageOnWhite, srcRectDrawBottomLeft,
+                                     destBufferOnWhite, dstRectDrawBottomLeft);
+          }
+
           destBufferOnWhite->MarkValid();
         }
       } else {
         // can't blit, just draw everything
         destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags);
         if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
           destBufferOnWhite = 
             CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags);
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -3388,18 +3388,18 @@ RasterImage::DecodeWorker::Run()
 
   } while ((TimeStamp::Now() - eventStart).ToMilliseconds() <= gMaxMSBeforeYield);
 
   // If decode requests are pending, re-post ourself to the event loop.
   if (!mASAPDecodeRequests.isEmpty() || !mNormalDecodeRequests.isEmpty()) {
     EnsurePendingInEventLoop();
   }
 
-  Telemetry::Accumulate(Telemetry::IMAGE_DECODE_LATENCY,
-                        uint32_t((TimeStamp::Now() - eventStart).ToMilliseconds()));
+  Telemetry::Accumulate(Telemetry::IMAGE_DECODE_LATENCY_US,
+                        uint32_t((TimeStamp::Now() - eventStart).ToMicroseconds()));
 
   return NS_OK;
 }
 
 nsresult
 RasterImage::DecodeWorker::DecodeUntilSizeAvailable(RasterImage* aImg)
 {
   return DecodeSomeOfImage(aImg, DECODE_TYPE_UNTIL_SIZE);
--- a/intl/locale/src/charsetalias.properties
+++ b/intl/locale/src/charsetalias.properties
@@ -112,17 +112,16 @@ x-mac-gurmukhi=x-mac-gurmukhi
 armscii-8=armscii-8
 x-viet-tcvn5712=x-viet-tcvn5712
 x-viet-vps=x-viet-vps
 iso-10646-ucs-2=UTF-16BE
 x-iso-10646-ucs-2-be=UTF-16BE
 x-iso-10646-ucs-2-le=UTF-16LE
 x-user-defined=x-user-defined
 x-johab=x-johab
-x-windows-949=x-windows-949
 #
 # Aliases for ISO-8859-1
 #
 latin1=ISO-8859-1
 iso_8859-1=ISO-8859-1
 iso8859-1=ISO-8859-1
 iso8859-2=ISO-8859-2
 iso8859-3=ISO-8859-3
@@ -272,30 +271,25 @@ cn-big5=Big5
 # x-x-big5 is not really a alias for Big5, add it only for MS FrontPage
 x-x-big5=Big5
 # Sun Solaris
 zh_tw-big5=Big5
 #
 # Aliases for EUC-KR
 #
 cseuckr=EUC-KR
-# The following are really not aliases EUC-KR, add them only for MS FrontPage
-#ks_c_5601-1987=EUC-KR
+ks_c_5601-1987=EUC-KR
 iso-ir-149=EUC-KR
 ks_c_5601-1989=EUC-KR
 ksc_5601=EUC-KR
 ksc5601=EUC-KR
 korean=EUC-KR
 csksc56011987=EUC-KR
 5601=EUC-KR
-#
-# Aliases for X-Windows-949, CP949, Unified Hangul Code (UHC)
-#
-# Microsoft uses ks_c_5601-1987 to mean Windows-949 or its subset EUC-KR.
-ks_c_5601-1987=x-windows-949
+windows-949=EUC-KR
 #
 # Aliases for GB2312
 #
 # The following are really not aliases GB2312, add them only for MS FrontPage
 gb_2312-80=GB2312
 iso-ir-58=GB2312
 chinese=GB2312
 csiso58gb231280=GB2312
--- a/intl/locale/src/windows/wincharset.properties
+++ b/intl/locale/src/windows/wincharset.properties
@@ -4,17 +4,17 @@
 #
 # This file map a ACP to a charset name
 # We use this to figure out the charset of file system, clipboard, etc
 #
 
 acp.874=TIS-620
 acp.932=Shift_JIS
 acp.936=gb18030
-acp.949=x-windows-949
+acp.949=EUC-KR
 acp.950=Big5
 acp.951=Big5-HKSCS
 acp.1250=windows-1250
 acp.1251=windows-1251
 acp.1252=windows-1252
 acp.1253=windows-1253
 acp.1254=windows-1254
 acp.1255=windows-1255
--- a/intl/uconv/directory.txt
+++ b/intl/uconv/directory.txt
@@ -10,17 +10,17 @@ tests/unit - xpcshell tests
 tools      - tools to build the tables used by the converters
 util       - utility functions used by the converters
 
 The following directories contain different charset converters:
 
 ucvcn    - Simplified Chinese charsets - GB2312, HZ, ISO-2022-CN, GBK, GB18030
 ucvibm   - IBM charsets - CP850, 852, 855, 857, 862, 864, 869, 1125, 1131
 ucvja    - Japanese charsets - Shift-JIS, ISO-2022-JP, EUC-JP
-ucvko    - Korean charsets - ISO-2022-KR, EUC-KR, CP949
+ucvko    - Korean charsets - ISO-2022-KR, EUC-KR, Johab
 ucvlatin - Latin charsets and others - ISO-8859-x, CP1250-1258
                             CP866, 874, ARMSCII, ISO-IR-111, KOI8,
                             Mac charsets, T61, TIS620, TCVN, VISCII, VPS
                             UTF7, UTF16
 ucvtw    - Traditional Chinese charsets Set 1 - Big5
 ucvtw2   - Traditional Chinese charsets Set 2 - EUC-TW
 
 Within the directories containing charset converters:
--- a/intl/uconv/src/charsetData.properties
+++ b/intl/uconv/src/charsetData.properties
@@ -64,17 +64,16 @@ iso-8859-6-e.notForOutgoing             
 iso-8859-6-i.notForOutgoing             = true
 ibm864.notForOutgoing                   = true
 ibm869.notForOutgoing                   = true
 ibm1125.notForOutgoing                  = true
 ibm1131.notForOutgoing                  = true
 iso-8859-8-e.notForOutgoing             = true
 iso-8859-8.notForOutgoing               = true
 iso-2022-kr.notForOutgoing              = true
-x-windows-949.notForOutgoing            = true
 x-johab.notForOutgoing                  = true
 
 
 // XXX : there are some entries only necessary for Gtk/Xlib builds
 // to map  XLFD registry-encoding pairs to langGroups. they can be
 // removed once bug 215537 is fixed.
 
 // XXX : todo: move to something based on BCP 47 (RFC 5646);
@@ -181,17 +180,16 @@ x-mac-gurmukhi.LangGroup           = x-g
 x-mac-icelandic.LangGroup          = x-western
 macintosh.LangGroup                = x-western
 x-mac-turkish.LangGroup            = tr
 x-mac-ukrainian.LangGroup          = x-cyrillic
 x-mac-romanian.LangGroup           = x-central-euro
 x-user-defined.LangGroup           = x-user-def
 ks_c_5601-1987.LangGroup           = ko
 x-johab.LangGroup                  = ko
-x-windows-949.LangGroup            = ko
 x-mac-hebrew.LangGroup             = he
 x-mac-arabic.LangGroup             = ar
 x-sun-unicode-india-0.LangGroup    = x-devanagari
 x-tscii.LangGroup                = x-tamil
 x-tamilttf-0.LangGroup             = x-tamil
 
 iso-2022-jp.isMultibyte     = true
 shift_jis.isMultibyte       = true
@@ -199,11 +197,10 @@ euc-jp.isMultibyte          = true
 big5.isMultibyte            = true
 big5-hkscs.isMultibyte      = true
 x-euc-tw.isMultibyte        = true
 gb2312.isMultibyte          = true
 hz-gb-2312.isMultibyte      = true
 iso-2022-kr.isMultibyte     = true
 euc-kr.isMultibyte          = true
 x-johab.isMultibyte         = true
-x-windows-949.isMultibyte   = true
 utf-7.isMultibyte           = true
 utf-8.isMultibyte           = true
--- a/intl/uconv/src/nsUConvModule.cpp
+++ b/intl/uconv/src/nsUConvModule.cpp
@@ -205,18 +205,16 @@
 #include "nsUnicodeToBIG5.h"
 #include "nsBIG5HKSCSToUnicode.h"
 #include "nsUnicodeToBIG5HKSCS.h"
 #include "nsUnicodeToHKSCS.h"
 
 // ucvko
 #include "nsUCvKOCID.h"
 #include "nsUCvKODll.h"
-#include "nsEUCKRToUnicode.h"
-#include "nsUnicodeToEUCKR.h"
 #include "nsJohabToUnicode.h"
 #include "nsUnicodeToJohab.h"
 #include "nsCP949ToUnicode.h"
 #include "nsUnicodeToCP949.h"
 #include "nsISO2022KRToUnicode.h"
 
 // ucvcn
 #include "nsUCvCnCID.h"
@@ -328,17 +326,16 @@ NS_UCONV_REG_UNREG("x-euc-tw", NS_EUCTWT
 NS_UCONV_REG_UNREG("Big5", NS_BIG5TOUNICODE_CID, NS_UNICODETOBIG5_CID)
 NS_UCONV_REG_UNREG("Big5-HKSCS", NS_BIG5HKSCSTOUNICODE_CID, NS_UNICODETOBIG5HKSCS_CID)
   
 NS_UCONV_REG_UNREG_ENCODER("hkscs-1" , NS_UNICODETOHKSCS_CID)
 
     // ucvko
 NS_UCONV_REG_UNREG("EUC-KR", NS_EUCKRTOUNICODE_CID, NS_UNICODETOEUCKR_CID)
 NS_UCONV_REG_UNREG("x-johab", NS_JOHABTOUNICODE_CID, NS_UNICODETOJOHAB_CID)
-NS_UCONV_REG_UNREG("x-windows-949", NS_CP949TOUNICODE_CID, NS_UNICODETOCP949_CID)
 NS_UCONV_REG_UNREG_DECODER("ISO-2022-KR", NS_ISO2022KRTOUNICODE_CID)
 
 // ucvcn
 NS_UCONV_REG_UNREG("GB2312", NS_GB2312TOUNICODE_CID, NS_UNICODETOGB2312_CID)
 NS_UCONV_REG_UNREG("gbk", NS_GBKTOUNICODE_CID, NS_UNICODETOGBK_CID)
 NS_UCONV_REG_UNREG("HZ-GB-2312", NS_HZTOUNICODE_CID, NS_UNICODETOHZ_CID)
 NS_UCONV_REG_UNREG("gb18030", NS_GB18030TOUNICODE_CID, NS_UNICODETOGB18030_CID)
 NS_UCONV_REG_UNREG_DECODER("ISO-2022-CN", NS_ISO2022CNTOUNICODE_CID)
@@ -682,18 +679,16 @@ NS_DEFINE_NAMED_CID(NS_UNICODETOBIG5_CID
 NS_DEFINE_NAMED_CID(NS_BIG5TOUNICODE_CID);
 NS_DEFINE_NAMED_CID(NS_UNICODETOBIG5HKSCS_CID);
 NS_DEFINE_NAMED_CID(NS_UNICODETOHKSCS_CID);
 NS_DEFINE_NAMED_CID(NS_BIG5HKSCSTOUNICODE_CID);
 NS_DEFINE_NAMED_CID(NS_EUCKRTOUNICODE_CID);
 NS_DEFINE_NAMED_CID(NS_UNICODETOEUCKR_CID);
 NS_DEFINE_NAMED_CID(NS_JOHABTOUNICODE_CID);
 NS_DEFINE_NAMED_CID(NS_UNICODETOJOHAB_CID);
-NS_DEFINE_NAMED_CID(NS_CP949TOUNICODE_CID);
-NS_DEFINE_NAMED_CID(NS_UNICODETOCP949_CID);
 NS_DEFINE_NAMED_CID(NS_ISO2022KRTOUNICODE_CID);
 NS_DEFINE_NAMED_CID(NS_GB2312TOUNICODE_CID);
 NS_DEFINE_NAMED_CID(NS_UNICODETOGB2312_CID);
 NS_DEFINE_NAMED_CID(NS_GBKTOUNICODE_CID);
 NS_DEFINE_NAMED_CID(NS_UNICODETOGBK_CID);
 NS_DEFINE_NAMED_CID(NS_HZTOUNICODE_CID);
 NS_DEFINE_NAMED_CID(NS_UNICODETOHZ_CID);
 NS_DEFINE_NAMED_CID(NS_GB18030TOUNICODE_CID);
@@ -865,22 +860,20 @@ static const mozilla::Module::CIDEntry k
   { &kNS_UNICODETOJISX0201_CID, false, nullptr, nsUnicodeToJISx0201Constructor },
   { &kNS_EUCTWTOUNICODE_CID, false, nullptr, nsEUCTWToUnicodeConstructor },
   { &kNS_UNICODETOEUCTW_CID, false, nullptr, nsUnicodeToEUCTWConstructor },
   { &kNS_UNICODETOBIG5_CID, false, nullptr, nsUnicodeToBIG5Constructor },
   { &kNS_BIG5TOUNICODE_CID, false, nullptr, nsBIG5ToUnicodeConstructor },
   { &kNS_UNICODETOBIG5HKSCS_CID, false, nullptr, nsUnicodeToBIG5HKSCSConstructor },
   { &kNS_UNICODETOHKSCS_CID, false, nullptr, nsUnicodeToHKSCSConstructor },
   { &kNS_BIG5HKSCSTOUNICODE_CID, false, nullptr, nsBIG5HKSCSToUnicodeConstructor },
-  { &kNS_EUCKRTOUNICODE_CID, false, nullptr, nsEUCKRToUnicodeConstructor },
-  { &kNS_UNICODETOEUCKR_CID, false, nullptr, nsUnicodeToEUCKRConstructor },
+  { &kNS_EUCKRTOUNICODE_CID, false, nullptr, nsCP949ToUnicodeConstructor },
+  { &kNS_UNICODETOEUCKR_CID, false, nullptr, nsUnicodeToCP949Constructor },
   { &kNS_JOHABTOUNICODE_CID, false, nullptr, nsJohabToUnicodeConstructor },
   { &kNS_UNICODETOJOHAB_CID, false, nullptr, nsUnicodeToJohabConstructor },
-  { &kNS_CP949TOUNICODE_CID, false, nullptr, nsCP949ToUnicodeConstructor },
-  { &kNS_UNICODETOCP949_CID, false, nullptr, nsUnicodeToCP949Constructor },
   { &kNS_ISO2022KRTOUNICODE_CID, false, nullptr, nsISO2022KRToUnicodeConstructor },
   { &kNS_GB2312TOUNICODE_CID, false, nullptr, nsGB2312ToUnicodeV2Constructor },
   { &kNS_UNICODETOGB2312_CID, false, nullptr, nsUnicodeToGB2312V2Constructor },
   { &kNS_GBKTOUNICODE_CID, false, nullptr, nsGBKToUnicodeConstructor },
   { &kNS_UNICODETOGBK_CID, false, nullptr, nsUnicodeToGBKConstructor },
   { &kNS_HZTOUNICODE_CID, false, nullptr, nsHZToUnicodeConstructor },
   { &kNS_UNICODETOHZ_CID, false, nullptr, nsUnicodeToHZConstructor },
   { &kNS_GB18030TOUNICODE_CID, false, nullptr, nsGB18030ToUnicodeConstructor },
@@ -1058,18 +1051,16 @@ static const mozilla::Module::ContractID
   { NS_UNICODEDECODER_CONTRACTID_BASE "Big5", &kNS_BIG5TOUNICODE_CID },
   { NS_UNICODEENCODER_CONTRACTID_BASE "Big5-HKSCS", &kNS_UNICODETOBIG5HKSCS_CID },
   { NS_UNICODEENCODER_CONTRACTID_BASE "hkscs-1", &kNS_UNICODETOHKSCS_CID },
   { NS_UNICODEDECODER_CONTRACTID_BASE "Big5-HKSCS", &kNS_BIG5HKSCSTOUNICODE_CID },
   { NS_UNICODEDECODER_CONTRACTID_BASE "EUC-KR", &kNS_EUCKRTOUNICODE_CID },
   { NS_UNICODEENCODER_CONTRACTID_BASE "EUC-KR", &kNS_UNICODETOEUCKR_CID },
   { NS_UNICODEDECODER_CONTRACTID_BASE "x-johab", &kNS_JOHABTOUNICODE_CID },
   { NS_UNICODEENCODER_CONTRACTID_BASE "x-johab", &kNS_UNICODETOJOHAB_CID },
-  { NS_UNICODEDECODER_CONTRACTID_BASE "x-windows-949", &kNS_CP949TOUNICODE_CID },
-  { NS_UNICODEENCODER_CONTRACTID_BASE "x-windows-949", &kNS_UNICODETOCP949_CID },
   { NS_UNICODEDECODER_CONTRACTID_BASE "ISO-2022-KR", &kNS_ISO2022KRTOUNICODE_CID },
   { NS_UNICODEDECODER_CONTRACTID_BASE "GB2312", &kNS_GB2312TOUNICODE_CID },
   { NS_UNICODEENCODER_CONTRACTID_BASE "GB2312", &kNS_UNICODETOGB2312_CID },
   { NS_UNICODEDECODER_CONTRACTID_BASE "gbk", &kNS_GBKTOUNICODE_CID },
   { NS_UNICODEENCODER_CONTRACTID_BASE "gbk", &kNS_UNICODETOGBK_CID },
   { NS_UNICODEDECODER_CONTRACTID_BASE "HZ-GB-2312", &kNS_HZTOUNICODE_CID },
   { NS_UNICODEENCODER_CONTRACTID_BASE "HZ-GB-2312", &kNS_UNICODETOHZ_CID },
   { NS_UNICODEDECODER_CONTRACTID_BASE "gb18030", &kNS_GB18030TOUNICODE_CID },
--- a/intl/uconv/tests/unit/test_bug718500.js
+++ b/intl/uconv/tests/unit/test_bug718500.js
@@ -90,17 +90,16 @@ var encoderList = [
   "EUC-JP",
   "jis_0201",
   "x-euc-tw",
   "Big5",
   "Big5-HKSCS",
   "hkscs-1",
   "EUC-KR",
   "x-johab",
-  "x-windows-949",
   "GB2312",
   "gbk",
   "HZ-GB-2312",
   "gb18030",
 ];
 
 var decoderList = [
   "ISO-8859-1",
@@ -173,17 +172,16 @@ var decoderList = [
   "Shift_JIS",
   "ISO-2022-JP",
   "EUC-JP",
   "x-euc-tw",
   "Big5",
   "Big5-HKSCS",
   "EUC-KR",
   "x-johab",
-  "x-windows-949",
   "GB2312",
   "gbk",
   "HZ-GB-2312",
   "gb18030",
   "ISO-2022-KR",
   "ISO-2022-CN",
 ];
 
--- a/intl/uconv/tests/unit/test_decode_EUCKR_Hangul.js
+++ b/intl/uconv/tests/unit/test_decode_EUCKR_Hangul.js
@@ -1,15 +1,15 @@
 // Tests conversion of 8-byte decomposed Hangul from EUC-KR (and variants)
 // to Unicode, including invalid input
         
 load('CharsetConversionTests.js');
 load('hangulTestStrings.js');
 
-const aliases = [ "euc-kr", "EUC-KR", "iso-ir-149", "ks_c_5601-1989", "ksc_5601", "ksc5601", "korean", "csksc56011987", "5601", "x-windows-949", "ks_c_5601-1987", "cseuckr"];
+const aliases = [ "euc-kr", "EUC-KR", "iso-ir-149", "ks_c_5601-1989", "ksc_5601", "ksc5601", "korean", "csksc56011987", "5601", "windows-949", "ks_c_5601-1987", "cseuckr"];
 
 function to8byteHangul(byte3, byte5, byte7)
 {
     return String.fromCharCode(0xa4, 0xd4, 0xa4, byte3, 0xa4, byte5, 0xa4, byte7);
 }
 
 function run_test() {
     var converter = CreateScriptableConverter();
--- a/intl/uconv/ucvko/Makefile.in
+++ b/intl/uconv/ucvko/Makefile.in
@@ -12,18 +12,16 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE		= ucvko
 LIBRARY_NAME	= ucvko_s
 FORCE_STATIC_LIB=1
 LIBXUL_LIBRARY = 1
 
 
 CPPSRCS		= \
-		nsEUCKRToUnicode.cpp \
-		nsUnicodeToEUCKR.cpp \
 		nsISO2022KRToUnicode.cpp \
 		nsCP949ToUnicode.cpp \
 		nsUnicodeToCP949.cpp \
 		nsUnicodeToJohab.cpp \
 		nsJohabToUnicode.cpp \
 		$(NULL)
 
 EXPORTS		= nsUCvKOCID.h
deleted file mode 100644
--- a/intl/uconv/ucvko/nsEUCKRToUnicode.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsEUCKRToUnicode.h"
-#include "nsUCvKODll.h"
-#include "nsUCConstructors.h"
-
-nsresult
-nsEUCKRToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
-                            void **aResult)
-{
-  return nsCP949ToUnicodeConstructor(aOuter, aIID, aResult);
-}
deleted file mode 100644
--- a/intl/uconv/ucvko/nsEUCKRToUnicode.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsEUCKRToUnicode_h___
-#define nsEUCKRToUnicode_h___
-
-#include "nsCP949ToUnicode.h"
-
-/**
- * A character set converter from EUCKR to Unicode.
- *
- * @created         06/Apr/1999
- * @author  Catalin Rotaru [CATA]
- */
-// Just make it an alias to CP949 decoder. bug 131388
-nsresult
-nsEUCKRToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
-                            void **aResult);
-
-#endif /* nsEUCKRToUnicode_h___ */
--- a/intl/uconv/ucvko/nsUCvKOCID.h
+++ b/intl/uconv/ucvko/nsUCvKOCID.h
@@ -23,24 +23,16 @@
 #define NS_UNICODETOEUCKR_CID \
   { 0x379c2778, 0xec77, 0x11d2, {0x8a, 0xac, 0x0, 0x60, 0x8, 0x11, 0xa8, 0x36}}
 
 // Class ID for our UnicodeToISO2022KR charset converter
 // {BA6151A0-1DFA-11d3-B3BF-00805F8A6670}
 #define NS_UNICODETOISO2022KR_CID \
   { 0xba6151a0, 0x1dfa, 0x11d3, {0xb3, 0xbf, 0x0, 0x80, 0x5f, 0x8a, 0x66, 0x70}}
 
-// Class ID for our UnicodeToCP949 charset converter
-#define NS_UNICODETOCP949_CID \
-  { 0x9416bfbe, 0x1f93, 0x11d3, {0xb3, 0xbf, 0x0, 0x80, 0x5f, 0x8a, 0x66, 0x70}}
-
-// Class ID for our CP949ToUnicode charset converter
-#define NS_CP949TOUNICODE_CID \
-  { 0x9416bfbf, 0x1f93, 0x11d3, {0xb3, 0xbf, 0x0, 0x80, 0x5f, 0x8a, 0x66, 0x70}}
-
 // Class ID for our UnicodeToJohab charset converter
 // {D9B1F97E-CFA0-80b6-FB92-9972E48E3DCC}
 #define NS_UNICODETOJOHAB_CID \
   { 0xd9b1f97e, 0xcfa0, 0x80b6,  {0xfb, 0x92, 0x99, 0x72, 0xe4, 0x8e, 0x3d, 0xcc}} 
 
 // Class ID for our JohabToUnicode charset converter
 // {D9B1F97F-CFA0-80b6-FB92-9972E48E3DCC}
 #define NS_JOHABTOUNICODE_CID \
deleted file mode 100644
--- a/intl/uconv/ucvko/nsUnicodeToEUCKR.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsUnicodeToEUCKR.h"
-#include "nsUCvKODll.h"
-#include "nsUCConstructors.h"
-
-//----------------------------------------------------------------------
-// Global functions and data [declaration]
-
-
-static const uint16_t *g_EUCKRMappingTable[3] = {
-  g_ASCIIMappingTable,
-  g_ufKSC5601Mapping,
-  g_HangulNullMapping
-};
-
-static const uScanClassID g_EUCKRScanCellIDTable[3] =  {
-  u1ByteCharset,
-  u2BytesGRCharset,
-  uDecomposedHangulCharset
-};
-
-nsresult
-nsUnicodeToEUCKRConstructor(nsISupports *aOuter, REFNSIID aIID,
-                            void **aResult)
-{
-  return CreateMultiTableEncoder(3,
-                                 (uScanClassID*) g_EUCKRScanCellIDTable, 
-                                 (uMappingTable**) g_EUCKRMappingTable,
-                                 // change from 2 to 8 because of composed jamo
-                                 8 /* max length = src * 8 */,
-                                 aOuter, aIID, aResult);
-}
-
deleted file mode 100644
--- a/intl/uconv/ucvko/nsUnicodeToEUCKR.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsUnicodeToEUCKR_h___
-#define nsUnicodeToEUCKR_h___
-
-#include "nsISupports.h"
-
-/**
- * A character set converter from Unicode to EUCKR.
- *
- * @created         06/Apr/1999
- * @author  Catalin Rotaru [CATA]
- */
-nsresult
-nsUnicodeToEUCKRConstructor(nsISupports *aOuter, REFNSIID aIID,
-                            void **aResult);
-
-#endif /* nsUnicodeToEUCKR_h___ */
--- a/ipc/chromium/src/base/histogram.cc
+++ b/ipc/chromium/src/base/histogram.cc
@@ -950,17 +950,17 @@ FlagHistogram::FactoryGet(const std::str
   Histogram *h(nullptr);
 
   if (!StatisticsRecorder::FindHistogram(name, &h)) {
     // To avoid racy destruction at shutdown, the following will be leaked.
     FlagHistogram *fh = new FlagHistogram(name);
     fh->InitializeBucketRange();
     fh->SetFlags(flags);
     size_t zero_index = fh->BucketIndex(0);
-    fh->Histogram::Accumulate(1, 1, zero_index);
+    fh->Histogram::Accumulate(0, 1, zero_index);
     h = StatisticsRecorder::RegisterOrDeleteDuplicate(fh);
   }
 
   return h;
 }
 
 FlagHistogram::FlagHistogram(const std::string &name)
   : BooleanHistogram(name), mSwitched(false) {
@@ -978,17 +978,17 @@ FlagHistogram::Accumulate(Sample value, 
   if (mSwitched) {
     return;
   }
 
   mSwitched = true;
   DCHECK_EQ(value, 1);
   Histogram::Accumulate(value, 1, index);
   size_t zero_index = BucketIndex(0);
-  Histogram::Accumulate(1, -1, zero_index);
+  Histogram::Accumulate(0, -1, zero_index);
 }
 
 void
 FlagHistogram::AddSampleSet(const SampleSet& sample) {
   DCHECK_EQ(bucket_count(), sample.size());
   // We can't be sure the SampleSet provided came from another FlagHistogram,
   // so we take the following steps:
   //  - If our flag has already been set do nothing.
--- a/js/src/assembler/jit/ExecutableAllocator.h
+++ b/js/src/assembler/jit/ExecutableAllocator.h
@@ -207,16 +207,23 @@ public:
     ~ExecutableAllocator()
     {
         for (size_t i = 0; i < m_smallPools.length(); i++)
             m_smallPools[i]->release(/* willDestroy = */true);
         // XXX: temporarily disabled because it fails;  see bug 654820.
         //JS_ASSERT(m_pools.empty());     // if this asserts we have a pool leak
     }
 
+    void purge() {
+        for (size_t i = 0; i < m_smallPools.length(); i++)
+            m_smallPools[i]->release();
+
+	m_smallPools.clear();
+    }
+
     // alloc() returns a pointer to some memory, and also (by reference) a
     // pointer to reference-counted pool. The caller owns a reference to the
     // pool; i.e. alloc() increments the count before returning the object.
     void* alloc(size_t n, ExecutablePool** poolp, CodeKind type)
     {
         // Round 'n' up to a multiple of word size; if all allocations are of
         // word sized quantities, then all subsequent allocations will be
         // aligned.
--- a/js/src/config/makefiles/xpcshell.mk
+++ b/js/src/config/makefiles/xpcshell.mk
@@ -57,16 +57,17 @@ xpcshell-tests-remote: DM_TRANS?=adb
 xpcshell-tests-remote:
 	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/build \
 	  -I$(topsrcdir)/build/mobile \
 	  -I$(topsrcdir)/testing/mozbase/mozdevice/mozdevice \
 	  $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
 	  --build-info-json=$(DEPTH)/mozinfo.json \
+	  --testing-modules-dir=$(DEPTH)/_tests/modules \
 	  $(EXTRA_TEST_ARGS) \
 	  --dm_trans=$(DM_TRANS) \
 	  --deviceIP=${TEST_DEVICE} \
 	  --objdir=$(DEPTH) \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 
 ###########################################################################
 # Execute a single test, specified in $(SOLO_FILE), but don't automatically
@@ -107,16 +108,17 @@ check-one-remote:
 	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/build \
 	  -I$(topsrcdir)/build/mobile \
 	  -I$(topsrcdir)/testing/mozbase/mozdevice/mozdevice \
 	  $(testxpcsrcdir)/remotexpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  --test-path=$(SOLO_FILE) \
+	  --testing-modules-dir=$(DEPTH)/_tests/modules \
 	  --profile-name=$(MOZ_APP_NAME) \
 	  --verbose \
 	  $(EXTRA_TEST_ARGS) \
 	  --dm_trans=$(DM_TRANS) \
 	  --deviceIP=${TEST_DEVICE} \
 	  --objdir=$(DEPTH) \
           --noSetup \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
--- a/js/src/gc/Memory.cpp
+++ b/js/src/gc/Memory.cpp
@@ -385,17 +385,17 @@ MarkPagesInUse(void *p, size_t size)
 
 size_t
 GetPageFaultCount()
 {
     struct rusage usage;
     int err = getrusage(RUSAGE_SELF, &usage);
     if (err)
         return 0;
-    return usage.ru_minflt + usage.ru_majflt;
+    return usage.ru_majflt;
 }
 
 #else
 #error "Memory mapping functions are not defined for your OS."
 #endif
 
 } /* namespace gc */
 } /* namespace js */
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -8,16 +8,17 @@
 #include "CodeGenerator.h"
 #include "IonLinker.h"
 #include "IonSpewer.h"
 #include "MIRGenerator.h"
 #include "shared/CodeGenerator-shared-inl.h"
 #include "jsnum.h"
 #include "jsmath.h"
 #include "jsinterpinlines.h"
+#include "ExecutionModeInlines.h"
 
 #include "vm/StringObject-inl.h"
 
 using namespace js;
 using namespace js::ion;
 
 using mozilla::DebugOnly;
 
@@ -793,16 +794,27 @@ CodeGenerator::emitCallInvokeFunction(LI
     if (!callVM(InvokeFunctionInfo, call))
         return false;
 
     // Un-nestle %esp from the argument vector. No prefix was pushed.
     masm.reserveStack(unusedStack);
     return true;
 }
 
+static inline int32_t ionOffset(ExecutionMode executionMode)
+{
+    switch (executionMode) {
+      case SequentialExecution: return offsetof(JSScript, ion);
+      case ParallelExecution: return offsetof(JSScript, parallelIon);
+    }
+
+    JS_ASSERT(false);
+    return offsetof(JSScript, ion);
+}
+
 bool
 CodeGenerator::visitCallGeneric(LCallGeneric *call)
 {
     Register calleereg = ToRegister(call->getFunction());
     Register objreg    = ToRegister(call->getTempObject());
     Register nargsreg  = ToRegister(call->getNargsReg());
     uint32 unusedStack = StackOffsetOfPassedArg(call->argslot());
     Label invoke, thunk, makeCall, end;
@@ -826,17 +838,18 @@ CodeGenerator::visitCallGeneric(LCallGen
     if (!bailoutIf(Assembler::NotEqual, call->snapshot()))
         return false;
 
     // Guard that calleereg is a non-native function:
     masm.branchIfFunctionIsNative(calleereg, &invoke);
 
     // Knowing that calleereg is a non-native function, load the JSScript.
     masm.movePtr(Address(calleereg, offsetof(JSFunction, u.i.script_)), objreg);
-    masm.movePtr(Address(objreg, offsetof(JSScript, ion)), objreg);
+    ExecutionMode executionMode = gen->info().executionMode();
+    masm.movePtr(Address(objreg, ionOffset(executionMode)), objreg);
 
     // Guard that the IonScript has been compiled.
     masm.branchPtr(Assembler::BelowOrEqual, objreg, ImmWord(ION_COMPILING_SCRIPT), &invoke);
 
     // Nestle the StackPointer up to the argument vector.
     masm.freeStack(unusedStack);
 
     // Construct the IonFramePrefix.
@@ -884,48 +897,51 @@ CodeGenerator::visitCallGeneric(LCallGen
     masm.bind(&end);
     dropArguments(call->numStackArgs() + 1);
     return true;
 }
 
 bool
 CodeGenerator::visitCallKnown(LCallKnown *call)
 {
+    JSContext *cx = GetIonContext()->cx;
     Register calleereg = ToRegister(call->getFunction());
     Register objreg    = ToRegister(call->getTempObject());
     uint32 unusedStack = StackOffsetOfPassedArg(call->argslot());
     JSFunction *target = call->getSingleTarget();
     Label end, invoke;
 
     // Native single targets are handled by LCallNative.
     JS_ASSERT(!target->isNative());
     // Missing arguments must have been explicitly appended by the IonBuilder.
     JS_ASSERT(target->nargs <= call->numStackArgs());
 
     masm.checkStackAlignment();
 
     // If the function is known to be uncompilable, only emit the call to InvokeFunction.
-    if (target->script()->ion == ION_DISABLED_SCRIPT) {
+    ExecutionMode executionMode = gen->info().executionMode();
+    RootedScript targetScript(cx, target->script());
+    if (GetIonScript(targetScript, executionMode) == ION_DISABLED_SCRIPT) {
         if (!emitCallInvokeFunction(call, calleereg, call->numActualArgs(), unusedStack))
             return false;
 
         if (call->mir()->isConstructing()) {
             Label notPrimitive;
             masm.branchTestPrimitive(Assembler::NotEqual, JSReturnOperand, &notPrimitive);
             masm.loadValue(Address(StackPointer, unusedStack), JSReturnOperand);
             masm.bind(&notPrimitive);
         }
 
         dropArguments(call->numStackArgs() + 1);
         return true;
     }
 
     // Knowing that calleereg is a non-native function, load the JSScript.
     masm.movePtr(Address(calleereg, offsetof(JSFunction, u.i.script_)), objreg);
-    masm.movePtr(Address(objreg, offsetof(JSScript, ion)), objreg);
+    masm.movePtr(Address(objreg, ionOffset(executionMode)), objreg);
 
     // Guard that the IonScript has been compiled.
     masm.branchPtr(Assembler::BelowOrEqual, objreg, ImmWord(ION_COMPILING_SCRIPT), &invoke);
 
     // Load the start of the target IonCode.
     masm.movePtr(Address(objreg, IonScript::offsetOfMethod()), objreg);
     masm.movePtr(Address(objreg, IonCode::offsetOfCode()), objreg);
 
@@ -1083,16 +1099,18 @@ CodeGenerator::emitPopArguments(LApplyAr
 {
     // Pop |this| and Arguments.
     masm.freeStack(extraStackSpace);
 }
 
 bool
 CodeGenerator::visitApplyArgsGeneric(LApplyArgsGeneric *apply)
 {
+    JSContext *cx = GetIonContext()->cx;
+
     // Holds the function object.
     Register calleereg = ToRegister(apply->getFunction());
 
     // Temporary register for modifying the function object.
     Register objreg = ToRegister(apply->getTempObject());
     Register copyreg = ToRegister(apply->getTempCopy());
 
     // Holds the function nargs. Initially undefined.
@@ -1107,39 +1125,40 @@ CodeGenerator::visitApplyArgsGeneric(LAp
     }
 
     // Copy the arguments of the current function.
     emitPushArguments(apply, copyreg);
 
     masm.checkStackAlignment();
 
     // If the function is known to be uncompilable, only emit the call to InvokeFunction.
-    if (apply->hasSingleTarget() &&
-        (!apply->getSingleTarget()->isInterpreted() ||
-         apply->getSingleTarget()->script()->ion == ION_DISABLED_SCRIPT))
-    {
-        if (!emitCallInvokeFunction(apply, copyreg))
-            return false;
-        emitPopArguments(apply, copyreg);
-        return true;
+    ExecutionMode executionMode = gen->info().executionMode();
+    if (apply->hasSingleTarget()) {
+        RootedFunction target(cx, apply->getSingleTarget());
+        if (!CanIonCompile(cx, target, executionMode)) {
+            if (!emitCallInvokeFunction(apply, copyreg))
+                return false;
+            emitPopArguments(apply, copyreg);
+            return true;
+        }
     }
 
     Label end, invoke;
 
     // Guard that calleereg is a non-native function:
     if (!apply->hasSingleTarget()) {
         masm.branchIfFunctionIsNative(calleereg, &invoke);
     } else {
         // Native single targets are handled by LCallNative.
         JS_ASSERT(!apply->getSingleTarget()->isNative());
     }
 
     // Knowing that calleereg is a non-native function, load the JSScript.
     masm.movePtr(Address(calleereg, offsetof(JSFunction, u.i.script_)), objreg);
-    masm.movePtr(Address(objreg, offsetof(JSScript, ion)), objreg);
+    masm.movePtr(Address(objreg, ionOffset(executionMode)), objreg);
 
     // Guard that the IonScript has been compiled.
     masm.branchPtr(Assembler::BelowOrEqual, objreg, ImmWord(ION_COMPILING_SCRIPT), &invoke);
 
     // Call with an Ion frame or a rectifier frame.
     {
         // Create the frame descriptor.
         unsigned pushed = masm.framePushed();
@@ -2980,77 +2999,81 @@ CodeGenerator::generate()
     IonCode *code = linker.newCode(cx);
     if (!code)
         return false;
 
     // We encode safepoints after the OSI-point offsets have been determined.
     encodeSafepoints();
 
     RootedScript script(cx, gen->info().script());
-    JS_ASSERT(!script->hasIonScript());
+    ExecutionMode executionMode = gen->info().executionMode();
+    JS_ASSERT(!HasIonScript(script, executionMode));
 
     uint32 scriptFrameSize = frameClass_ == FrameSizeClass::None()
                            ? frameDepth_
                            : FrameSizeClass::FromDepth(frameDepth_).frameSize();
 
     // Check to make sure we didn't have a mid-build invalidation. If so, we
     // will trickle to ion::Compile() and return Method_Skipped.
     if (cx->compartment->types.compiledInfo.compilerOutput(cx)->isInvalidated())
         return true;
 
-    script->ion = IonScript::New(cx, slots, scriptFrameSize, snapshots_.size(),
-                                 bailouts_.length(), graph.numConstants(),
-                                 safepointIndices_.length(), osiIndices_.length(),
-                                 cacheList_.length(), barrierOffsets_.length(),
-                                 safepoints_.size(), graph.mir().numScripts());
-    if (!script->ion)
+    IonScript *ionScript =
+      IonScript::New(cx, slots, scriptFrameSize, snapshots_.size(),
+                     bailouts_.length(), graph.numConstants(),
+                     safepointIndices_.length(), osiIndices_.length(),
+                     cacheList_.length(), barrierOffsets_.length(),
+                     safepoints_.size(), graph.mir().numScripts());
+    SetIonScript(script, executionMode, ionScript);
+
+    if (!ionScript)
         return false;
     invalidateEpilogueData_.fixup(&masm);
     Assembler::patchDataWithValueCheck(CodeLocationLabel(code, invalidateEpilogueData_),
-                                       ImmWord(uintptr_t(script->ion)),
+                                       ImmWord(uintptr_t(ionScript)),
                                        ImmWord(uintptr_t(-1)));
 
     IonSpew(IonSpew_Codegen, "Created IonScript %p (raw %p)",
-            (void *) script->ion, (void *) code->raw());
-
-    script->ion->setInvalidationEpilogueDataOffset(invalidateEpilogueData_.offset());
-    script->ion->setOsrPc(gen->info().osrPc());
-    script->ion->setOsrEntryOffset(getOsrEntryOffset());
+            (void *) ionScript, (void *) code->raw());
+
+    ionScript->setInvalidationEpilogueDataOffset(invalidateEpilogueData_.offset());
+    ionScript->setOsrPc(gen->info().osrPc());
+    ionScript->setOsrEntryOffset(getOsrEntryOffset());
     ptrdiff_t real_invalidate = masm.actualOffset(invalidate_.offset());
-    script->ion->setInvalidationEpilogueOffset(real_invalidate);
-
-    script->ion->setMethod(code);
-    script->ion->setDeoptTable(deoptTable_);
+    ionScript->setInvalidationEpilogueOffset(real_invalidate);
+
+    ionScript->setMethod(code);
+    ionScript->setDeoptTable(deoptTable_);
     if (snapshots_.size())
-        script->ion->copySnapshots(&snapshots_);
+        ionScript->copySnapshots(&snapshots_);
     if (bailouts_.length())
-        script->ion->copyBailoutTable(&bailouts_[0]);
+        ionScript->copyBailoutTable(&bailouts_[0]);
     if (graph.numConstants())
-        script->ion->copyConstants(graph.constantPool());
+        ionScript->copyConstants(graph.constantPool());
     if (safepointIndices_.length())
-        script->ion->copySafepointIndices(&safepointIndices_[0], masm);
+        ionScript->copySafepointIndices(&safepointIndices_[0], masm);
     if (osiIndices_.length())
-        script->ion->copyOsiIndices(&osiIndices_[0], masm);
+        ionScript->copyOsiIndices(&osiIndices_[0], masm);
     if (cacheList_.length())
-        script->ion->copyCacheEntries(&cacheList_[0], masm);
+        ionScript->copyCacheEntries(&cacheList_[0], masm);
     if (barrierOffsets_.length())
-        script->ion->copyPrebarrierEntries(&barrierOffsets_[0], masm);
+        ionScript->copyPrebarrierEntries(&barrierOffsets_[0], masm);
     if (safepoints_.size())
-        script->ion->copySafepoints(&safepoints_);
+        ionScript->copySafepoints(&safepoints_);
 
     JS_ASSERT(graph.mir().numScripts() > 0);
-    script->ion->copyScriptEntries(graph.mir().scripts());
+    ionScript->copyScriptEntries(graph.mir().scripts());
 
     linkAbsoluteLabels();
 
     // The correct state for prebarriers is unknown until the end of compilation,
     // since a GC can occur during code generation. All barriers are emitted
     // off-by-default, and are toggled on here if necessary.
     if (cx->compartment->needsBarrier())
-        script->ion->toggleBarriers(true);
+        ionScript->toggleBarriers(true);
 
     return true;
 }
 
 // An out-of-line path to convert a boxed int32 to a double.
 class OutOfLineUnboxDouble : public OutOfLineCodeBase<CodeGenerator>
 {
     LUnboxDouble *unboxDouble_;
--- a/js/src/ion/CompileInfo.h
+++ b/js/src/ion/CompileInfo.h
@@ -12,22 +12,33 @@ namespace js {
 namespace ion {
 
 inline unsigned
 CountArgSlots(JSFunction *fun)
 {
     return fun ? fun->nargs + 2 : 1; // +2 for |scopeChain| and |this|, or +1 for |scopeChain|
 }
 
+enum ExecutionMode {
+    // Normal JavaScript execution
+    SequentialExecution,
+
+    // JavaScript code to be executed in parallel worker threads,
+    // e.g. by ParallelArray
+    ParallelExecution
+};
+
 // Contains information about the compilation source for IR being generated.
 class CompileInfo
 {
   public:
-    CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing)
-      : script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing)
+    CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing,
+                ExecutionMode executionMode)
+      : script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing),
+        executionMode_(executionMode)
     {
         JS_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY);
         nslots_ = script->nslots + CountArgSlots(fun);
     }
 
     JSScript *script() const {
         return script_;
     }
@@ -128,20 +139,29 @@ class CompileInfo
     uint32 stackSlot(uint32 i) const {
         return firstStackSlot() + i;
     }
 
     bool hasArguments() {
         return script()->argumentsHasVarBinding();
     }
 
+    ExecutionMode executionMode() const {
+        return executionMode_;
+    }
+
+    bool isParallelExecution() const {
+        return executionMode_ == ParallelExecution;
+    }
+
   private:
     JSScript *script_;
     JSFunction *fun_;
     unsigned nslots_;
     jsbytecode *osrPc_;
     bool constructing_;
+    ExecutionMode executionMode_;
 };
 
 } // namespace ion
 } // namespace js
 
 #endif
new file mode 100644
--- /dev/null
+++ b/js/src/ion/ExecutionModeInlines.h
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=4 sw=4 et tw=99:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef jsion_compilemode_h__
+#define jsion_compilemode_h__
+
+namespace js {
+namespace ion {
+
+static inline bool HasIonScript(JSScript *script, ExecutionMode cmode)
+{
+    switch (cmode) {
+      case SequentialExecution: return script->hasIonScript();
+      case ParallelExecution: return script->hasParallelIonScript();
+    }
+    JS_NOT_REACHED("No such execution mode");
+    return false;
+}
+
+static inline IonScript *GetIonScript(JSScript *script, ExecutionMode cmode)
+{
+    switch (cmode) {
+      case SequentialExecution: return script->ion;
+      case ParallelExecution: return script->parallelIon;
+    }
+    JS_NOT_REACHED("No such execution mode");
+    return NULL;
+}
+
+static inline void SetIonScript(JSScript *script, ExecutionMode cmode, IonScript *ionScript)
+{
+    switch (cmode) {
+      case SequentialExecution: script->ion = ionScript; return;
+      case ParallelExecution: script->parallelIon = ionScript; return;
+    }
+    JS_NOT_REACHED("No such execution mode");
+}
+
+static inline bool CanIonCompile(HandleScript script, ExecutionMode cmode)
+{
+    switch (cmode) {
+      case SequentialExecution: return script->canIonCompile();
+      case ParallelExecution: return script->canParallelIonCompile();
+    }
+    JS_NOT_REACHED("No such execution mode");
+    return false;
+}
+
+static inline bool CanIonCompile(JSContext *cx, HandleFunction fun, ExecutionMode cmode)
+{
+    if (!fun->isInterpreted())
+        return false;
+    RootedScript script(cx, fun->script());
+    return CanIonCompile(script, cmode);
+}
+
+static inline bool CompilingOffThread(JSScript *script, ExecutionMode cmode)
+{
+    switch (cmode) {
+      case SequentialExecution: return script->isIonCompilingOffThread();
+      case ParallelExecution: return script->isParallelIonCompilingOffThread();
+    }
+    JS_NOT_REACHED("No such execution mode");
+    return false;
+}
+
+static inline bool CompilingOffThread(HandleScript script, ExecutionMode cmode)
+{
+    switch (cmode) {
+      case SequentialExecution: return script->isIonCompilingOffThread();
+      case ParallelExecution: return script->isParallelIonCompilingOffThread();
+    }
+    JS_NOT_REACHED("No such execution mode");
+    return false;
+}
+
+static inline bool Disabled(JSScript *script, ExecutionMode cmode) {
+    switch (cmode) {
+      case SequentialExecution: return script->isIonCompilingOffThread();
+      case ParallelExecution: return script->isParallelIonCompilingOffThread();
+    }
+    JS_NOT_REACHED("No such execution mode");
+    return false;
+}
+
+static inline types::CompilerOutput::Kind CompilerOutputKind(ExecutionMode cmode)
+{
+    switch (cmode) {
+      case SequentialExecution: return types::CompilerOutput::Ion;
+      case ParallelExecution: return types::CompilerOutput::ParallelIon;
+    }
+    JS_NOT_REACHED("No such execution mode");
+    return types::CompilerOutput::Ion;
+}
+
+}
+}
+
+#endif
--- a/js/src/ion/Ion.cpp
+++ b/js/src/ion/Ion.cpp
@@ -32,16 +32,17 @@
 #include "gc/Marking.h"
 #include "jsgcinlines.h"
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 #include "vm/Stack-inl.h"
 #include "ion/IonFrames-inl.h"
 #include "ion/CompilerRoot.h"
 #include "methodjit/Retcon.h"
+#include "ExecutionModeInlines.h"
 
 #if JS_TRACE_LOGGING
 #include "TraceLogging.h"
 #endif
 
 using namespace js;
 using namespace js::ion;
 
@@ -958,16 +959,26 @@ class AutoDestroyAllocator
 
     ~AutoDestroyAllocator()
     {
         if (alloc)
             js_delete(alloc);
     }
 };
 
+class SequentialCompileContext {
+public:
+    ExecutionMode executionMode() {
+        return SequentialExecution;
+    }
+
+    bool compile(IonBuilder *builder, MIRGraph *graph,
+                 AutoDestroyAllocator &autoDestroy);
+};
+
 void
 AttachFinishedCompilations(JSContext *cx)
 {
 #ifdef JS_THREADSAFE
     AssertCanGC();
     IonCompartment *ion = cx->compartment->ionCompartment();
     if (!ion || !cx->runtime->workerThreadState)
         return;
@@ -983,17 +994,18 @@ AttachFinishedCompilations(JSContext *cx
         IonBuilder *builder = compilations.popCopy();
 
         if (builder->backgroundCompiledLir) {
             RootedScript script(cx, builder->script());
             IonContext ictx(cx, cx->compartment, &builder->temp());
 
             CodeGenerator codegen(builder, *builder->backgroundCompiledLir);
 
-            types::AutoEnterCompilation enterCompiler(cx, types::AutoEnterCompilation::Ion);
+            ExecutionMode executionMode = builder->info().executionMode();
+            types::AutoEnterCompilation enterCompiler(cx, CompilerOutputKind(executionMode));
             enterCompiler.initExisting(builder->recompileInfo);
 
             bool success;
             {
                 // Release the worker thread lock and root the compiler for GC.
                 AutoTempAllocatorRooter root(cx, &builder->temp());
                 AutoUnlockWorkerThreadState unlock(cx->runtime);
                 success = codegen.generate();
@@ -1013,18 +1025,20 @@ AttachFinishedCompilations(JSContext *cx
     }
 
     compilations.clear();
 #endif
 }
 
 static const size_t BUILDER_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 1 << 12;
 
+template <typename CompileContext>
 static bool
-IonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing)
+IonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing,
+           CompileContext &compileContext)
 {
     AssertCanGC();
 #if JS_TRACE_LOGGING
     AutoTraceLog logger(TraceLogging::defaultLogger(),
                         TraceLogging::ION_COMPILE_START,
                         TraceLogging::ION_COMPILE_STOP,
                         script);
 #endif
@@ -1040,35 +1054,50 @@ IonCompile(JSContext *cx, JSScript *scri
         return false;
 
     IonContext ictx(cx, cx->compartment, temp);
 
     if (!cx->compartment->ensureIonCompartmentExists(cx))
         return false;
 
     MIRGraph *graph = alloc->new_<MIRGraph>(temp);
-    CompileInfo *info = alloc->new_<CompileInfo>(script, fun, osrPc, constructing);
+    ExecutionMode executionMode = compileContext.executionMode();
+    CompileInfo *info = alloc->new_<CompileInfo>(script, fun, osrPc, constructing,
+                                                 executionMode);
     if (!info)
         return false;
 
     types::AutoEnterTypeInference enter(cx, true);
     TypeInferenceOracle oracle;
 
     if (!oracle.init(cx, script))
         return false;
 
     AutoFlushCache afc("IonCompile");
 
-    types::AutoEnterCompilation enterCompiler(cx, types::AutoEnterCompilation::Ion);
+    types::AutoEnterCompilation enterCompiler(cx, CompilerOutputKind(executionMode));
     enterCompiler.init(script, false, 0);
 
     AutoTempAllocatorRooter root(cx, temp);
 
     IonBuilder *builder = alloc->new_<IonBuilder>(cx, temp, graph, &oracle, info);
+    if (!compileContext.compile(builder, graph, autoDestroy)) {
+        IonSpew(IonSpew_Abort, "IM Compilation failed.");
+        return false;
+    }
+
+    return true;
+}
+
+bool
+SequentialCompileContext::compile(IonBuilder *builder, MIRGraph *graph,
+                                  AutoDestroyAllocator &autoDestroy)
+{
     JS_ASSERT(!builder->script()->ion);
+    JSContext *cx = GetIonContext()->cx;
 
     IonSpewNewFunction(graph, builder->script().unsafeGet());
 
     if (!builder->build()) {
         IonSpew(IonSpew_Abort, "Builder failed to build.");
         return false;
     }
     builder->clearForBackEnd();
@@ -1103,17 +1132,18 @@ IonCompile(JSContext *cx, JSScript *scri
     IonSpewEndFunction();
 
     return true;
 }
 
 bool
 TestIonCompile(JSContext *cx, JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing)
 {
-    if (!IonCompile(cx, script, fun, osrPc, constructing)) {
+    SequentialCompileContext compileContext;
+    if (!IonCompile(cx, script, fun, osrPc, constructing, compileContext)) {
         if (!cx->isExceptionPending())
             ForbidCompilation(cx, script);
         return false;
     }
     return true;
 }
 
 static bool
@@ -1223,17 +1253,18 @@ Compile(JSContext *cx, JSScript *script,
         // bumping the use count twice.
         if (script->getUseCount() < js_IonOptions.usesBeforeCompile)
             return Method_Skipped;
     } else {
         if (script->incUseCount() < js_IonOptions.usesBeforeCompileNoJaeger)
             return Method_Skipped;
     }
 
-    if (!IonCompile(cx, script, fun, osrPc, constructing))
+    SequentialCompileContext compileContext;
+    if (!IonCompile(cx, script, fun, osrPc, constructing, compileContext))
         return Method_CantCompile;
 
     // Compilation succeeded, but we invalidated right away.
     return script->hasIonScript() ? Method_Compiled : Method_Skipped;
 }
 
 } // namespace ion
 } // namespace js
@@ -1339,24 +1370,29 @@ ion::CanEnter(JSContext *cx, HandleScrip
 
     if (!script->ion)
         return Method_Skipped;
 
     return Method_Compiled;
 }
 
 MethodStatus
-ion::CanEnterUsingFastInvoke(JSContext *cx, HandleScript script)
+ion::CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_t numActualArgs)
 {
     JS_ASSERT(ion::IsEnabled(cx));
 
     // Skip if the code is expected to result in a bailout.
     if (!script->hasIonScript() || script->ion->bailoutExpected())
         return Method_Skipped;
 
+    // Don't handle arguments underflow, to make this work we would have to pad
+    // missing arguments with |undefined|.
+    if (numActualArgs < script->function()->nargs)
+        return Method_Skipped;
+
     if (!cx->compartment->ensureIonCompartmentExists(cx))
         return Method_Error;
 
     // This can GC, so afterward, script->ion is not guaranteed to be valid.
     AssertCanGC();
     if (!cx->compartment->ionCompartment()->enterJIT(cx))
         return Method_Error;
 
@@ -1547,21 +1583,22 @@ ion::FastInvoke(JSContext *cx, HandleFun
         JS_ASSERT(!activation.entryfp());
     }
 
     activation.setPrevPc(cx->regs().pc);
 
     EnterIonCode enter = cx->compartment->ionCompartment()->enterJITInfallible();
     void *calleeToken = CalleeToToken(fun);
 
-    Value result = Int32Value(fun->nargs);
+    Value result = Int32Value(args.length());
+    JS_ASSERT(args.length() >= fun->nargs);
 
     JSAutoResolveFlags rf(cx, RESOLVE_INFER);
     args.setActive();
-    enter(jitcode, args.length() + 1, &args[0] - 1, fp, calleeToken, &result);
+    enter(jitcode, args.length() + 1, args.array() - 1, fp, calleeToken, &result);
     args.setInactive();
 
     if (clearCallingIntoIon)
         fp->clearCallingIntoIon();
 
     JS_ASSERT(fp == cx->fp());
     JS_ASSERT(!cx->runtime->hasIonReturnOverride());
 
@@ -1719,17 +1756,21 @@ ion::Invalidate(types::TypeCompartment &
     IonSpew(IonSpew_Invalidate, "Start invalidation.");
     AutoFlushCache afc ("Invalidate");
 
     // Add an invalidation reference to all invalidated IonScripts to indicate
     // to the traversal which frames have been invalidated.
     bool anyInvalidation = false;
     for (size_t i = 0; i < invalid.length(); i++) {
         const types::CompilerOutput &co = *invalid[i].compilerOutput(types);
-        if (co.isIon()) {
+        switch (co.kind()) {
+          case types::CompilerOutput::MethodJIT:
+            break;
+          case types::CompilerOutput::Ion:
+          case types::CompilerOutput::ParallelIon:
             JS_ASSERT(co.isValid());
             IonSpew(IonSpew_Invalidate, " Invalidate %s:%u, IonScript %p",
                     co.script->filename, co.script->lineno, co.ion());
 
             // Keep the ion script alive during the invalidation and flag this
             // ionScript as being invalidated.  This increment is removed by the
             // loop after the calls to InvalidateActivation.
             co.ion()->incref();
@@ -1745,39 +1786,48 @@ ion::Invalidate(types::TypeCompartment &
     for (IonActivationIterator iter(fop->runtime()); iter.more(); ++iter)
         InvalidateActivation(fop, iter.top(), false);
 
     // Drop the references added above. If a script was never active, its
     // IonScript will be immediately destroyed. Otherwise, it will be held live
     // until its last invalidated frame is destroyed.
     for (size_t i = 0; i < invalid.length(); i++) {
         types::CompilerOutput &co = *invalid[i].compilerOutput(types);
-        if (co.isIon()) {
-            JS_ASSERT(co.isValid());
-            JSScript *script = co.script;
-            IonScript *ionScript = script->ionScript();
+        ExecutionMode executionMode;
+        switch (co.kind()) {
+          case types::CompilerOutput::MethodJIT:
+            continue;
+          case types::CompilerOutput::Ion:
+            executionMode = SequentialExecution;
+            break;
+          case types::CompilerOutput::ParallelIon:
+            executionMode = ParallelExecution;
+            break;
+        }
+        JS_ASSERT(co.isValid());
+        JSScript *script = co.script;
+        IonScript *ionScript = GetIonScript(script, executionMode);
 
-            JSCompartment *compartment = script->compartment();
-            if (compartment->needsBarrier()) {
-                // We're about to remove edges from the JSScript to gcthings
-                // embedded in the IonScript. Perform one final trace of the
-                // IonScript for the incremental GC, as it must know about
-                // those edges.
-                IonScript::Trace(compartment->barrierTracer(), ionScript);
-            }
+        JSCompartment *compartment = script->compartment();
+        if (compartment->needsBarrier()) {
+            // We're about to remove edges from the JSScript to gcthings
+            // embedded in the IonScript. Perform one final trace of the
+            // IonScript for the incremental GC, as it must know about
+            // those edges.
+            IonScript::Trace(compartment->barrierTracer(), ionScript);
+        }
 
-            ionScript->decref(fop);
-            script->ion = NULL;
-            co.invalidate();
+        ionScript->decref(fop);
+        SetIonScript(script, executionMode, NULL);
+        co.invalidate();
 
-            // Wait for the scripts to get warm again before doing another
-            // compile, unless we are recompiling *because* a script got hot.
-            if (resetUses)
-                script->resetUseCount();
-        }
+        // Wait for the scripts to get warm again before doing another
+        // compile, unless we are recompiling *because* a script got hot.
+        if (resetUses)
+            script->resetUseCount();
     }
 }
 
 void
 ion::Invalidate(JSContext *cx, const Vector<types::RecompileInfo> &invalid, bool resetUses)
 {
     ion::Invalidate(cx->compartment->types, cx->runtime->defaultFreeOp(), invalid, resetUses);
 }
@@ -1886,8 +1936,47 @@ AutoFlushCache::AutoFlushCache(const cha
         comp->setFlusher(this);
     } else {
         IonSpew(IonSpew_CacheFlush, "<%s DEAD>\n", nonce);
     }
     myCompartment_ = comp;
 }
 int js::ion::LabelBase::id_count = 0;
 
+void
+ion::PurgeCaches(JSScript *script, JSCompartment *c) {
+    if (script->hasIonScript())
+        script->ion->purgeCaches(c);
+
+    if (script->hasParallelIonScript())
+        script->ion->purgeCaches(c);
+}
+
+size_t
+ion::MemoryUsed(JSScript *script, JSMallocSizeOfFun mallocSizeOf) {
+    size_t result = 0;
+
+    if (script->hasIonScript())
+        result += script->ion->sizeOfIncludingThis(mallocSizeOf);
+
+    if (script->hasParallelIonScript())
+        result += script->parallelIon->sizeOfIncludingThis(mallocSizeOf);
+
+    return result;
+}
+
+void
+ion::DestroyIonScripts(FreeOp *fop, JSScript *script) {
+    if (script->hasIonScript())
+        ion::IonScript::Destroy(fop, script->ion);
+
+    if (script->hasParallelIonScript())
+        ion::IonScript::Destroy(fop, script->parallelIon);
+}
+
+void
+ion::TraceIonScripts(JSTracer* trc, JSScript *script) {
+    if (script->hasIonScript())
+        ion::IonScript::Trace(trc, script->ion);
+
+    if (script->hasParallelIonScript())
+        ion::IonScript::Trace(trc, script->parallelIon);
+}
--- a/js/src/ion/Ion.h
+++ b/js/src/ion/Ion.h
@@ -221,17 +221,17 @@ bool InitializeIon();
 // Get and set the current Ion context.
 IonContext *GetIonContext();
 
 bool SetIonContext(IonContext *ctx);
 
 MethodStatus CanEnterAtBranch(JSContext *cx, HandleScript script,
                               StackFrame *fp, jsbytecode *pc);
 MethodStatus CanEnter(JSContext *cx, HandleScript script, StackFrame *fp, bool newType);
-MethodStatus CanEnterUsingFastInvoke(JSContext *cx, HandleScript script);
+MethodStatus CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_t numActualArgs);
 
 enum IonExecStatus
 {
     IonExec_Error,
     IonExec_Ok,
     IonExec_Bailout
 };
 
@@ -263,13 +263,18 @@ bool TestIonCompile(JSContext *cx, JSScr
 static inline bool IsEnabled(JSContext *cx)
 {
     return cx->hasRunOption(JSOPTION_ION) && cx->typeInferenceEnabled();
 }
 
 void ForbidCompilation(JSContext *cx, JSScript *script);
 uint32_t UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc);
 
+void PurgeCaches(JSScript *script, JSCompartment *c);
+size_t MemoryUsed(JSScript *script, JSMallocSizeOfFun mallocSizeOf);
+void DestroyIonScripts(FreeOp *fop, JSScript *script);
+void TraceIonScripts(JSTracer* trc, JSScript *script);
+
 } // namespace ion
 } // namespace js
 
 #endif // jsion_ion_h__
 
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -10,16 +10,17 @@
 #include "MIRGraph.h"
 #include "Ion.h"
 #include "IonAnalysis.h"
 #include "IonSpewer.h"
 #include "frontend/BytecodeEmitter.h"
 
 #include "jsscriptinlines.h"
 #include "jstypedarrayinlines.h"
+#include "ExecutionModeInlines.h"
 
 #ifdef JS_THREADSAFE
 # include "prthread.h"
 #endif
 
 using namespace js;
 using namespace js::ion;
 
@@ -199,18 +200,18 @@ IonBuilder::canInlineTarget(JSFunction *
     }
 
     if (target->getParent() != &script_->global()) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to scope mismatch");
         return false;
     }
 
     RootedScript inlineScript(cx, target->script());
-
-    if (!inlineScript->canIonCompile()) {
+    ExecutionMode executionMode = info().executionMode();
+    if (!CanIonCompile(inlineScript, executionMode)) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to disable Ion compilation");
         return false;
     }
 
     // Allow inlining of recursive calls, but only one level deep.
     IonBuilder *builder = callerBuilder_;
     while (builder) {
         if (builder->script() == inlineScript) {
@@ -2824,17 +2825,18 @@ IonBuilder::jsop_call_inline(HandleFunct
         return false;
     for (int32 i = argc; i >= 0; i--)
         argv[i] = current->pop();
 
     // Compilation information is allocated for the duration of the current tempLifoAlloc
     // lifetime.
     RootedScript calleeScript(cx, callee->script());
     CompileInfo *info = cx->tempLifoAlloc().new_<CompileInfo>(calleeScript.get(), callee,
-                                                              (jsbytecode *)NULL, constructing);
+                                                              (jsbytecode *)NULL, constructing,
+                                                              SequentialExecution);
     if (!info)
         return false;
 
     MIRGraphExits saveExits;
     AutoAccumulateExits aae(graph(), saveExits);
 
     TypeInferenceOracle oracle;
     if (!oracle.init(cx, calleeScript))
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug809021.js
@@ -0,0 +1,73 @@
+// nactuals > nformals
+function testOverflow() {
+    var called = false;
+    function f(a) {
+        assertEq(a, 173);
+        assertEq(arguments.length, 2);
+        assertEq(arguments[0], a);
+        assertEq(arguments[1], a);
+        called = true;
+    }
+
+    for (var i=0; i<10; i++)
+        [173, 173, 173].sort(f);
+    assertEq(called, true);
+}
+testOverflow();
+
+// nactuals == nformals
+function testEqual() {
+    var called = false;
+    function f(a, b) {
+        assertEq(a, 173);
+        assertEq(arguments.length, 2);
+        assertEq(arguments[0], a);
+        assertEq(arguments[1], b);
+        called = true;
+    }
+
+    for (var i=0; i<10; i++)
+        [173, 173, 173].sort(f);
+    assertEq(called, true);
+}
+testEqual();
+
+// nactuals < nformals
+function testUnderflow() {
+    var called = false;
+    function f(a, b, c) {
+        assertEq(a, 173);
+        assertEq(c, undefined);
+        assertEq(arguments.length, 2);
+        assertEq(arguments[0], a);
+        assertEq(arguments[1], b);
+        called = true;
+    }
+
+    for (var i=0; i<10; i++)
+        [173, 173, 173].sort(f);
+    assertEq(called, true);
+}
+testUnderflow();
+
+function testUnderflowMany() {
+    var called = 0;
+    function f(a, b, c, d, e, f, g, h) {
+        assertEq(a, 173);
+        assertEq(arguments.length, 3);
+        assertEq(arguments[0], a);
+        assertEq(arguments[1] < 3, true);
+        assertEq(c.length, 3);
+        assertEq(d, undefined);
+        assertEq(e, undefined);
+        assertEq(f, undefined);
+        assertEq(g, undefined);
+        assertEq(h, undefined);
+        called += 1;
+    }
+
+    for (var i=0; i<10; i++)
+        [173, 173, 173].map(f);
+    assertEq(called, 30);
+}
+testUnderflowMany();
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -509,16 +509,19 @@ struct JSRuntime : js::RuntimeFriendFiel
   public:
     JSC::ExecutableAllocator *getExecAlloc(JSContext *cx) {
         return execAlloc_ ? execAlloc_ : createExecutableAllocator(cx);
     }
     JSC::ExecutableAllocator &execAlloc() {
         JS_ASSERT(execAlloc_);
         return *execAlloc_;
     }
+    JSC::ExecutableAllocator *maybeExecAlloc() {
+        return execAlloc_;
+    }
     WTF::BumpPointerAllocator *getBumpPointerAllocator(JSContext *cx) {
         return bumpAlloc_ ? bumpAlloc_ : createBumpPointerAllocator(cx);
     }
 #ifdef JS_METHODJIT
     js::mjit::JaegerRuntime *getJaegerRuntime(JSContext *cx) {
         return jaegerRuntime_ ? jaegerRuntime_ : createJaegerRuntime(cx);
     }
     bool hasJaegerRuntime() const {
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -547,18 +547,19 @@ JS_SetTopFrameAnnotation(JSContext *cx, 
     // because we will never EnterIon on a frame with an annotation.
     fp->setAnnotation(annotation);
 
     RawScript script = fp->script().get(nogc);
 
     ReleaseAllJITCode(cx->runtime->defaultFreeOp());
 
     // Ensure that we'll never try to compile this again.
-    JS_ASSERT(!script->hasIonScript());
+    JS_ASSERT(!script->hasAnyIonScript());
     script->ion = ION_DISABLED_SCRIPT;
+    script->parallelIon = ION_DISABLED_SCRIPT;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fpArg)
 {
     StackFrame *fp = Valueify(fpArg);
     JS_ASSERT(cx->stack.space().containsSlow(fp));
     AutoCompartment ac(cx, fp->scopeChain());
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -127,17 +127,17 @@ fun_getProperty(JSContext *cx, HandleObj
 #ifdef JS_ION
         AutoAssertNoGC nogc;
 
         // If this script hasn't been compiled yet, make sure it will never
         // be compiled. IonMonkey does not guarantee |f.arguments| can be
         // fully recovered, so we try to mitigate observing this behavior by
         // detecting its use early.
         RawScript script = iter.script().get(nogc);
-        if (!script->hasIonScript())
+        if (!script->hasAnyIonScript())
             ion::ForbidCompilation(cx, script);
 #endif
 
         vp.setObject(*argsobj);
         return true;
     }
 
 #ifdef JS_METHODJIT
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -4005,16 +4005,20 @@ EndSweepPhase(JSRuntime *rt, JSGCInvocat
          * Sweep script filenames after sweeping functions in the generic loop
          * above. In this way when a scripted function's finalizer destroys the
          * script and calls rt->destroyScriptHook, the hook can still access the
          * script's filename. See bug 323267.
          */
         if (rt->gcIsFull)
             SweepScriptFilenames(rt);
 
+        /* Clear out any small pools that we're hanging on to. */
+        if (JSC::ExecutableAllocator *execAlloc = rt->maybeExecAlloc())
+            execAlloc->purge();
+
         /*
          * This removes compartments from rt->compartment, so we do it last to make
          * sure we don't miss sweeping any compartments.
          */
         if (!lastGC)
             SweepCompartments(&fop, lastGC);
 
         if (!rt->gcSweepOnBackgroundThread) {
@@ -4569,28 +4573,29 @@ IsDeterministicGCReason(gcreason::Reason
     if (reason == gcreason::MAYBEGC)
         return false;
 
     return true;
 }
 #endif
 
 static bool
-ShouldCleanUpEverything(JSRuntime *rt, gcreason::Reason reason)
+ShouldCleanUpEverything(JSRuntime *rt, gcreason::Reason reason, JSGCInvocationKind gckind)
 {
     // During shutdown, we must clean everything up, for the sake of leak
     // detection. When a runtime has no contexts, or we're doing a GC before a
     // shutdown CC, those are strong indications that we're shutting down.
     //
     // DEBUG_MODE_GC indicates we're discarding code because the debug mode
     // has changed; debug mode affects the results of bytecode analysis, so
     // we need to clear everything away.
     return !rt->hasContexts() ||
            reason == gcreason::SHUTDOWN_CC ||
-           reason == gcreason::DEBUG_MODE_GC;
+           reason == gcreason::DEBUG_MODE_GC ||
+           gckind == GC_SHRINK;
 }
 
 static void
 Collect(JSRuntime *rt, bool incremental, int64_t budget,
         JSGCInvocationKind gckind, gcreason::Reason reason)
 {
     JS_AbortIfWrongThread(rt);
 
@@ -4648,17 +4653,17 @@ Collect(JSRuntime *rt, bool incremental,
         if (rt->gcIncrementalState != NO_INCREMENTAL && c->needsBarrier())
             c->scheduleGC();
 
         compartmentCount++;
         if (c->isGCScheduled())
             collectedCount++;
     }
 
-    rt->gcShouldCleanUpEverything = ShouldCleanUpEverything(rt, reason);
+    rt->gcShouldCleanUpEverything = ShouldCleanUpEverything(rt, reason, gckind);
 
     gcstats::AutoGCSlice agc(rt->gcStats, collectedCount, compartmentCount, reason);
 
     do {
         /*
          * Let the API user decide to defer a GC if it wants to (unless this
          * is the last context). Invoke the callback regardless.
          */
@@ -5871,18 +5876,17 @@ PurgeJITCaches(JSCompartment *c)
         JSScript *script = i.get<JSScript>();
 
         /* Discard JM caches. */
         mjit::PurgeCaches(script);
 
 #ifdef JS_ION
 
         /* Discard Ion caches. */
-        if (script->hasIonScript())
-            script->ion->purgeCaches(c);
+        ion::PurgeCaches(script, c);
 
 #endif
     }
 #endif
 }
 
 AutoMaybeTouchDeadCompartments::AutoMaybeTouchDeadCompartments(JSContext *cx)
   : runtime(cx->runtime),
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -1992,17 +1992,17 @@ JITCodeHasCheck(HandleScript script, jsb
                     found = true;
             }
             if (!found)
                 return false;
         }
     }
 #endif
 
-    if (script->hasIonScript())
+    if (script->hasAnyIonScript())
         return false;
 
     return true;
 }
 
 /*
  * Force recompilation of any jitcode for script at pc, or of any other script
  * which this script was inlined into.
@@ -2021,18 +2021,24 @@ AddPendingRecompile(JSContext *cx, Handl
     /*
      * Remind Ion not to save the compile code if generating type
      * inference information mid-compilation causes an invalidation of the
      * script being compiled.
      */
     RecompileInfo& info = cx->compartment->types.compiledInfo;
     if (info.outputIndex != RecompileInfo::NoCompilerRunning) {
         CompilerOutput *co = info.compilerOutput(cx);
-        if (co->isIon() && co->script == script) {
-            co->invalidate();
+        switch (co->kind()) {
+          case CompilerOutput::MethodJIT:
+            break;
+          case CompilerOutput::Ion:
+          case CompilerOutput::ParallelIon:
+            if (co->script == script)
+                co->invalidate();
+            break;
         }
     }
 
     /*
      * When one script is inlined into another the caller listens to state
      * changes on the callee's script, so trigger these to force recompilation
      * of any such callers.
      */
@@ -2412,21 +2418,26 @@ TypeCompartment::processPendingRecompile
     JS_ASSERT(!pending->empty());
 
 #ifdef JS_METHODJIT
 
     mjit::ExpandInlineFrames(compartment());
 
     for (unsigned i = 0; i < pending->length(); i++) {
         CompilerOutput &co = *(*pending)[i].compilerOutput(*this);
-        if (co.isJM()) {
+        switch (co.kind()) {
+          case CompilerOutput::MethodJIT:
             JS_ASSERT(co.isValid());
             mjit::Recompiler::clearStackReferences(fop, co.script);
             co.mjit()->destroyChunk(fop, co.chunkIndex);
             JS_ASSERT(co.script == NULL);
+            break;
+          case CompilerOutput::Ion:
+          case CompilerOutput::ParallelIon:
+            break;
         }
     }
 
 # ifdef JS_ION
     ion::Invalidate(*this, fop, *pending);
 # endif
 #endif /* JS_METHODJIT */
 
@@ -2513,17 +2524,17 @@ TypeCompartment::addPendingRecompile(JSC
         return;
     }
 
 #ifdef JS_METHODJIT
     mjit::JITScript *jit = co->script->getJIT(co->constructing, co->barriers);
     bool hasJITCode = jit && jit->chunkDescriptor(co->chunkIndex).chunk;
 
 # if defined(JS_ION)
-    hasJITCode |= !!co->script->hasIonScript();
+    hasJITCode |= !!co->script->hasAnyIonScript();
 # endif
 
     if (!hasJITCode) {
         /* Scripts which haven't been compiled yet don't need to be recompiled. */
         return;
     }
 #endif
 
@@ -2580,16 +2591,19 @@ TypeCompartment::addPendingRecompile(JSC
         }
     }
 
 # ifdef JS_ION
     CancelOffThreadIonCompile(cx->compartment, script);
 
     if (script->hasIonScript())
         addPendingRecompile(cx, script->ionScript()->recompileInfo());
+
+    if (script->hasParallelIonScript())
+        addPendingRecompile(cx, script->parallelIonScript()->recompileInfo());
 # endif
 #endif
 }
 
 void
 TypeCompartment::monitorBytecode(JSContext *cx, HandleScript script, uint32_t offset,
                                  bool returnOnly)
 {
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -1208,27 +1208,37 @@ typedef HashMap<AllocationSiteKey,ReadBa
 /*
  * Information about the result of the compilation of a script.  This structure
  * stored in the TypeCompartment is indexed by the RecompileInfo. This
  * indirection enable the invalidation of all constraints related to the same
  * compilation. The compiler output is build by the AutoEnterCompilation.
  */
 struct CompilerOutput
 {
+    enum Kind {
+        MethodJIT,
+        Ion,
+        ParallelIon
+    };
+
     JSScript *script;
-    bool isIonFlag : 1;
+
+    // This integer will always be a member of CompilerOutput::Kind,
+    // but, for portability, bitfields are limited to bool, int, and
+    // unsigned int.  You should really use the accessor below.
+    unsigned kindInt : 2;
     bool constructing : 1;
     bool barriers : 1;
     bool pendingRecompilation : 1;
-    uint32_t chunkIndex:28;
+    uint32_t chunkIndex:27;
 
     CompilerOutput();
 
-    bool isJM() const { return !isIonFlag; }
-    bool isIon() const { return isIonFlag; }
+    Kind kind() const { return static_cast<Kind>(kindInt); }
+    void setKind(Kind k) { kindInt = k; }
 
     mjit::JITScript *mjit() const;
     ion::IonScript *ion() const;
 
     bool isValid() const;
 
     void setPendingRecompilation() {
         pendingRecompilation = true;
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -83,79 +83,95 @@ namespace types {
 
 /////////////////////////////////////////////////////////////////////
 // CompilerOutput & RecompileInfo
 /////////////////////////////////////////////////////////////////////
 
 inline
 CompilerOutput::CompilerOutput()
   : script(NULL),
-    isIonFlag(false),
+    kindInt(MethodJIT),
     constructing(false),
     barriers(false),
     chunkIndex(false)
 {
 }
 
 inline mjit::JITScript *
 CompilerOutput::mjit() const
 {
 #ifdef JS_METHODJIT
-    JS_ASSERT(isJM() && isValid());
+    JS_ASSERT(kind() == MethodJIT && isValid());
     return script->getJIT(constructing, barriers);
 #else
     return NULL;
 #endif
 }
 
 inline ion::IonScript *
 CompilerOutput::ion() const
 {
 #ifdef JS_ION
-    JS_ASSERT(isIon() && isValid());
-    return script->ionScript();
-#else
+    JS_ASSERT(kind() != MethodJIT && isValid());
+    switch (kind()) {
+      case MethodJIT: break;
+      case Ion: return script->ionScript();
+      case ParallelIon: return script->parallelIonScript();
+    }
+#endif
+    JS_NOT_REACHED("Invalid kind of CompilerOutput");
     return NULL;
-#endif
 }
 
 inline bool
 CompilerOutput::isValid() const
 {
     if (!script)
         return false;
 
 #if defined(DEBUG) && (defined(JS_METHODJIT) || defined(JS_ION))
     TypeCompartment &types = script->compartment()->types;
 #endif
 
+    switch (kind()) {
+      case MethodJIT: {
 #ifdef JS_METHODJIT
-    if (isJM()) {
         mjit::JITScript *jit = script->getJIT(constructing, barriers);
         if (!jit)
             return false;
         mjit::JITChunk *chunk = jit->chunkDescriptor(chunkIndex).chunk;
         if (!chunk)
             return false;
         JS_ASSERT(this == chunk->recompileInfo.compilerOutput(types));
         return true;
-    }
 #endif
+      }
 
+      case Ion:
 #ifdef JS_ION
-    if (isIon()) {
         if (script->hasIonScript()) {
             JS_ASSERT(this == script->ion->recompileInfo().compilerOutput(types));
             return true;
         }
         if (script->isIonCompilingOffThread())
             return true;
+#endif
+        return false;
+
+      case ParallelIon:
+#ifdef JS_ION
+        if (script->hasParallelIonScript()) {
+            JS_ASSERT(this == script->parallelIonScript()->recompileInfo().compilerOutput(types));
+            return true;
+        }
+        if (script->isParallelIonCompilingOffThread())
+            return true;
+#endif
         return false;
     }
-#endif
     return false;
 }
 
 inline CompilerOutput*
 RecompileInfo::compilerOutput(TypeCompartment &types) const
 {
     return &(*types.constrainedOutputs)[outputIndex];
 }
@@ -382,37 +398,32 @@ struct AutoEnterTypeInference
 /*
  * Structure marking the currently compiled script, for constraints which can
  * trigger recompilation.
  */
 struct AutoEnterCompilation
 {
     JSContext *cx;
     RecompileInfo &info;
+    CompilerOutput::Kind kind;
 
-    enum Compiler {
-        JM,
-        Ion
-    };
-    Compiler mode;
-
-    AutoEnterCompilation(JSContext *cx, Compiler mode)
+    AutoEnterCompilation(JSContext *cx, CompilerOutput::Kind kind)
       : cx(cx),
         info(cx->compartment->types.compiledInfo),
-        mode(mode)
+        kind(kind)
     {
         JS_ASSERT(cx->compartment->activeAnalysis);
         JS_ASSERT(info.outputIndex == RecompileInfo::NoCompilerRunning);
     }
 
     bool init(JSScript *script, bool constructing, unsigned chunkIndex)
     {
         CompilerOutput co;
         co.script = script;
-        co.isIonFlag = (mode == Ion);
+        co.setKind(kind);
         co.constructing = constructing;
         co.barriers = cx->compartment->compileBarriers();
         co.chunkIndex = chunkIndex;
 
         // This flag is used to prevent adding the current compiled script in
         // the list of compiler output which should be invalided.  This is
         // necessary because we can run some analysis might discard the script
         // it-self, which can happen when the monitored value does not reflect
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -1002,21 +1002,21 @@ class FastInvokeGuard
     RootedScript script_;
 #ifdef JS_ION
     ion::IonContext ictx_;
     bool useIon_;
 #endif
 
   public:
     FastInvokeGuard(JSContext *cx, const Value &fval)
-      : fun_(cx),
-        script_(cx)
+      : fun_(cx)
+      , script_(cx)
 #ifdef JS_ION
-        , ictx_(cx, cx->compartment, NULL),
-        useIon_(ion::IsEnabled(cx))
+      , ictx_(cx, cx->compartment, NULL)
+      , useIon_(ion::IsEnabled(cx))
 #endif
     {
         initFunction(fval);
     }
 
     void initFunction(const Value &fval) {
         if (fval.isObject() && fval.toObject().isFunction()) {
             JSFunction *fun = fval.toObject().toFunction();
@@ -1031,17 +1031,17 @@ class FastInvokeGuard
         return args_;
     }
 
     bool invoke(JSContext *cx) {
 #ifdef JS_ION
         if (useIon_ && fun_) {
             JS_ASSERT(fun_->script() == script_);
 
-            ion::MethodStatus status = ion::CanEnterUsingFastInvoke(cx, script_);
+            ion::MethodStatus status = ion::CanEnterUsingFastInvoke(cx, script_, args_.length());
             if (status == ion::Method_Error)
                 return false;
             if (status == ion::Method_Compiled) {
                 ion::IonExecStatus result = ion::FastInvoke(cx, fun_, args_);
                 if (result == ion::IonExec_Error)
                     return false;
 
                 JS_ASSERT(result == ion::IonExec_Ok);
--- a/js/src/jsmemorymetrics.cpp
+++ b/js/src/jsmemorymetrics.cpp
@@ -15,16 +15,17 @@
 #include "jsgc.h"
 #include "jsobj.h"
 #include "jsscope.h"
 #include "jsscript.h"
 
 #include "jsobjinlines.h"
 
 #include "ion/IonCode.h"
+#include "ion/Ion.h"
 
 namespace js {
 
 size_t MemoryReportingSundriesThreshold()
 {
     return 8 * 1024;
 }
 
@@ -227,18 +228,17 @@ StatsCellCallback(JSRuntime *rt, void *d
     case JSTRACE_SCRIPT:
     {
         JSScript *script = static_cast<JSScript *>(thing);
         cStats->gcHeapScripts += thingSize;
         cStats->scriptData += script->sizeOfData(rtStats->mallocSizeOf);
 #ifdef JS_METHODJIT
         cStats->jaegerData += script->sizeOfJitScripts(rtStats->mallocSizeOf);
 # ifdef JS_ION
-        if (script->hasIonScript())
-            cStats->ionData += script->ion->sizeOfIncludingThis(rtStats->mallocSizeOf);
+        cStats->ionData += ion::MemoryUsed(script, rtStats->mallocSizeOf);
 # endif
 #endif
 
         ScriptSource *ss = script->scriptSource();
         SourceSet::AddPtr entry = closure->seenSources.lookupForAdd(ss);
         if (!entry) {
             closure->seenSources.add(entry, ss); // Not much to be done on failure.
             rtStats->runtime.scriptSources += ss->sizeOfIncludingThis(rtStats->mallocSizeOf);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1901,18 +1901,17 @@ JSScript::finalize(FreeOp *fop)
         JS_DropPrincipals(fop->runtime(), originPrincipals);
 
     if (types)
         types->destroy();
 
 #ifdef JS_METHODJIT
     mjit::ReleaseScriptCode(fop, this);
 # ifdef JS_ION
-    if (hasIonScript())
-        ion::IonScript::Destroy(fop, ion);
+    ion::DestroyIonScripts(fop, this);
 # endif
 #endif
 
     destroyScriptCounts(fop);
     destroyDebugScript(fop);
     scriptSource_->decref(fop->runtime());
 
     if (data) {
@@ -2594,18 +2593,17 @@ JSScript::markChildren(JSTracer *trc)
         for (unsigned i = 0; i < length; i++) {
             BreakpointSite *site = debugScript()->breakpoints[i];
             if (site && site->trapHandler)
                 MarkValue(trc, &site->trapClosure, "trap closure");
         }
     }
 
 #ifdef JS_ION
-    if (hasIonScript())
-        ion::IonScript::Trace(trc, ion);
+    ion::TraceIonScripts(trc, this);
 #endif
 }
 
 void
 JSScript::setArgumentsHasVarBinding()
 {
     argsHasVarBinding_ = true;
     needsArgsAnalysis_ = true;
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -544,36 +544,60 @@ struct JSScript : public js::gc::Cell
      * canonical location for the arguments. Note: if a formal is aliased
      * through the scope chain, then script->formalIsAliased and JSOP_*ARG*
      * opcodes won't be emitted at all.
      */
     bool argsObjAliasesFormals() const {
         return needsArgsObj() && !strictModeCode;
     }
 
-    js::ion::IonScript *ion;          /* Information attached by Ion */
+    bool hasAnyIonScript() const {
+        return hasIonScript() || hasParallelIonScript();
+    }
 
-#if defined(JS_METHODJIT) && JS_BITS_PER_WORD == 32
-    void *padding_;
-#endif
+    /* Information attached by Ion: script for sequential mode execution */
+    js::ion::IonScript *ion;
 
     bool hasIonScript() const {
         return ion && ion != ION_DISABLED_SCRIPT && ion != ION_COMPILING_SCRIPT;
     }
+
     bool canIonCompile() const {
         return ion != ION_DISABLED_SCRIPT;
     }
+
     bool isIonCompilingOffThread() const {
         return ion == ION_COMPILING_SCRIPT;
     }
+
     js::ion::IonScript *ionScript() const {
         JS_ASSERT(hasIonScript());
         return ion;
     }
 
+    /* Information attached by Ion: script for parallel mode execution */
+    js::ion::IonScript *parallelIon;
+
+    bool hasParallelIonScript() const {
+        return parallelIon && parallelIon != ION_DISABLED_SCRIPT && parallelIon != ION_COMPILING_SCRIPT;
+    }
+
+    bool canParallelIonCompile() const {
+        return parallelIon != ION_DISABLED_SCRIPT;
+    }
+
+    bool isParallelIonCompilingOffThread() const {
+        return parallelIon == ION_COMPILING_SCRIPT;
+    }
+
+    js::ion::IonScript *parallelIonScript() const {
+        JS_ASSERT(hasParallelIonScript());
+        return parallelIon;
+    }
+
     /*
      * Original compiled function for the script, if it has a function.
      * NULL for global and eval scripts.
      */
     JSFunction *function() const { return function_; }
     void setFunction(JSFunction *fun);
 
     JSFlatString *sourceData(JSContext *cx);
--- a/js/src/jsworkers.cpp
+++ b/js/src/jsworkers.cpp
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jsworkers.h"
 
 #if JS_ION
 # include "ion/IonBuilder.h"
+# include "ion/ExecutionModeInlines.h"
 #endif
 
 using namespace js;
 
 using mozilla::DebugOnly;
 
 #ifdef JS_PARALLEL_COMPILATION
 
@@ -289,17 +290,18 @@ WorkerThread::threadLoop()
                 state.unlock();
                 return;
             }
             state.wait(WorkerThreadState::WORKER);
         }
 
         ionBuilder = state.ionWorklist.popCopy();
 
-        JS_ASSERT(ionBuilder->script()->ion == ION_COMPILING_SCRIPT);
+        ion::ExecutionMode executionMode = ionBuilder->info().executionMode();
+        JS_ASSERT(GetIonScript(ionBuilder->script().unsafeGet(), executionMode) == ION_COMPILING_SCRIPT);
 
         state.unlock();
 
         {
             ion::IonContext ictx(NULL, ionBuilder->script()->compartment(), &ionBuilder->temp());
             ionBuilder->backgroundCompiledLir = ion::CompileBackEnd(ionBuilder);
         }
 
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -534,17 +534,17 @@ mjit::Compiler::performCompilation()
 
 #ifdef JS_METHODJIT
     outerScript->debugMode = debugMode();
 #endif
 
     JS_ASSERT(cx->compartment->activeInference);
 
     {
-        types::AutoEnterCompilation enter(cx, types::AutoEnterCompilation::JM);
+        types::AutoEnterCompilation enter(cx, types::CompilerOutput::MethodJIT);
         if (!enter.init(outerScript, isConstructing, chunkIndex)) {
             js_ReportOutOfMemory(cx);
             return Compile_Error;
         }
 
         CHECK_STATUS(checkAnalysis(outerScript));
         if (inlining())
             CHECK_STATUS(scanInlineCalls(CrossScriptSSA::OUTER_FRAME, 0));
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -2047,16 +2047,17 @@ ContainerState::ProcessDisplayItems(cons
       if (activeScrolledRoot != lastActiveScrolledRoot) {
         lastActiveScrolledRoot = activeScrolledRoot;
         topLeft = activeScrolledRoot->GetOffsetToCrossDoc(mContainerReferenceFrame);
       }
     }
 
     // Assign the item to a layer
     if (layerState == LAYER_ACTIVE_FORCE ||
+        (layerState == LAYER_INACTIVE && !mManager->IsWidgetLayerManager()) ||
         (!forceInactive &&
          (layerState == LAYER_ACTIVE_EMPTY ||
           layerState == LAYER_ACTIVE))) {
 
       // LAYER_ACTIVE_EMPTY means the layer is created just for its metadata.
       // We should never see an empty layer with any visible content!
       NS_ASSERTION(layerState != LAYER_ACTIVE_EMPTY ||
                    itemVisibleRect.IsEmpty(),
@@ -2691,17 +2692,17 @@ ChooseScaleAndSetTransform(FrameLayerBui
         int32_t(NSAppUnitsToDoublePixels(appUnitOffset.x, appUnitsPerDevPixel)*aIncomingScale.mXScale),
         int32_t(NSAppUnitsToDoublePixels(appUnitOffset.y, appUnitsPerDevPixel)*aIncomingScale.mYScale));
   }
   transform = transform * gfx3DMatrix::Translation(offset.x + aIncomingScale.mOffset.x, offset.y + aIncomingScale.mOffset.y, 0);
 
   gfxMatrix transform2d;
   bool canDraw2D = transform.CanDraw2D(&transform2d);
   gfxSize scale;
-  bool isRetained = aLayerBuilder->GetRetainingLayerManager() == aLayer->Manager();
+  bool isRetained = aLayer->Manager()->IsWidgetLayerManager();
   // Only fiddle with scale factors for the retaining layer manager, since
   // it only matters for retained layers
   // XXX Should we do something for 3D transforms?
   if (canDraw2D && isRetained) {
     //Scale factors are normalized to a power of 2 to reduce the number of resolution changes
     scale = transform2d.ScaleFactors(true);
     // For frames with a changing transform that's not just a translation,
     // round scale factors up to nearest power-of-2 boundary so that we don't
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2614,40 +2614,46 @@ bool nsDisplayWrapList::IsVaryingRelativ
   return true;
 }
 
 void nsDisplayWrapList::Paint(nsDisplayListBuilder* aBuilder,
                               nsRenderingContext* aCtx) {
   NS_ERROR("nsDisplayWrapList should have been flattened away for painting");
 }
 
-bool nsDisplayWrapList::ChildrenCanBeInactive(nsDisplayListBuilder* aBuilder,
-                                              LayerManager* aManager,
-                                              const ContainerParameters& aParameters,
-                                              const nsDisplayList& aList,
-                                              nsIFrame* aActiveScrolledRoot) {
+LayerState
+nsDisplayWrapList::RequiredLayerStateForChildren(nsDisplayListBuilder* aBuilder,
+                                                 LayerManager* aManager,
+                                                 const ContainerParameters& aParameters,
+                                                 const nsDisplayList& aList,
+                                                 nsIFrame* aActiveScrolledRoot) {
+  LayerState result = LAYER_INACTIVE;
   for (nsDisplayItem* i = aList.GetBottom(); i; i = i->GetAbove()) {
     nsIFrame* f = i->GetUnderlyingFrame();
     if (f) {
       nsIFrame* activeScrolledRoot =
         nsLayoutUtils::GetActiveScrolledRootFor(f, nullptr);
-      if (activeScrolledRoot != aActiveScrolledRoot)
-        return false;
+      if (activeScrolledRoot != aActiveScrolledRoot && result == LAYER_INACTIVE)
+        result = LAYER_ACTIVE;
     }
 
     LayerState state = i->GetLayerState(aBuilder, aManager, aParameters);
-    if (state == LAYER_ACTIVE || state == LAYER_ACTIVE_FORCE)
-      return false;
+    if ((state == LAYER_ACTIVE || state == LAYER_ACTIVE_FORCE) && (state > result))
+      result = state;
     if (state == LAYER_NONE) {
       nsDisplayList* list = i->GetSameCoordinateSystemChildren();
-      if (list && !ChildrenCanBeInactive(aBuilder, aManager, aParameters, *list, aActiveScrolledRoot))
-        return false;
+      if (list) {
+        LayerState childState = RequiredLayerStateForChildren(aBuilder, aManager, aParameters, *list, aActiveScrolledRoot);
+        if (childState > result) {
+          result = childState;
+        }
+      }
     }
   }
-  return true;
+  return result;
 }
 
 nsRect nsDisplayWrapList::GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder)
 {
   nsRect bounds;
   for (nsDisplayItem* i = mList.GetBottom(); i; i = i->GetAbove()) {
     bounds.UnionRect(bounds, i->GetComponentAlphaBounds(aBuilder));
   }
@@ -2787,18 +2793,17 @@ nsDisplayOpacity::GetLayerState(nsDispla
   if (mFrame->GetContent()) {
     if (nsLayoutUtils::HasAnimationsForCompositor(mFrame->GetContent(),
                                                   eCSSProperty_opacity)) {
       return LAYER_ACTIVE;
     }
   }
   nsIFrame* activeScrolledRoot =
     nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nullptr);
-  return !ChildrenCanBeInactive(aBuilder, aManager, aParameters, mList, activeScrolledRoot)
-      ? LAYER_ACTIVE : LAYER_INACTIVE;
+  return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, activeScrolledRoot);
 }
 
 bool
 nsDisplayOpacity::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                     nsRegion* aVisibleRegion,
                                     const nsRect& aAllowVisibleRegionExpansion) {
   // Our children are translucent so we should not allow them to subtract
   // area from aVisibleRegion. We do need to find out what is visible under
@@ -3933,37 +3938,40 @@ already_AddRefed<Layer> nsDisplayTransfo
   }
   return container.forget();
 }
 
 nsDisplayItem::LayerState
 nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
                                   LayerManager* aManager,
                                   const ContainerParameters& aParameters) {
+  // If the transform is 3d, or the layer takes part in preserve-3d sorting
+  // then we *always* want this to be an active layer.
+  if (!GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel()).Is2D() || 
+      mFrame->Preserves3D()) {
+    return LAYER_ACTIVE_FORCE;
+  }
   // Here we check if the *post-transform* bounds of this item are big enough
   // to justify an active layer.
   if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer) &&
       !IsItemTooSmallForActiveLayer(this))
     return LAYER_ACTIVE;
-  if (!GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel()).Is2D() || mFrame->Preserves3D())
-    return LAYER_ACTIVE;
   if (mFrame->GetContent()) {
     if (nsLayoutUtils::HasAnimationsForCompositor(mFrame->GetContent(),
                                                   eCSSProperty_transform)) {
       return LAYER_ACTIVE;
     }
   }
   nsIFrame* activeScrolledRoot =
     nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nullptr);
-  return !mStoredList.ChildrenCanBeInactive(aBuilder,
-                                            aManager,
-                                            aParameters,
-                                            *mStoredList.GetChildren(),
-                                            activeScrolledRoot)
-      ? LAYER_ACTIVE : LAYER_INACTIVE;
+  return mStoredList.RequiredLayerStateForChildren(aBuilder,
+                                                   aManager,
+                                                   aParameters,
+                                                   *mStoredList.GetChildren(),
+                                                   activeScrolledRoot);
 }
 
 bool nsDisplayTransform::ComputeVisibility(nsDisplayListBuilder *aBuilder,
                                              nsRegion *aVisibleRegion,
                                              const nsRect& aAllowVisibleRegionExpansion)
 {
   /* As we do this, we need to be sure to
    * untransform the visible rect, since we want everything that's painting to
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -1881,16 +1881,22 @@ public:
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
   
   virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                    bool* aSnap) MOZ_OVERRIDE;
   virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE;
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
 
+  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE
+  {
+    *aSnap = true;
+    return nsRect(ToReferenceFrame(), GetUnderlyingFrame()->GetSize());
+  }
+
   NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
 
   nscolor mColor;
 };
 
 /**
  * The standard display item to paint the outer CSS box-shadows of a frame.
  */
@@ -2118,21 +2124,21 @@ public:
     return nullptr;
   }
 
   /**
    * Returns true if all descendant display items can be placed in the same
    * ThebesLayer --- GetLayerState returns LAYER_INACTIVE or LAYER_NONE,
    * and they all have the given aActiveScrolledRoot.
    */
-  static bool ChildrenCanBeInactive(nsDisplayListBuilder* aBuilder,
-                                    LayerManager* aManager,
-                                    const ContainerParameters& aParameters,
-                                    const nsDisplayList& aList,
-                                    nsIFrame* aActiveScrolledRoot);
+  static LayerState RequiredLayerStateForChildren(nsDisplayListBuilder* aBuilder,
+                                                  LayerManager* aManager,
+                                                  const ContainerParameters& aParameters,
+                                                  const nsDisplayList& aList,
+                                                  nsIFrame* aActiveScrolledRoot);
 
 protected:
   nsDisplayWrapList() {}
 
   void MergeFrom(nsDisplayWrapList* aOther)
   {
     mList.AppendToBottom(&aOther->mList);
     mBounds.UnionRect(mBounds, aOther->mBounds);
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -2612,17 +2612,23 @@ nsRootPresContext::ComputePluginGeometry
     // again.
     aBuilder->SetAllowMergingAndFlattening(false);
     nsRegion region = rootFrame->GetVisualOverflowRectRelativeToSelf();
     // nsDisplayPlugin::ComputeVisibility will automatically set a non-hidden
     // widget configuration for the plugin, if it's visible.
     aList->ComputeVisibilityForRoot(aBuilder, &region);
   }
 
+#ifdef XP_MACOSX
+  // We control painting of Mac plugins, so just apply geometry updates now.
+  // This is not happening during a paint event.
+  ApplyPluginGeometryUpdates();
+#else
   InitApplyPluginGeometryTimer();
+#endif
 }
 
 static void
 ApplyPluginGeometryUpdatesCallback(nsITimer *aTimer, void *aClosure)
 {
   static_cast<nsRootPresContext*>(aClosure)->ApplyPluginGeometryUpdates();
 }
 
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -7122,17 +7122,19 @@ PresShell::WillPaintWindow(bool aWillSen
 {
   nsRootPresContext* rootPresContext = mPresContext->GetRootPresContext();
   if (rootPresContext != mPresContext) {
     // This could be a popup's presshell. We don't allow plugins in popups
     // so there's nothing to do here.
     return;
   }
 
+#ifndef XP_MACOSX
   rootPresContext->ApplyPluginGeometryUpdates();
+#endif
 }
 
 void
 PresShell::DidPaintWindow()
 {
   nsRootPresContext* rootPresContext = mPresContext->GetRootPresContext();
   if (rootPresContext != mPresContext) {
     // This could be a popup's presshell. No point in notifying XPConnect
--- a/layout/base/tests/Makefile.in
+++ b/layout/base/tests/Makefile.in
@@ -144,16 +144,17 @@ MOCHITEST_FILES =	\
 		test_bug629838.html \
 		test_bug646757.html \
 		test_bug718809.html \
 		test_bug725426.html \
 		test_bug731777.html \
 		test_bug761572.html \
 		test_bug770106.html \
 		test_maxLineBoxWidth.html \
+		test_remote_frame.html \
 		$(NULL)
 
 # Tests for bugs 441782, 467672 and 570378 don't pass reliably on Windows, because of bug 469208
 ifeq (,$(filter windows,$(MOZ_WIDGET_TOOLKIT)))
 # THESE TESTS (BELOW) DO NOT RUN ON WINDOWS
 MOCHITEST_FILES += \
 		bidi_numeral_test.js \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/test_remote_frame.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style>
+  div, iframe {
+    position:absolute;
+    left:0; top:50px;
+    width:400px; height:400px;
+    transform: translateY(50px);
+    border:5px solid black;
+  }
+  </style>
+</head>
+  <body>
+    <div id="d" style="background:blue"></div>
+
+  <script type="application/javascript;version=1.7">
+    "use strict";
+
+    var referenceSnapshot;
+    var iterations = 0;
+
+    SimpleTest.waitForExplicitFinish();
+
+    function pollForTestPass() {
+      var snapshot = snapshotWindow(window);
+      if (compareSnapshots(referenceSnapshot, snapshot, true)[0]) {
+        ok(true, "Test passed after " + iterations + " iterations");
+        SimpleTest.finish();
+        return;
+      }
+
+      ++iterations;
+      if (iterations == 20) {
+        todo(false, "We couldn't draw the frame, but at least we didn't crash");
+        SimpleTest.finish();
+        return;
+      }
+      setTimeout(pollForTestPass, 10);
+    }
+    function addRemoteFrame() {
+      let iframe = document.createElement("iframe");
+      iframe.mozbrowser = true;
+      iframe.src = "data:text/html,<html style='background:blue;'>";
+
+      document.body.appendChild(iframe);
+
+      pollForTestPass();
+    }
+    addEventListener("load", function() {
+      referenceSnapshot = snapshotWindow(window);
+      document.getElementById("d").style.display = 'none';
+      SpecialPowers.addPermission("browser", true, document);
+      SpecialPowers.pushPrefEnv({
+        "set": [
+          ["dom.ipc.browser_frames.oop_by_default", true],
+          ["dom.mozBrowserFramesEnabled", true]
+        ]
+      }, addRemoteFrame);      
+    });
+  </script>
+</body>
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -170,17 +170,16 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsTextSer
 #include "nsHTMLEditorLog.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLEditorLog)
 #else
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLEditor)
 #endif
 
 #include "nsHTMLCanvasFrame.h"
 
-#include "nsIDOMCanvasRenderingContext2D.h"
 #include "nsIDOMWebGLRenderingContext.h"
 
 class nsIDocumentLoaderFactory;
 
 #define PRODUCT_NAME "Gecko"
 
 #define NS_HTMLIMGELEMENT_CONTRACTID \
   "@mozilla.org/content/element/html;1?name=img"
@@ -437,17 +436,16 @@ nsresult NS_NewBoxObject(nsIBoxObject** 
 nsresult NS_NewListBoxObject(nsIBoxObject** aResult);
 nsresult NS_NewScrollBoxObject(nsIBoxObject** aResult);
 nsresult NS_NewMenuBoxObject(nsIBoxObject** aResult);
 nsresult NS_NewPopupBoxObject(nsIBoxObject** aResult);
 nsresult NS_NewContainerBoxObject(nsIBoxObject** aResult);
 nsresult NS_NewTreeBoxObject(nsIBoxObject** aResult);
 #endif
 
-nsresult NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult);
 nsresult NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult);
 
 nsresult NS_CreateFrameTraversal(nsIFrameTraversal** aResult);
 
 nsresult NS_NewDomSelection(nsISelection** aResult);
 nsresult NS_NewContentViewer(nsIContentViewer** aResult);
 nsresult NS_NewGenRegularIterator(nsIContentIterator** aResult);
 nsresult NS_NewGenSubtreeIterator(nsIContentIterator** aInstancePtrResult);
@@ -561,17 +559,16 @@ MAKE_CTOR(CreateChildMessageManager,    
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDataDocumentContentPolicy)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsNoDataProtocolContentPolicy)
 MAKE_CTOR(CreatePluginDocument,           nsIDocument,                 NS_NewPluginDocument)
 #ifdef MOZ_MEDIA
 MAKE_CTOR(CreateVideoDocument,            nsIDocument,                 NS_NewVideoDocument)
 #endif
 MAKE_CTOR(CreateFocusManager,             nsIFocusManager,      NS_NewFocusManager)
 
-MAKE_CTOR(CreateCanvasRenderingContext2D, nsIDOMCanvasRenderingContext2D, NS_NewCanvasRenderingContext2D)
 MAKE_CTOR(CreateCanvasRenderingContextWebGL, nsIDOMWebGLRenderingContext, NS_NewCanvasRenderingContextWebGL)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStyleSheetService, Init)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsJSURI)
 
 // views are not refcounted, so this is the same as
 // NS_GENERIC_FACTORY_CONSTRUCTOR without the NS_ADDREF/NS_RELEASE
@@ -724,17 +721,16 @@ NS_DEFINE_NAMED_CID(NS_DOMSELECTION_CID)
 NS_DEFINE_NAMED_CID(NS_CONTENTITERATOR_CID);
 NS_DEFINE_NAMED_CID(NS_PRECONTENTITERATOR_CID);
 NS_DEFINE_NAMED_CID(NS_SUBTREEITERATOR_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLIMAGEELEMENT_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLOPTIONELEMENT_CID);
 #ifdef MOZ_MEDIA
 NS_DEFINE_NAMED_CID(NS_HTMLAUDIOELEMENT_CID);
 #endif
-NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXT2D_CID);
 NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXTWEBGL_CID);
 NS_DEFINE_NAMED_CID(NS_TEXT_ENCODER_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLCOPY_TEXT_ENCODER_CID);
 NS_DEFINE_NAMED_CID(NS_XMLCONTENTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_XHTMLCONTENTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLCONTENTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_PLAINTEXTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_PARSERUTILS_CID);
@@ -1010,17 +1006,16 @@ static const mozilla::Module::CIDEntry k
   { &kNS_CONTENTITERATOR_CID, false, NULL, CreateContentIterator },
   { &kNS_PRECONTENTITERATOR_CID, false, NULL, CreatePreContentIterator },
   { &kNS_SUBTREEITERATOR_CID, false, NULL, CreateSubtreeIterator },
   { &kNS_HTMLIMAGEELEMENT_CID, false, NULL, CreateHTMLImgElement },
   { &kNS_HTMLOPTIONELEMENT_CID, false, NULL, CreateHTMLOptionElement },
 #ifdef MOZ_MEDIA
   { &kNS_HTMLAUDIOELEMENT_CID, false, NULL, CreateHTMLAudioElement },
 #endif
-  { &kNS_CANVASRENDERINGCONTEXT2D_CID, false, NULL, CreateCanvasRenderingContext2D },
   { &kNS_CANVASRENDERINGCONTEXTWEBGL_CID, false, NULL, CreateCanvasRenderingContextWebGL },
   { &kNS_TEXT_ENCODER_CID, false, NULL, CreateTextEncoder },
   { &kNS_HTMLCOPY_TEXT_ENCODER_CID, false, NULL, CreateHTMLCopyTextEncoder },
   { &kNS_XMLCONTENTSERIALIZER_CID, false, NULL, CreateXMLContentSerializer },
   { &kNS_HTMLCONTENTSERIALIZER_CID, false, NULL, CreateHTMLContentSerializer },
   { &kNS_XHTMLCONTENTSERIALIZER_CID, false, NULL, CreateXHTMLContentSerializer },
   { &kNS_PLAINTEXTSERIALIZER_CID, false, NULL, CreatePlainTextSerializer },
   { &kNS_PARSERUTILS_CID, false, NULL, nsParserUtilsConstructor },
@@ -1157,17 +1152,16 @@ static const mozilla::Module::ContractID
   { "@mozilla.org/content/post-content-iterator;1", &kNS_CONTENTITERATOR_CID },
   { "@mozilla.org/content/pre-content-iterator;1", &kNS_PRECONTENTITERATOR_CID },
   { "@mozilla.org/content/subtree-content-iterator;1", &kNS_SUBTREEITERATOR_CID },
   { NS_HTMLIMGELEMENT_CONTRACTID, &kNS_HTMLIMAGEELEMENT_CID },
   { NS_HTMLOPTIONELEMENT_CONTRACTID, &kNS_HTMLOPTIONELEMENT_CID },
 #ifdef MOZ_MEDIA
   { NS_HTMLAUDIOELEMENT_CONTRACTID, &kNS_HTMLAUDIOELEMENT_CID },
 #endif
-  { "@mozilla.org/content/canvas-rendering-context;1?id=2d", &kNS_CANVASRENDERINGCONTEXT2D_CID },
   { "@mozilla.org/content/canvas-rendering-context;1?id=moz-webgl", &kNS_CANVASRENDERINGCONTEXTWEBGL_CID },
   { "@mozilla.org/content/canvas-rendering-context;1?id=experimental-webgl", &kNS_CANVASRENDERINGCONTEXTWEBGL_CID },
   { NS_DOC_ENCODER_CONTRACTID_BASE "text/xml", &kNS_TEXT_ENCODER_CID },
   { NS_DOC_ENCODER_CONTRACTID_BASE "application/xml", &kNS_TEXT_ENCODER_CID },
   { NS_DOC_ENCODER_CONTRACTID_BASE "application/xhtml+xml", &kNS_TEXT_ENCODER_CID },
   { NS_DOC_ENCODER_CONTRACTID_BASE "image/svg+xml", &kNS_TEXT_ENCODER_CID },
   { NS_DOC_ENCODER_CONTRACTID_BASE "text/html", &kNS_TEXT_ENCODER_CID },
   { NS_DOC_ENCODER_CONTRACTID_BASE "text/plain", &kNS_TEXT_ENCODER_CID },
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -1450,16 +1450,17 @@ nsGfxScrollFrameInner::nsGfxScrollFrameI
   , mHadNonInitialReflow(false)
   , mHorizontalOverflow(false)
   , mVerticalOverflow(false)
   , mPostedReflowCallback(false)
   , mMayHaveDirtyFixedChildren(false)
   , mUpdateScrollbarAttributes(false)
   , mCollapsedResizer(false)
   , mShouldBuildLayer(false)
+  , mHasBeenScrolled(false)
 {
   mScrollingActive = IsAlwaysActive();
 
   if (LookAndFeel::GetInt(LookAndFeel::eIntID_ShowHideScrollbars) != 0) {
     mScrollbarActivity = new ScrollbarActivity(do_QueryFrame(aOuter));
   }
 }
 
@@ -1735,21 +1736,33 @@ bool nsGfxScrollFrameInner::ShouldClampS
     return true;
   nsSubDocumentFrame* subdocFrame = static_cast<nsSubDocumentFrame*>
     (nsLayoutUtils::GetCrossDocParentFrame(mOuter->PresContext()->PresShell()->GetRootFrame()));
   return !subdocFrame || subdocFrame->ShouldClampScrollPosition();
 }
 
 bool nsGfxScrollFrameInner::IsAlwaysActive() const
 {
-  // The root scrollframe for a non-chrome document which is the direct
-  // child of a chrome document is always treated as "active".
-  // XXX maybe we should extend this so that IFRAMEs which are fill the
-  // entire viewport (like GMail!) are always active
-  return mIsRoot && mOuter->PresContext()->IsRootContentDocument();
+  // Unless this is the root scrollframe for a non-chrome document 
+  // which is the direct child of a chrome document, we default to not
+  // being "active".
+  if (!(mIsRoot && mOuter->PresContext()->IsRootContentDocument())) {
+     return false;
+  }
+
+  // If we have scrolled before, then we should stay active.
+  if (mHasBeenScrolled) {
+   return true;
+  }
+ 
+  // If we're overflow:hidden, then start as inactive until
+  // we get scrolled manually.
+  ScrollbarStyles styles = GetScrollbarStylesFromFrame();
+  return (styles.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN &&
+          styles.mVertical != NS_STYLE_OVERFLOW_HIDDEN);
 }
 
 void nsGfxScrollFrameInner::MarkInactive()
 {
   if (IsAlwaysActive() || !mScrollingActive)
     return;
 
   mScrollingActive = false;
@@ -1769,16 +1782,22 @@ void nsGfxScrollFrameInner::MarkActive()
       gScrollFrameActivityTracker = new ScrollFrameActivityTracker();
     }
     gScrollFrameActivityTracker->AddObject(this);
   }
 }
 
 void nsGfxScrollFrameInner::ScrollVisual(nsPoint aOldScrolledFramePos)
 {
+  // Mark this frame as having been scrolled. If this is the root
+  // scroll frame of a content document, then IsAlwaysActive()
+  // will return true from now on and MarkInactive() won't
+  // have any effect.
+  mHasBeenScrolled = true;
+
   AdjustViews(mScrolledFrame);
   // We need to call this after fixing up the view positions
   // to be consistent with the frame hierarchy.
   bool invalidate = false;
   bool canScrollWithBlitting = CanScrollWithBlitting(mOuter);
   mOuter->RemoveStateBits(NS_SCROLLFRAME_INVALIDATE_CONTENTS_ON_SCROLL);
   if (IsScrollingActive()) {
     if (!canScrollWithBlitting) {
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -329,16 +329,19 @@ public:
   bool mScrollingActive:1;
   // If true, the resizer is collapsed and not displayed
   bool mCollapsedResizer:1;
 
   // If true, the layer should always be active because we always build a layer.
   // Used for asynchronous scrolling.
   bool mShouldBuildLayer:1;
 
+  // True if this frame has been scrolled at least once
+  bool mHasBeenScrolled:1;
+
 protected:
   void ScrollToWithOrigin(nsPoint aScrollPosition,
                           nsIScrollableFrame::ScrollMode aMode,
                           nsIAtom *aOrigin, // nullptr indicates "other" origin
                           const nsRect* aRange);
 };
 
 /**
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -47,17 +47,17 @@ public:
     nsRegion result;
     if (canvas->GetIsOpaque()) {
       result = GetBounds(aBuilder, aSnap);
     }
     return result;
   }
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
-    *aSnap = false;
+    *aSnap = true;
     nsHTMLCanvasFrame* f = static_cast<nsHTMLCanvasFrame*>(GetUnderlyingFrame());
     return f->GetInnerArea() + ToReferenceFrame();
   }
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerParameters& aContainerParameters)
   {
--- a/layout/generic/nsImageFrame.h
+++ b/layout/generic/nsImageFrame.h
@@ -372,16 +372,21 @@ public:
    */
   virtual already_AddRefed<ImageContainer> GetContainer() MOZ_OVERRIDE;
 
   gfxRect GetDestRect();
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerParameters& aParameters) MOZ_OVERRIDE;
+  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE
+  {
+    *aSnap = true;
+    return nsRect(ToReferenceFrame(), GetUnderlyingFrame()->GetSize());
+  }
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerParameters& aContainerParameters) MOZ_OVERRIDE;
 
   /**
    * Configure an ImageLayer for this display item.
    * Set the required filter and scaling transform.
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -1028,17 +1028,17 @@ nsDisplayPluginVideo::ComputeVisibility(
                                           aAllowVisibleRegionExpansion);
 }
 
 #endif
 
 nsRect
 nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
 {
-  *aSnap = false;
+  *aSnap = true;
   return GetDisplayItemBounds(aBuilder, this, mFrame);
 }
 
 void
 nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
                        nsRenderingContext* aCtx)
 {
   nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -325,17 +325,17 @@ public:
   // updated asynchronously from decoder threads, and it's possible that
   // we might have an opaque video frame when GetOpaqueRegion is called, but
   // when we come to paint, the video frame is transparent or has gone
   // away completely (e.g. because of a decoder error). The problem would
   // be especially acute if we have off-main-thread rendering.
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
   {
-    *aSnap = false;
+    *aSnap = true;
     nsIFrame* f = GetUnderlyingFrame();
     return f->GetContentRect() - f->GetPosition() + ToReferenceFrame();
   }
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerParameters& aContainerParameters)
   {
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -653,23 +653,25 @@ RenderFrameParent::BuildLayer(nsDisplayL
 {
   NS_ABORT_IF_FALSE(aFrame,
                     "makes no sense to have a shadow tree without a frame");
   NS_ABORT_IF_FALSE(!mContainer ||
                     IsTempLayerManager(aManager) ||
                     mContainer->Manager() == aManager,
                     "retaining manager changed out from under us ... HELP!");
 
-  if (mContainer && mContainer->Manager() != aManager) {
+  if (IsTempLayerManager(aManager) ||
+      (mContainer && mContainer->Manager() != aManager)) {
     // This can happen if aManager is a "temporary" manager, or if the
     // widget's layer manager changed out from under us.  We need to
     // FIXME handle the former case somehow, probably with an API to
     // draw a manager's subtree.  The latter is bad bad bad, but the
     // the NS_ABORT_IF_FALSE() above will flag it.  Returning NULL
     // here will just cause the shadow subtree not to be rendered.
+    NS_WARNING("Remote iframe not rendered");
     return nullptr;
   }
 
   uint64_t id = GetLayerTreeId();
   if (0 != id) {
     MOZ_ASSERT(!GetRootLayer());
 
     nsRefPtr<Layer> layer =
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -676,17 +676,17 @@ fails-if(Android) != 376532-3.html 37653
 == 378535-1.html 378535-1-ref.html
 == 378933-1.html 378933-1-ref.html
 == 378935-1.html 378935-1-ref.html
 == 378937-1.html 378937-1-ref.html
 == 379178-xhtml.xhtml 379178-xhtml-ref.xhtml
 == 379178-html.html 379178-html-ref.html
 == 379178-svg.svg 379178-svg-ref.svg
 == 379316-1.html 379316-1-ref.html
-fails-if(Android) random-if(cocoaWidget) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 379316-2.html 379316-2-ref.html # bug 379786
+fails-if(Android) random-if(cocoaWidget) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fuzzy-if(gtk2Widget,1,191) == 379316-2.html 379316-2-ref.html # bug 379786
 == 379328-1.html 379328-1-ref.html
 # The next set of reftests all fail until bug 724978 has been fixed, and the
 # overflow container ability of nsColumnSetFrame is restored.
 fails == 379349-1a.xhtml 379349-1-ref.xhtml
 fails == 379349-1b.xhtml 379349-1-ref.xhtml
 fails == 379349-1c.xhtml 379349-1-ref.xhtml
 fails == 379349-2a.xhtml 379349-2-ref.xhtml
 fails == 379349-2b.xhtml 379349-2-ref.xhtml
--- a/layout/xul/base/src/nsImageBoxFrame.h
+++ b/layout/xul/base/src/nsImageBoxFrame.h
@@ -127,16 +127,21 @@ public:
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayXULImage() {
     MOZ_COUNT_DTOR(nsDisplayXULImage);
   }
 #endif
 
   virtual already_AddRefed<ImageContainer> GetContainer() MOZ_OVERRIDE;
   virtual void ConfigureLayer(ImageLayer* aLayer, const nsIntPoint& aOffset) MOZ_OVERRIDE;
+  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
+  {
+    *aSnap = true;
+    return nsRect(ToReferenceFrame(), GetUnderlyingFrame()->GetSize());
+  }
 
   // Doesn't handle HitTest because nsLeafBoxFrame already creates an
   // event receiver for us
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      nsRenderingContext* aCtx);
   NS_DISPLAY_DECL_NAME("XULImage", TYPE_XUL_IMAGE)
 };
 
--- a/layout/xul/base/src/nsMenuPopupFrame.cpp
+++ b/layout/xul/base/src/nsMenuPopupFrame.cpp
@@ -266,16 +266,17 @@ nsMenuPopupFrame::CreateWidgetForView(ns
   nsTransparencyMode mode = nsLayoutUtils::GetFrameTransparency(this, this);
   bool viewHasTransparentContent = !mInContentShell &&
                                      (eTransparencyTransparent ==
                                       mode);
   nsIContent* parentContent = GetContent()->GetParent();
   nsIAtom *tag = nullptr;
   if (parentContent)
     tag = parentContent->Tag();
+  widgetData.mSupportTranslucency = mode == eTransparencyTransparent;
   widgetData.mDropShadow = !(viewHasTransparentContent || tag == nsGkAtoms::menulist);
   widgetData.mPopupLevel = PopupLevel(widgetData.mNoAutoHide);
 
   // panels which have a parent level need a parent widget. This allows them to
   // always appear in front of the parent window but behind other windows that
   // should be in front of it.
   nsCOMPtr<nsIWidget> parentWidget;
   if (widgetData.mPopupLevel != ePopupLevelTop) {
--- a/media/libcubeb/README_MOZILLA
+++ b/media/libcubeb/README_MOZILLA
@@ -1,11 +1,8 @@
 The source from this directory was copied from the cubeb 
 git repository using the update.sh script.  The only changes
 made were those applied by update.sh and the addition of
 Makefile.in build files for the Mozilla build system.
 
 The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
 
-The git commit ID used was 2d7d3e8f2ecabb70d2723f3c86fcb591a84b7f85.
-Plus the single commit f4c927fb1c2dc0a0580d0bca4bd267c34febada4.
-Plus the single commit 1e54b689752a1e853828cb4124985d3160694913.
-Plus the single commit e5837ecbb2389abd7e6635f4339878c5e4c1e1d5.
+The git commit ID used was 6e9ffc59202f95f09e5adb895d10eaedf36a6ea2.
--- a/media/libcubeb/src/cubeb_alsa.c
+++ b/media/libcubeb/src/cubeb_alsa.c
@@ -13,17 +13,18 @@
 #include <limits.h>
 #include <poll.h>
 #include <unistd.h>
 #include <alsa/asoundlib.h>
 #include "cubeb/cubeb.h"
 
 #define CUBEB_STREAM_MAX 16
 #define CUBEB_WATCHDOG_MS 10000
-#define UNUSED __attribute__ ((__unused__))
+
+#define CUBEB_ALSA_PCM_NAME "default"
 
 #define ALSA_PA_PLUGIN "ALSA <-> PulseAudio PCM I/O Plugin"
 
 /* ALSA is not thread-safe.  snd_pcm_t instances are individually protected
    by the owning cubeb_stream's mutex.  snd_pcm_t creation and destruction
    is not thread-safe until ALSA 1.0.24 (see alsa-lib.git commit 91c9c8f1),
    so those calls must be wrapped in the following mutex. */
 static pthread_mutex_t cubeb_alsa_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -47,16 +48,22 @@ struct cubeb {
 
   /* Control pipe for forcing poll to wake and rebuild fds or recalculate the timeout. */
   int control_fd_read;
   int control_fd_write;
 
   /* Track number of active streams.  This is limited to CUBEB_STREAM_MAX
      due to resource contraints. */
   unsigned int active_streams;
+
+  /* Local configuration with handle_underrun workaround set for PulseAudio
+     ALSA plugin.  Will be NULL if the PA ALSA plugin is not in use or the
+     workaround is not required. */
+  snd_config_t * local_config;
+  int is_pa;
 };
 
 enum stream_state {
   INACTIVE,
   RUNNING,
   DRAINING,
   PROCESSING,
   ERROR
@@ -406,23 +413,175 @@ cubeb_run_thread(void * context)
 
   do {
     r = cubeb_run(ctx);
   } while (r >= 0);
 
   return NULL;
 }
 
+static snd_config_t *
+get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm)
+{
+  int r;
+  snd_config_t * slave_pcm;
+  snd_config_t * slave_def;
+  snd_config_t * pcm;
+  char const * string;
+  char node_name[64];
+
+  slave_def = NULL;
+
+  r = snd_config_search(root_pcm, "slave", &slave_pcm);
+  if (r < 0) {
+    return NULL;
+  }
+
+  r = snd_config_get_string(slave_pcm, &string);
+  if (r >= 0) {
+    r = snd_config_search_definition(lconf, "pcm_slave", string, &slave_def);
+    if (r < 0) {
+      return NULL;
+    }
+  }
+
+  do {
+    r = snd_config_search(slave_def ? slave_def : slave_pcm, "pcm", &pcm);
+    if (r < 0) {
+      break;
+    }
+
+    r = snd_config_get_string(slave_def ? slave_def : slave_pcm, &string);
+    if (r < 0) {
+      break;
+    }
+
+    r = snprintf(node_name, sizeof(node_name), "pcm.%s", string);
+    if (r < 0 || r > (int) sizeof(node_name)) {
+      break;
+    }
+    r = snd_config_search(lconf, node_name, &pcm);
+    if (r < 0) {
+      break;
+    }
+
+    return pcm;
+  } while (0);
+
+  if (slave_def) {
+    snd_config_delete(slave_def);
+  }
+
+  return NULL;
+}
+
+/* Work around PulseAudio ALSA plugin bug where the PA server forces a
+   higher than requested latency, but the plugin does not update its (and
+   ALSA's) internal state to reflect that, leading to an immediate underrun
+   situation.  Inspired by WINE's make_handle_underrun_config.
+   Reference: http://mailman.alsa-project.org/pipermail/alsa-devel/2012-July/05 */
+static snd_config_t *
+init_local_config_with_workaround(char const * pcm_name)
+{
+  int r;
+  snd_config_t * lconf;
+  snd_config_t * pcm_node;
+  snd_config_t * node;
+  char const * string;
+  char node_name[64];
+
+  lconf = NULL;
+
+  if (snd_config == NULL) {
+    return NULL;
+  }
+
+  r = snd_config_copy(&lconf, snd_config);
+  if (r < 0) {
+    return NULL;
+  }
+
+  do {
+    r = snd_config_search_definition(lconf, "pcm", pcm_name, &pcm_node);
+    if (r < 0) {
+      break;
+    }
+
+    r = snd_config_get_id(pcm_node, &string);
+    if (r < 0) {
+      break;
+    }
+
+    r = snprintf(node_name, sizeof(node_name), "pcm.%s", string);
+    if (r < 0 || r > (int) sizeof(node_name)) {
+      break;
+    }
+    r = snd_config_search(lconf, node_name, &pcm_node);
+    if (r < 0) {
+      break;
+    }
+
+    /* If this PCM has a slave, walk the slave configurations until we reach the bottom. */
+    while ((node = get_slave_pcm_node(lconf, pcm_node)) != NULL) {
+      pcm_node = node;
+    }
+
+    /* Fetch the PCM node's type, and bail out if it's not the PulseAudio plugin. */
+    r = snd_config_search(pcm_node, "type", &node);
+    if (r < 0) {
+      break;
+    }
+
+    r = snd_config_get_string(node, &string);
+    if (r < 0) {
+      break;
+    }
+
+    if (strcmp(string, "pulse") != 0) {
+      break;
+    }
+
+    /* Don't clobber an explicit existing handle_underrun value, set it only
+       if it doesn't already exist. */
+    r = snd_config_search(pcm_node, "handle_underrun", &node);
+    if (r != -ENOENT) {
+      break;
+    }
+
+    /* Disable pcm_pulse's asynchronous underrun handling. */
+    r = snd_config_imake_integer(&node, "handle_underrun", 0);
+    if (r < 0) {
+      break;
+    }
+
+    r = snd_config_add(pcm_node, node);
+    if (r < 0) {
+      break;
+    }
+
+    return lconf;
+  } while (0);
+
+  snd_config_delete(lconf);
+
+  return NULL;
+}
+
+
 static int
-cubeb_locked_pcm_open(snd_pcm_t ** pcm, snd_pcm_stream_t stream)
+cubeb_locked_pcm_open(snd_pcm_t ** pcm, snd_pcm_stream_t stream, snd_config_t * local_config)
 {
   int r;
 
   pthread_mutex_lock(&cubeb_alsa_mutex);
-  r = snd_pcm_open(pcm, "default", stream, SND_PCM_NONBLOCK);
+  if (local_config) {
+    r = snd_pcm_open_lconf(pcm, CUBEB_ALSA_PCM_NAME, stream, SND_PCM_NONBLOCK, local_config);
+  } else {
+    r = snd_pcm_open(pcm, CUBEB_ALSA_PCM_NAME, stream, SND_PCM_NONBLOCK);
+  }
   pthread_mutex_unlock(&cubeb_alsa_mutex);
 
   return r;
 }
 
 static int
 cubeb_locked_pcm_close(snd_pcm_t * pcm)
 {
@@ -466,47 +625,30 @@ cubeb_unregister_stream(cubeb_stream * s
       ctx->streams[i] = NULL;
       break;
     }
   }
   pthread_mutex_unlock(&ctx->mutex);
 }
 
 static void
-silent_error_handler(char const * file UNUSED, int line UNUSED, char const * function UNUSED,
-                     int err UNUSED, char const * fmt UNUSED, ...)
+silent_error_handler(char const * file, int line, char const * function,
+                     int err, char const * fmt, ...)
 {
 }
 
-static int
-pcm_uses_pulseaudio_plugin(snd_pcm_t * pcm)
-{
-  snd_output_t * out;
-  char * buf;
-  size_t bufsz;
-  int r;
-
-  snd_output_buffer_open(&out);
-  snd_pcm_dump(pcm, out);
-  bufsz = snd_output_buffer_string(out, &buf);
-  r = bufsz >= strlen(ALSA_PA_PLUGIN) &&
-      strncmp(buf, ALSA_PA_PLUGIN, strlen(ALSA_PA_PLUGIN)) == 0;
-  snd_output_close(out);
-
-  return r;
-}
-
 int
-cubeb_init(cubeb ** context, char const * context_name UNUSED)
+cubeb_init(cubeb ** context, char const * context_name)
 {
   cubeb * ctx;
   int r;
   int i;
   int fd[2];
   pthread_attr_t attr;
+  snd_pcm_t * dummy;
 
   assert(context);
   *context = NULL;
 
   pthread_mutex_lock(&cubeb_alsa_mutex);
   if (!cubeb_alsa_error_handler_set) {
     snd_lib_error_set_handler(silent_error_handler);
     cubeb_alsa_error_handler_set = 1;
@@ -541,23 +683,48 @@ cubeb_init(cubeb ** context, char const 
   assert(r == 0);
 
   r = pthread_create(&ctx->thread, &attr, cubeb_run_thread, ctx);
   assert(r == 0);
 
   r = pthread_attr_destroy(&attr);
   assert(r == 0);
 
+  /* Open a dummy PCM to force the configuration space to be evaluated so that
+     init_local_config_with_workaround can find and modify the default node. */
+  r = cubeb_locked_pcm_open(&dummy, SND_PCM_STREAM_PLAYBACK, NULL);
+  if (r >= 0) {
+    cubeb_locked_pcm_close(dummy);
+  }
+  ctx->is_pa = 0;
+  pthread_mutex_lock(&cubeb_alsa_mutex);
+  ctx->local_config = init_local_config_with_workaround(CUBEB_ALSA_PCM_NAME);
+  pthread_mutex_unlock(&cubeb_alsa_mutex);
+  if (ctx->local_config) {
+    ctx->is_pa = 1;
+    r = cubeb_locked_pcm_open(&dummy, SND_PCM_STREAM_PLAYBACK, ctx->local_config);
+    /* If we got a local_config, we found a PA PCM.  If opening a PCM with that
+       config fails with EINVAL, the PA PCM is too old for this workaround. */
+    if (r == -EINVAL) {
+      pthread_mutex_lock(&cubeb_alsa_mutex);
+      snd_config_delete(ctx->local_config);
+      pthread_mutex_unlock(&cubeb_alsa_mutex);
+      ctx->local_config = NULL;
+    } else if (r >= 0) {
+      cubeb_locked_pcm_close(dummy);
+    }
+  }
+
   *context = ctx;
 
   return CUBEB_OK;
 }
 
 char const *
-cubeb_get_backend_id(cubeb * ctx UNUSED)
+cubeb_get_backend_id(cubeb * ctx)
 {
   return "alsa";
 }
 
 void
 cubeb_destroy(cubeb * ctx)
 {
   int r;
@@ -572,21 +739,27 @@ cubeb_destroy(cubeb * ctx)
   r = pthread_join(ctx->thread, NULL);
   assert(r == 0);
 
   close(ctx->control_fd_read);
   close(ctx->control_fd_write);
   pthread_mutex_destroy(&ctx->mutex);
   free(ctx->fds);
 
+  if (ctx->local_config) {
+    pthread_mutex_lock(&cubeb_alsa_mutex);
+    snd_config_delete(ctx->local_config);
+    pthread_mutex_unlock(&cubeb_alsa_mutex);
+  }
+
   free(ctx);
 }
 
 int
-cubeb_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name UNUSED,
+cubeb_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name,
                   cubeb_stream_params stream_params, unsigned int latency,
                   cubeb_data_callback data_callback, cubeb_state_callback state_callback,
                   void * user_ptr)
 {
   cubeb_stream * stm;
   int r;
   snd_pcm_format_t format;
 
@@ -633,29 +806,30 @@ cubeb_stream_init(cubeb * ctx, cubeb_str
   stm->state_callback = state_callback;
   stm->user_ptr = user_ptr;
   stm->params = stream_params;
   stm->state = INACTIVE;
 
   r = pthread_mutex_init(&stm->mutex, NULL);
   assert(r == 0);
 
-  r = cubeb_locked_pcm_open(&stm->pcm, SND_PCM_STREAM_PLAYBACK);
+  r = cubeb_locked_pcm_open(&stm->pcm, SND_PCM_STREAM_PLAYBACK, ctx->local_config);
   if (r < 0) {
     cubeb_stream_destroy(stm);
     return CUBEB_ERROR;
   }
 
   r = snd_pcm_nonblock(stm->pcm, 1);
   assert(r == 0);
 
   /* Ugly hack: the PA ALSA plugin allows buffer configurations that can't
-     possibly work.  See https://bugzilla.mozilla.org/show_bug.cgi?id=761274 */
-  if (pcm_uses_pulseaudio_plugin(stm->pcm)) {
-    latency = latency < 200 ? 200 : latency;
+     possibly work.  See https://bugzilla.mozilla.org/show_bug.cgi?id=761274.
+     Only resort to this hack if the handle_underrun workaround failed. */
+  if (!ctx->local_config && ctx->is_pa) {
+    latency = latency < 500 ? 500 : latency;
   }
 
   r = snd_pcm_set_params(stm->pcm, format, SND_PCM_ACCESS_RW_INTERLEAVED,
                          stm->params.channels, stm->params.rate, 1,
                          latency * 1000);
   if (r < 0) {
     cubeb_stream_destroy(stm);
     return CUBEB_ERROR_INVALID_FORMAT;
--- a/media/libcubeb/src/cubeb_winmm.c
+++ b/media/libcubeb/src/cubeb_winmm.c
@@ -28,16 +28,17 @@ struct cubeb_stream_item {
 
 struct cubeb {
   HANDLE event;
   HANDLE thread;
   int shutdown;
   PSLIST_HEADER work;
   CRITICAL_SECTION lock;
   unsigned int active_streams;
+  int minimum_latency;
 };
 
 struct cubeb_stream {
   cubeb * context;
   cubeb_stream_params params;
   cubeb_data_callback data_callback;
   cubeb_state_callback state_callback;
   void * user_ptr;
@@ -185,16 +186,44 @@ cubeb_buffer_callback(HWAVEOUT waveout, 
   item = _aligned_malloc(sizeof(struct cubeb_stream_item), MEMORY_ALLOCATION_ALIGNMENT);
   assert(item);
   item->stream = stm;
   InterlockedPushEntrySList(stm->context->work, &item->head);
 
   SetEvent(stm->context->event);
 }
 
+static int
+calculate_minimum_latency(void)
+{
+  OSVERSIONINFOEX osvi;
+  DWORDLONG mask;
+
+  /* Vista's WinMM implementation underruns when less than 200ms of audio is buffered. */
+  memset(&osvi, 0, sizeof(OSVERSIONINFOEX));
+  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+  osvi.dwMajorVersion = 6;
+  osvi.dwMinorVersion = 0;
+
+  mask = 0;
+  VER_SET_CONDITION(mask, VER_MAJORVERSION, VER_EQUAL);
+  VER_SET_CONDITION(mask, VER_MINORVERSION, VER_EQUAL);
+
+  if (VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, mask) != 0) {
+    return 200;
+  }
+
+  /* Running under Terminal Services results in underruns with low latency. */
+  if (GetSystemMetrics(SM_REMOTESESSION) == TRUE) {
+    return 500;
+  }
+
+  return 0;
+}
+
 int
 cubeb_init(cubeb ** context, char const * context_name)
 {
   cubeb * ctx;
 
   assert(context);
   *context = NULL;
 
@@ -217,16 +246,18 @@ cubeb_init(cubeb ** context, char const 
     return CUBEB_ERROR;
   }
 
   SetThreadPriority(ctx->thread, THREAD_PRIORITY_TIME_CRITICAL);
 
   InitializeCriticalSection(&ctx->lock);
   ctx->active_streams = 0;
 
+  ctx->minimum_latency = calculate_minimum_latency();
+
   *context = ctx;
 
   return CUBEB_OK;
 }
 
 char const *
 cubeb_get_backend_id(cubeb * ctx)
 {
@@ -337,16 +368,20 @@ cubeb_stream_init(cubeb * context, cubeb
   stm->context = context;
 
   stm->params = stream_params;
 
   stm->data_callback = data_callback;
   stm->state_callback = state_callback;
   stm->user_ptr = user_ptr;
 
+  if (latency < context->minimum_latency) {
+    latency = context->minimum_latency;
+  }
+
   bufsz = (size_t) (stm->params.rate / 1000.0 * latency * bytes_per_frame(stm->params) / NBUFS);
   if (bufsz % bytes_per_frame(stm->params) != 0) {
     bufsz += bytes_per_frame(stm->params) - (bufsz % bytes_per_frame(stm->params));
   }
   assert(bufsz % bytes_per_frame(stm->params) == 0);
 
   stm->buffer_size = bufsz;
 
--- a/memory/mozjemalloc/jemalloc.c
+++ b/memory/mozjemalloc/jemalloc.c
@@ -1380,17 +1380,17 @@ static void	chunk_dealloc(void *chunk, s
 static arena_t	*choose_arena_hard(void);
 #endif
 static void	arena_run_split(arena_t *arena, arena_run_t *run, size_t size,
     bool large, bool zero);
 static void arena_chunk_init(arena_t *arena, arena_chunk_t *chunk);
 static void	arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk);
 static arena_run_t *arena_run_alloc(arena_t *arena, arena_bin_t *bin,
     size_t size, bool large, bool zero);
-static void	arena_purge(arena_t *arena);
+static void	arena_purge(arena_t *arena, bool all);
 static void	arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty);
 static void	arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk,
     arena_run_t *run, size_t oldsize, size_t newsize);
 static void	arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk,
     arena_run_t *run, size_t oldsize, size_t newsize, bool dirty);
 static arena_run_t *arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin);
 static void *arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin);
 static size_t arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size);
@@ -3589,41 +3589,43 @@ arena_run_alloc(arena_t *arena, arena_bi
 		    (arena_chunk_header_npages << pagesize_2pow));
 	}
 	/* Update page map. */
 	arena_run_split(arena, run, size, large, zero);
 	return (run);
 }
 
 static void
-arena_purge(arena_t *arena)
+arena_purge(arena_t *arena, bool all)
 {
 	arena_chunk_t *chunk;
 	size_t i, npages;
+	/* If all is set purge all dirty pages. */
+	size_t dirty_max = all ? 1 : opt_dirty_max;
 #ifdef MALLOC_DEBUG
 	size_t ndirty = 0;
 	rb_foreach_begin(arena_chunk_t, link_dirty, &arena->chunks_dirty,
 	    chunk) {
 		ndirty += chunk->ndirty;
 	} rb_foreach_end(arena_chunk_t, link_dirty, &arena->chunks_dirty, chunk)
 	assert(ndirty == arena->ndirty);
 #endif
-	RELEASE_ASSERT(arena->ndirty > opt_dirty_max);
+	RELEASE_ASSERT(all || (arena->ndirty > opt_dirty_max));
 
 #ifdef MALLOC_STATS
 	arena->stats.npurge++;
 #endif
 
 	/*
 	 * Iterate downward through chunks until enough dirty memory has been
 	 * purged.  Terminate as soon as possible in order to minimize the
 	 * number of system calls, even if a chunk has only been partially
 	 * purged.
 	 */
-	while (arena->ndirty > (opt_dirty_max >> 1)) {
+	while (arena->ndirty > (dirty_max >> 1)) {
 #ifdef MALLOC_DOUBLE_PURGE
 		bool madvised = false;
 #endif
 		chunk = arena_chunk_tree_dirty_last(&arena->chunks_dirty);
 		RELEASE_ASSERT(chunk != NULL);
 
 		for (i = chunk_npages - 1; chunk->ndirty > 0; i--) {
 			RELEASE_ASSERT(i >= arena_chunk_header_npages);
@@ -3670,17 +3672,17 @@ arena_purge(arena_t *arena)
 #  ifdef MALLOC_DOUBLE_PURGE
 				madvised = true;
 #  endif
 #endif
 #ifdef MALLOC_STATS
 				arena->stats.nmadvise++;
 				arena->stats.purged += npages;
 #endif
-				if (arena->ndirty <= (opt_dirty_max >> 1))
+				if (arena->ndirty <= (dirty_max >> 1))
 					break;
 			}
 		}
 
 		if (chunk->ndirty == 0) {
 			arena_chunk_tree_dirty_remove(&arena->chunks_dirty,
 			    chunk);
 		}
@@ -3795,17 +3797,17 @@ arena_run_dalloc(arena_t *arena, arena_r
 
 	/* Deallocate chunk if it is now completely unused. */
 	if ((chunk->map[arena_chunk_header_npages].bits & (~pagesize_mask |
 	    CHUNK_MAP_ALLOCATED)) == arena_maxclass)
 		arena_chunk_dealloc(arena, chunk);
 
 	/* Enforce opt_dirty_max. */
 	if (arena->ndirty > opt_dirty_max)
-		arena_purge(arena);
+		arena_purge(arena, false);
 }
 
 static void
 arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
     size_t oldsize, size_t newsize)
 {
 	size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> pagesize_2pow;
 	size_t head_npages = (oldsize - newsize) >> pagesize_2pow;
@@ -6849,16 +6851,31 @@ void*
 size_t
 _msize(const void *ptr)
 {
 
 	return malloc_usable_size(ptr);
 }
 #endif
 
+void
+jemalloc_free_dirty_pages(void)
+{
+	size_t i;
+	for (i = 0; i < narenas; i++) {
+		arena_t *arena = arenas[i];
+
+		if (arena != NULL) {
+			malloc_spin_lock(&arena->lock);
+			arena_purge(arena, true);
+			malloc_spin_unlock(&arena->lock);
+		}
+	}
+}
+
 /*
  * End non-standard functions.
  */
 /******************************************************************************/
 /*
  * Begin library-private functions, used by threading libraries for protection
  * of malloc during fork().  These functions are only called if the program is
  * running in threaded mode, so there is no need to check whether the program
--- a/memory/mozjemalloc/jemalloc.h
+++ b/memory/mozjemalloc/jemalloc.h
@@ -111,15 +111,29 @@ static inline size_t je_malloc_usable_si
  * If MALLOC_DOUBLE_PURGE is not defined, this function does nothing.
  */
 #if defined(MOZ_MEMORY_LINUX) || defined(MOZ_JEMALLOC)
 static inline void jemalloc_purge_freed_pages() { }
 #else
 void    jemalloc_purge_freed_pages();
 #endif
 
+/*
+ * Free all unused dirty pages in all arenas. Calling this function will slow
+ * down subsequent allocations so it is recommended to use it only when
+ * memory needs to be reclaimed at all costs (see bug 805855). This function
+ * provides functionality similar to mallctl("arenas.purge") in jemalloc 3.
+ */
+
+#if !defined(MOZ_NATIVE_JEMALLOC)
+#if defined(MOZ_MEMORY_LINUX) || defined(MOZ_MEMORY_BSD)
+__attribute__((weak))
+#endif /* defined(MOZ_MEMORY_LINUX) || defined(MOZ_MEMORY_BSD) */
+void    jemalloc_free_dirty_pages();
+#endif /* !defined(MOZ_NATIVE_JEMALLOC) */
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
 
 #undef wrap
 
 #endif /* _JEMALLOC_H_ */
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -724,16 +724,17 @@ abstract public class GeckoApp
         int dw = Tabs.getThumbnailWidth();
         int dh = Tabs.getThumbnailHeight();
         GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, 0, 0, 0, 0, dw, dh, dw, dh, ScreenshotHandler.SCREENSHOT_THUMBNAIL, tab.getThumbnailBuffer()));
     }
 
     void handleThumbnailData(Tab tab, ByteBuffer data) {
         if (shouldUpdateThumbnail(tab)) {
             Bitmap b = tab.getThumbnailBitmap();
+            data.position(0);
             b.copyPixelsFromBuffer(data);
             processThumbnail(tab, b, null);
         }
     }
 
     void processThumbnail(Tab thumbnailTab, Bitmap bitmap, byte[] compressed) {
         try {
             if (bitmap == null) {
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -92,16 +92,19 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.NoSuchElementException;
 import java.util.StringTokenizer;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.SynchronousQueue;
+import java.net.ProxySelector;
+import java.net.Proxy;
+import java.net.URI;
 
 public class GeckoAppShell
 {
     private static final String LOGTAG = "GeckoAppShell";
 
     // static members only
     private GeckoAppShell() { }
 
@@ -2228,9 +2231,49 @@ public class GeckoAppShell
         GeckoProfile profile = GeckoApp.mAppContext.getProfile();
         File lock = profile.getFile(".parentlock");
         if (lock.exists()) {
             lock.delete();
             return true;
         }
         return false;
     }
+
+    public static String getProxyForURI(String spec, String scheme, String host, int port) {
+        URI uri = null;
+        try {
+            uri = new URI(spec);
+        } catch(java.net.URISyntaxException uriEx) {
+            try {
+                uri = new URI(scheme, null, host, port, null, null, null);
+            } catch(java.net.URISyntaxException uriEx2) {
+                Log.d("GeckoProxy", "Failed to create uri from spec", uriEx);
+                Log.d("GeckoProxy", "Failed to create uri from parts", uriEx2);
+            }
+        }
+        if (uri != null) {
+            ProxySelector ps = ProxySelector.getDefault();
+            if (ps != null) {
+                List<Proxy> proxies = ps.select(uri);
+                if (proxies != null && !proxies.isEmpty()) {
+                    Proxy proxy = proxies.get(0);
+                    if (!Proxy.NO_PROXY.equals(proxy)) {
+                        final String proxyStr;
+                        switch (proxy.type()) {
+                        case HTTP:
+                            proxyStr = "PROXY " + proxy.address().toString();
+                            break;
+                        case SOCKS:
+                            proxyStr = "SOCKS " + proxy.address().toString();
+                            break;
+                        case DIRECT:
+                        default:
+                            proxyStr = "DIRECT";
+                            break;
+                        }
+                        return proxyStr;
+                    }
+                }
+            }
+        }
+        return "DIRECT";
+    }
 }
--- a/mobile/android/base/GeckoEditable.java
+++ b/mobile/android/base/GeckoEditable.java
@@ -29,16 +29,30 @@ interface GeckoEditableClient {
     Editable getEditable();
     void setUpdateGecko(boolean update);
     void setListener(GeckoEditableListener listener);
 }
 
 /* interface for the Editable to listen to the Gecko thread
    and also for the UI thread to listen to the Editable */
 interface GeckoEditableListener {
+    // IME notification type for notifyIME()
+    final int NOTIFY_IME_RESETINPUTSTATE = 0;
+    final int NOTIFY_IME_REPLY_EVENT = 1;
+    final int NOTIFY_IME_CANCELCOMPOSITION = 2;
+    final int NOTIFY_IME_FOCUSCHANGE = 3;
+    // IME focus state for notifyIME(NOTIFY_IME_FOCUSCHANGE, ..)
+    final int IME_FOCUS_STATE_FOCUS = 1;
+    final int IME_FOCUS_STATE_BLUR = 0;
+    // IME enabled state for notifyIMEEnabled()
+    final int IME_STATE_DISABLED = 0;
+    final int IME_STATE_ENABLED = 1;
+    final int IME_STATE_PASSWORD = 2;
+    final int IME_STATE_PLUGIN = 3;
+
     void notifyIME(int type, int state);
     void notifyIMEEnabled(int state, String typeHint,
                           String modeHint, String actionHint);
     void onSelectionChange(int start, int end);
     void onTextChange(String text, int start, int oldEnd, int newEnd);
 }
 
 /*
@@ -47,17 +61,16 @@ interface GeckoEditableListener {
    SpannableStringBuilder/Editable that contains our text.
 */
 final class GeckoEditable
         implements InvocationHandler, Editable,
                    GeckoEditableClient, GeckoEditableListener {
 
     private static final boolean DEBUG = false;
     private static final String LOGTAG = "GeckoEditable";
-    private static final int NOTIFY_IME_REPLY_EVENT = 1;
 
     // Filters to implement Editable's filtering functionality
     private InputFilter[] mFilters;
 
     private final SpannableStringBuilder mText;
     private final Editable mProxy;
     private GeckoEditableListener mListener;
     private final ActionQueue mActionQueue;
@@ -459,16 +472,21 @@ final class GeckoEditable
         if (type == NOTIFY_IME_REPLY_EVENT) {
             geckoActionReply();
             return;
         }
         geckoPostToUI(new Runnable() {
             public void run() {
                 // Make sure there are no other things going on
                 mActionQueue.syncWithGecko();
+                if (type == NOTIFY_IME_FOCUSCHANGE && state != IME_FOCUS_STATE_BLUR) {
+                    // Unmask events on the Gecko side
+                    GeckoAppShell.sendEventToGecko(GeckoEvent.createIMEEvent(
+                            GeckoEvent.IME_ACKNOWLEDGE_FOCUS));
+                }
                 if (mListener != null) {
                     mListener.notifyIME(type, state);
                 }
             }
         });
     }
 
     @Override
@@ -548,24 +566,24 @@ final class GeckoEditable
                 // Replace using saved text to preserve spans
                 mText.replace(start, oldEnd, action.mSequence,
                               0, action.mSequence.length());
             } else {
                 mText.replace(start, oldEnd, text, 0, text.length());
             }
         } else {
             mText.replace(start, oldEnd, text, 0, text.length());
-            geckoPostToUI(new Runnable() {
-                public void run() {
-                    if (mListener != null) {
-                        mListener.onTextChange(text, start, oldEnd, newEnd);
-                    }
+        }
+        geckoPostToUI(new Runnable() {
+            public void run() {
+                if (mListener != null) {
+                    mListener.onTextChange(text, start, oldEnd, newEnd);
                 }
-            });
-        }
+            }
+        });
     }
 
     // InvocationHandler interface
 
     private static StringBuilder debugAppend(StringBuilder sb, Object obj) {
         if (obj == null) {
             sb.append("null");
         } else if (obj instanceof GeckoEditable) {
@@ -635,19 +653,17 @@ final class GeckoEditable
     @Override
     public void removeSpan(Object what) {
         if (what == Selection.SELECTION_START ||
                 what == Selection.SELECTION_END) {
             Log.w(LOGTAG, "selection removed with removeSpan()");
         }
         // Okay to remove immediately
         mText.removeSpan(what);
-        if (mUpdateGecko) {
-            mActionQueue.offer(new Action(Action.TYPE_REMOVE_SPAN));
-        }
+        mActionQueue.offer(new Action(Action.TYPE_REMOVE_SPAN));
     }
 
     @Override
     public void setSpan(Object what, int start, int end, int flags) {
         if (what == Selection.SELECTION_START) {
             if ((flags & Spanned.SPAN_INTERMEDIATE) != 0) {
                 // We will get the end offset next, just save the start for now
                 mSavedSelectionStart = start;
--- a/mobile/android/base/GeckoEvent.java
+++ b/mobile/android/base/GeckoEvent.java
@@ -81,16 +81,17 @@ public class GeckoEvent {
     private static final int DOM_KEY_LOCATION_JOYSTICK = 5;
 
     public static final int IME_SYNCHRONIZE = 0;
     public static final int IME_REPLACE_TEXT = 1;
     public static final int IME_SET_SELECTION = 2;
     public static final int IME_ADD_COMPOSITION_RANGE = 3;
     public static final int IME_UPDATE_COMPOSITION = 4;
     public static final int IME_REMOVE_COMPOSITION = 5;
+    public static final int IME_ACKNOWLEDGE_FOCUS = 6;
 
     public static final int IME_RANGE_CARETPOSITION = 1;
     public static final int IME_RANGE_RAWINPUT = 2;
     public static final int IME_RANGE_SELECTEDRAWTEXT = 3;
     public static final int IME_RANGE_CONVERTEDTEXT = 4;
     public static final int IME_RANGE_SELECTEDCONVERTEDTEXT = 5;
 
     public static final int IME_RANGE_UNDERLINE = 1;
--- a/mobile/android/base/GeckoInputConnection.java
+++ b/mobile/android/base/GeckoInputConnection.java
@@ -34,41 +34,33 @@ import java.util.TimerTask;
 
 class GeckoInputConnection
     extends BaseInputConnection
     implements InputConnectionHandler, GeckoEditableListener {
 
     private static final boolean DEBUG = false;
     protected static final String LOGTAG = "GeckoInputConnection";
 
-    // IME stuff
-    public static final int IME_STATE_DISABLED = 0;
-    public static final int IME_STATE_ENABLED = 1;
-    public static final int IME_STATE_PASSWORD = 2;
-    public static final int IME_STATE_PLUGIN = 3;
-
-    private static final int NOTIFY_IME_RESETINPUTSTATE = 0;
-    private static final int NOTIFY_IME_CANCELCOMPOSITION = 2;
-    private static final int NOTIFY_IME_FOCUSCHANGE = 3;
-
     private static final int INLINE_IME_MIN_DISPLAY_SIZE = 480;
 
     private static final Timer mIMETimer = new Timer("GeckoInputConnection Timer");
 
     private static int mIMEState;
     private static String mIMETypeHint = "";
     private static String mIMEModeHint = "";
     private static String mIMEActionHint = "";
 
     private String mCurrentInputMethod;
 
     private final GeckoEditableClient mEditableClient;
     protected int mBatchEditCount;
     private ExtractedTextRequest mUpdateRequest;
     private final ExtractedText mUpdateExtract = new ExtractedText();
+    private boolean mBatchSelectionChanged;
+    private boolean mBatchTextChanged;
 
     public static InputConnectionHandler create(View targetView,
                                                 GeckoEditableClient editable) {
         if (DEBUG)
             return DebugGeckoInputConnection.create(targetView, editable);
         else
             return new GeckoInputConnection(targetView, editable);
     }
@@ -89,16 +81,26 @@ class GeckoInputConnection
         return true;
     }
 
     @Override
     public synchronized boolean endBatchEdit() {
         if (mBatchEditCount > 0) {
             mBatchEditCount--;
             if (mBatchEditCount == 0) {
+                if (mBatchTextChanged) {
+                    notifyTextChange();
+                    mBatchTextChanged = false;
+                }
+                if (mBatchSelectionChanged) {
+                    Editable editable = getEditable();
+                    notifySelectionChange(Selection.getSelectionStart(editable),
+                                           Selection.getSelectionEnd(editable));
+                    mBatchSelectionChanged = false;
+                }
                 mEditableClient.setUpdateGecko(true);
             }
         } else {
             Log.w(LOGTAG, "endBatchEdit() called, but mBatchEditCount == 0?!");
         }
         return true;
     }
 
@@ -186,48 +188,64 @@ class GeckoInputConnection
             return null;
         }
         Context context = view.getContext();
         return InputMethods.getInputMethodManager(context);
     }
 
     public void onTextChange(String text, int start, int oldEnd, int newEnd) {
 
-        if (mBatchEditCount > 0 || mUpdateRequest == null) {
+        if (mUpdateRequest == null) {
             return;
         }
 
+        if (mBatchEditCount > 0) {
+            // Delay notification until after the batch edit
+            mBatchTextChanged = true;
+            return;
+        }
+        notifyTextChange();
+    }
+
+    private void notifyTextChange() {
+
         final InputMethodManager imm = getInputMethodManager();
         if (imm == null) {
             return;
         }
         final View v = getView();
         final Editable editable = getEditable();
 
         mUpdateExtract.flags = 0;
-        // Update from (0, oldEnd) to (0, newEnd) because some IMEs
-        // assume that updates start at zero, according to jchen.
-        mUpdateExtract.partialStartOffset = 0;
-        mUpdateExtract.partialEndOffset = editable.length();
+        // Update the entire Editable range
+        mUpdateExtract.partialStartOffset = -1;
+        mUpdateExtract.partialEndOffset = -1;
         mUpdateExtract.selectionStart =
                 Selection.getSelectionStart(editable);
         mUpdateExtract.selectionEnd =
                 Selection.getSelectionEnd(editable);
         mUpdateExtract.startOffset = 0;
         mUpdateExtract.text = editable;
 
         imm.updateExtractedText(v, mUpdateRequest.token,
                                 mUpdateExtract);
     }
 
     public void onSelectionChange(int start, int end) {
 
         if (mBatchEditCount > 0) {
+            // Delay notification until after the batch edit
+            mBatchSelectionChanged = true;
             return;
         }
+        notifySelectionChange(start, end);
+    }
+
+    private void notifySelectionChange(int start, int end) {
+
         final InputMethodManager imm = getInputMethodManager();
         if (imm == null) {
             return;
         }
         final View v = getView();
         final Editable editable = getEditable();
         imm.updateSelection(v, start, end, getComposingSpanStart(editable),
                             getComposingSpanEnd(editable));
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -66,17 +66,22 @@
 <!ENTITY pref_category_general "General">
 <!ENTITY pref_category_privacy "Privacy &amp; Security">
 <!ENTITY pref_category_content "Content">
 <!ENTITY pref_category_importexport "Import &amp; Export">
 <!ENTITY pref_about_firefox "About &brandShortName;">
 <!ENTITY pref_do_not_track "Tell sites not to track me">
 <!ENTITY pref_telemetry "Send performance data">
 <!ENTITY pref_remember_signons "Remember passwords">
-<!ENTITY pref_cookies "Enable cookies">
+
+<!ENTITY pref_cookies "Cookies">
+<!ENTITY pref_cookies_accept_all "Enabled">
+<!ENTITY pref_cookies_not_accept_foreign "Enabled, excluding 3rd party">
+<!ENTITY pref_cookies_disabled "Disabled">
+
 <!ENTITY pref_char_encoding "Character encoding">
 <!ENTITY pref_char_encoding_on "Show menu">
 <!ENTITY pref_char_encoding_off "Don\'t show menu">
 <!ENTITY pref_clear_private_data "Clear private data">
 <!ENTITY pref_plugins "Plugins">
 <!ENTITY pref_plugins_enabled "Enabled">
 <!ENTITY pref_plugins_tap_to_play "Tap to play">
 <!ENTITY pref_plugins_disabled "Disabled">
--- a/mobile/android/base/resources/values/arrays.xml
+++ b/mobile/android/base/resources/values/arrays.xml
@@ -32,16 +32,26 @@
     <string-array name="pref_char_encoding_entries">
         <item>@string/pref_char_encoding_on</item>
         <item>@string/pref_char_encoding_off</item>
     </string-array>
     <string-array name="pref_char_encoding_values">
         <item>true</item>
         <item>false</item>
     </string-array>
+    <string-array name="pref_cookies_entries">
+        <item>@string/pref_cookies_accept_all</item>
+        <item>@string/pref_cookies_not_accept_foreign</item>
+        <item>@string/pref_cookies_disabled</item>
+    </string-array>
+    <string-array name="pref_cookies_values">
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+    </string-array>
     <string-array name="pref_import_android_entries">
         <item>@string/awesomebar_bookmarks_title</item>
         <item>@string/awesomebar_history_title</item>
     </string-array>
     <string-array name="pref_import_android_values">
         <item>true</item>
         <item>true</item>
     </string-array>
--- a/mobile/android/base/resources/xml/preferences.xml.in
+++ b/mobile/android/base/resources/xml/preferences.xml.in
@@ -72,19 +72,21 @@
                             android:defaultValue="false"
                             android:persistent="false" />
 
         <CheckBoxPreference android:key="signon.rememberSignons"
                             android:title="@string/pref_remember_signons"
                             android:defaultValue="true"
                             android:persistent="false" />
 
-        <CheckBoxPreference android:key="network.cookie.cookieBehavior"
-                            android:title="@string/pref_cookies"
-                            android:persistent="false" />
+        <ListPreference android:key="network.cookie.cookieBehavior"
+                        android:title="@string/pref_cookies"
+                        android:entries="@array/pref_cookies_entries"
+                        android:entryValues="@array/pref_cookies_values"
+                        android:persistent="false" />
 
 #ifdef MOZ_TELEMETRY_REPORTING
         <CheckBoxPreference android:key="toolkit.telemetry.enabled"
                             android:title="@string/pref_telemetry"
                             android:persistent="false" />
 #endif
 
         <CheckBoxPreference android:key="privacy.masterpassword.enabled"
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -72,17 +72,22 @@
   <string name="pref_category_general">&pref_category_general;</string>
   <string name="pref_category_privacy">&pref_category_privacy;</string>
   <string name="pref_category_content">&pref_category_content;</string>
   <string name="pref_category_importexport">&pref_category_importexport;</string>
   <string name="pref_about_firefox">&pref_about_firefox;</string>
   <string name="pref_do_not_track">&pref_do_not_track;</string>
   <string name="pref_telemetry">&pref_telemetry;</string>
   <string name="pref_remember_signons">&pref_remember_signons;</string>
+
   <string name="pref_cookies">&pref_cookies;</string>
+  <string name="pref_cookies_accept_all">&pref_cookies_accept_all;</string>
+  <string name="pref_cookies_not_accept_foreign">&pref_cookies_not_accept_foreign;</string>
+  <string name="pref_cookies_disabled">&pref_cookies_disabled;</string>
+
   <string name="pref_char_encoding">&pref_char_encoding;</string>
   <string name="pref_char_encoding_on">&pref_char_encoding_on;</string>
   <string name="pref_char_encoding_off">&pref_char_encoding_off;</string>
   <string name="pref_clear_private_data">&pref_clear_private_data;</string>
   <string name="pref_plugins">&pref_plugins;</string>
   <string name="pref_plugins_enabled">&pref_plugins_enabled;</string>
   <string name="pref_plugins_tap_to_play">&pref_plugins_tap_to_play;</string>
   <string name="pref_plugins_disabled">&pref_plugins_disabled;</string>
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -870,18 +870,18 @@ var BrowserApp = {
         }
 
         // some preferences use integers or strings instead of booleans for
         // indicating enabled/disabled. since the java ui uses the type to
         // determine which ui elements to show, we need to normalize these
         // preferences to be actual booleans.
         switch (prefName) {
           case "network.cookie.cookieBehavior":
-            pref.type = "bool";
-            pref.value = pref.value == 0;
+            pref.type = "string";
+            pref.value = pref.value.toString();
             break;
           case "font.size.inflation.minTwips":
             pref.type = "string";
             pref.value = pref.value.toString();
             break;
         }
 
         prefs.push(pref);
@@ -918,17 +918,17 @@ var BrowserApp = {
     }
 
     // when sending to java, we normalized special preferences that use
     // integers and strings to represent booleans.  here, we convert them back
     // to their actual types so we can store them.
     switch (json.name) {
       case "network.cookie.cookieBehavior":
         json.type = "int";
-        json.value = (json.value ? 0 : 2);
+        json.value = parseInt(json.value);
         break;
       case "font.size.inflation.minTwips":
         json.type = "int";
         json.value = parseInt(json.value);
         break;
     }
 
     if (json.type == "bool") {
@@ -7112,17 +7112,17 @@ var Telemetry = {
     NativeWindow.doorhanger.show(message, "telemetry-optin", buttons, BrowserApp.selectedTab.id, options);
   },
 };
 
 let Reader = {
   // Version of the cache database schema
   DB_VERSION: 1,
 
-  DEBUG: 1,
+  DEBUG: 0,
 
   // Don't try to parse the page if it has too many elements (for memory and
   // performance reasons)
   MAX_ELEMS_TO_PARSE: 3000,
 
   init: function Reader_init() {
     this.log("Init()");
     this._requests = {};
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -1260,17 +1260,17 @@ pref("converter.html2txt.structs",      
 pref("converter.html2txt.header_strategy",  1); // 0 = no indention; 1 = indention, increased with header level; 2 = numbering and slight indention
 
 pref("intl.accept_languages",               "chrome://global/locale/intl.properties");
 pref("intl.menuitems.alwaysappendaccesskeys","chrome://global/locale/intl.properties");
 pref("intl.menuitems.insertseparatorbeforeaccesskeys","chrome://global/locale/intl.properties");
 pref("intl.charsetmenu.browser.static",     "chrome://global/locale/intl.properties");
 pref("intl.charsetmenu.browser.more1",      "ISO-8859-1, ISO-8859-15, IBM850, macintosh, windows-1252, ISO-8859-14, ISO-8859-7, x-mac-greek, windows-1253, x-mac-icelandic, ISO-8859-10, ISO-8859-3");
 pref("intl.charsetmenu.browser.more2",      "ISO-8859-4, ISO-8859-13, windows-1257, IBM852, ISO-8859-2, x-mac-ce, windows-1250, x-mac-croatian, IBM855, ISO-8859-5, ISO-IR-111, KOI8-R, x-mac-cyrillic, windows-1251, IBM866, KOI8-U, x-mac-ukrainian, ISO-8859-16, x-mac-romanian");
-pref("intl.charsetmenu.browser.more3",      "GB2312, gbk, gb18030, HZ-GB-2312, ISO-2022-CN, Big5, Big5-HKSCS, x-euc-tw, EUC-JP, ISO-2022-JP, Shift_JIS, EUC-KR, x-windows-949, x-johab, ISO-2022-KR");
+pref("intl.charsetmenu.browser.more3",      "GB2312, gbk, gb18030, HZ-GB-2312, ISO-2022-CN, Big5, Big5-HKSCS, x-euc-tw, EUC-JP, ISO-2022-JP, Shift_JIS, EUC-KR, x-johab, ISO-2022-KR");
 pref("intl.charsetmenu.browser.more4",      "armscii-8, TIS-620, ISO-8859-11, windows-874, IBM857, ISO-8859-9, x-mac-turkish, windows-1254, x-viet-tcvn5712, VISCII, x-viet-vps, windows-1258, x-mac-devanagari, x-mac-gujarati, x-mac-gurmukhi");
 pref("intl.charsetmenu.browser.more5",      "ISO-8859-6, windows-1256, ISO-8859-8-I, windows-1255, ISO-8859-8, IBM862");
 pref("intl.charsetmenu.browser.unicode",    "UTF-8, UTF-16LE, UTF-16BE");
 pref("intl.charsetmenu.mailedit",           "chrome://global/locale/intl.properties");
 pref("intl.charsetmenu.browser.cache",      "");
 pref("intl.charsetmenu.mailview.cache",     "");
 pref("intl.charsetmenu.composer.cache",     "");
 pref("intl.charsetmenu.browser.cache.size", 5);
@@ -3609,17 +3609,17 @@ pref("image.mem.decodeondraw", true);
 // value and twice this value.
 //
 // This used to be 120 seconds, but having it that high causes our working
 // set to grow very large. Switching it back to 10 seconds will hopefully
 // be better.
 pref("image.mem.min_discard_timeout_ms", 10000);
 
 // Chunk size for calls to the image decoders
-pref("image.mem.decode_bytes_at_a_time", 4096);
+pref("image.mem.decode_bytes_at_a_time", 16384);
 
 // The longest time we can spend in an iteration of an async decode
 pref("image.mem.max_ms_before_yield", 5);
 
 // The maximum amount of decoded image data we'll willingly keep around (we
 // might keep around more than this, but we'll try to get down to this value).
 pref("image.mem.max_decoded_image_kb", 51200);
 
@@ -3805,16 +3805,19 @@ pref("memory.low_physical_memory_thresho
 pref("memory.low_memory_notification_interval_ms", 10000);
 #endif
 
 // How long must we wait before declaring that a window is a "ghost" (i.e., a
 // likely leak)?  This should be longer than it usually takes for an eligible
 // window to be collected via the GC/CC.
 pref("memory.ghost_window_timeout_seconds", 60);
 
+// Disable freeing dirty pages when minimizing memory.
+pref("memory.free_dirty_pages", false);
+
 pref("social.enabled", false);
 
 // Disable idle observer fuzz, because only privileged content can access idle
 // observers (bug 780507).
 pref("dom.idle-observers-api.fuzz_time.disabled", true);
 
 // Setting that to true grant elevated privileges to apps that ask
 // for them in their manifest.
@@ -3835,9 +3838,9 @@ pref("network.activity.blipIntervalMilli
 // to take effect.
 pref("jsloader.reuseGlobal", false);
 
 // When we're asked to take a screenshot, don't wait more than 2000ms for the
 // event loop to become idle before actually taking the screenshot.
 pref("dom.browserElement.maxScreenshotDelayMS", 2000);
 
 // Whether we should show the placeholder when the element is focused but empty.
-pref("dom.placeholder.show_on_focus", true);
\ No newline at end of file
+pref("dom.placeholder.show_on_focus", true);
--- a/mozglue/build/mozglue.def.in
+++ b/mozglue/build/mozglue.def.in
@@ -19,11 +19,12 @@ EXPORTS
   _wcsdup=je_wcsdup
   malloc_usable_size=je_malloc_usable_size
 #ifdef MOZ_JEMALLOC
   je_nallocm
 #else
   je_malloc_good_size
 #endif
   jemalloc_stats
+  jemalloc_free_dirty_pages
   ; A hack to work around the CRT (see giant comment in Makefile.in)
   frex=je_dumb_free_thunk
 #endif
--- a/netwerk/protocol/http/SpdySession3.cpp
+++ b/netwerk/protocol/http/SpdySession3.cpp
@@ -1865,17 +1865,17 @@ SpdySession3::Close(nsresult aReason)
   NS_ABORT_IF_FALSE(mStreamTransactionHash.Count() ==
                     mStreamIDHash.Count(),
                     "index corruption");
   mStreamTransactionHash.Enumerate(ShutdownEnumerator, this);
   mStreamIDHash.Clear();
   mStreamTransactionHash.Clear();
 
   if (NS_SUCCEEDED(aReason))
-    GenerateGoAway(goawayReason::OK);
+    GenerateGoAway(OK);
   mConnection = nullptr;
   mSegmentReader = nullptr;
   mSegmentWriter = nullptr;
 }
 
 void
 SpdySession3::CloseTransaction(nsAHttpTransaction *aTransaction,
                               nsresult aResult)
--- a/parser/xml/src/nsSAXXMLReader.cpp
+++ b/parser/xml/src/nsSAXXMLReader.cpp
@@ -174,18 +174,18 @@ nsSAXXMLReader::HandleStartDTD(const PRU
     aSystemId = &nullChar;
   if (!aPublicId)
     aPublicId = &nullChar;
 
   mSystemId = aSystemId;
   mPublicId = aPublicId;
   if (mLexicalHandler) {
     return mLexicalHandler->StartDTD(nsDependentString(aName),
-                                     nsDependentString(aSystemId),
-                                     nsDependentString(aPublicId));
+                                     nsDependentString(aPublicId),
+                                     nsDependentString(aSystemId));
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSAXXMLReader::HandleDoctypeDecl(const nsAString & aSubset,
                                   const nsAString & aName,
--- a/testing/mozbase/mozhttpd/mozhttpd/mozhttpd.py
+++ b/testing/mozbase/mozhttpd/mozhttpd/mozhttpd.py
@@ -63,16 +63,20 @@ class Request(object):
 class RequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
 
     docroot = os.getcwd() # current working directory at time of import
     proxy_host_dirs = False
     request_log = []
     log_requests = False
     request = None
 
+    def __init__(self, *args, **kwargs):
+        SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, *args, **kwargs)
+        self.extensions_map['.svg'] = 'image/svg+xml'
+
     def _try_handler(self, method):
         if self.log_requests:
             self.request_log.append({ 'method': method,
                                       'path': self.request.path,
                                       'time': time.time() })
 
         handlers = [handler for handler in self.urlhandlers
                     if handler['method'] == method]
--- a/testing/mozbase/mozhttpd/setup.py
+++ b/testing/mozbase/mozhttpd/setup.py
@@ -6,17 +6,17 @@ import os
 from setuptools import setup
 
 try:
     here = os.path.dirname(os.path.abspath(__file__))
     description = file(os.path.join(here, 'README.md')).read()
 except IOError:
     description = None
 
-PACKAGE_VERSION = '0.4'
+PACKAGE_VERSION = '0.5'
 
 deps = []
 
 setup(name='mozhttpd',
       version=PACKAGE_VERSION,
       description="basic python webserver, tested with talos",
       long_description=description,
       classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
--- a/testing/testsuite-targets.mk
+++ b/testing/testsuite-targets.mk
@@ -43,16 +43,17 @@ RERUN_MOCHITEST = \
     --testing-modules-dir=$(call core_abspath,_tests/modules) \
     $(SYMBOLS_PATH) $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS)
 
 RUN_MOCHITEST_REMOTE = \
   rm -f ./$@.log && \
   $(PYTHON) _tests/testing/mochitest/runtestsremote.py --autorun --close-when-done \
     --console-level=INFO --log-file=./$@.log --file-level=INFO $(DM_FLAGS) --dm_trans=$(DM_TRANS) \
     --app=$(TEST_PACKAGE_NAME) --deviceIP=${TEST_DEVICE} --xre-path=${MOZ_HOST_BIN} \
+    --testing-modules-dir=$(call core_abspath,_tests/modules) \
     $(SYMBOLS_PATH) $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS)
 
 RUN_MOCHITEST_ROBOTIUM = \
   rm -f ./$@.log && \
   $(PYTHON) _tests/testing/mochitest/runtestsremote.py --robocop-path=$(DEPTH)/dist \
     --robocop-ids=$(DEPTH)/build/mobile/robocop/fennec_ids.txt \
     --console-level=INFO --log-file=./$@.log --file-level=INFO $(DM_FLAGS) --dm_trans=$(DM_TRANS) \
     --app=$(TEST_PACKAGE_NAME) --deviceIP=${TEST_DEVICE} --xre-path=${MOZ_HOST_BIN} \
@@ -264,16 +265,17 @@ REMOTE_XPCSHELL = \
 	rm -f ./$@.log && \
 	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/build \
 	  -I$(topsrcdir)/testing/mozbase/mozdevice/mozdevice \
 	  $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
 	  --manifest=$(DEPTH)/_tests/xpcshell/xpcshell.ini \
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  --no-logfiles \
+	  --testing-modules-dir=$(call core_abspath,_tests/modules) \
 	  --dm_trans=$(DM_TRANS) \
 	  --deviceIP=${TEST_DEVICE} \
 	  --objdir=$(DEPTH) \
 	  $(SYMBOLS_PATH) \
 	  $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS)
 
 B2G_XPCSHELL = \
 	rm -f ./@.log && \
--- a/testing/xpcshell/remotexpcshelltests.py
+++ b/testing/xpcshell/remotexpcshelltests.py
@@ -2,16 +2,17 @@
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 import re, sys, os
 import subprocess
 import runxpcshelltests as xpcshell
+import tempfile
 from automationutils import *
 from mozdevice import devicemanager, devicemanagerADB, devicemanagerSUT
 
 # A specialization of XPCShellTests that runs tests on an Android device
 # via devicemanager.
 class XPCShellRemote(xpcshell.XPCShellTests, object):
 
     def __init__(self, devmgr, options, args):
@@ -24,21 +25,24 @@ class XPCShellRemote(xpcshell.XPCShellTe
         # to minimize the length of the command line used to execute
         # xpcshell on the remote device. adb has a limit to the number
         # of characters used in a shell command, and the xpcshell command
         # line can be quite complex.
         self.remoteBinDir = self.remoteJoin(self.remoteTestRoot, "b")
         self.remoteTmpDir = self.remoteJoin(self.remoteTestRoot, "tmp")
         self.remoteScriptsDir = self.remoteTestRoot
         self.remoteComponentsDir = self.remoteJoin(self.remoteTestRoot, "c")
+        self.remoteModulesDir = self.remoteJoin(self.remoteTestRoot, "m")
         self.profileDir = self.remoteJoin(self.remoteTestRoot, "p")
         self.remoteDebugger = options.debugger
         self.remoteDebuggerArgs = options.debuggerArgs
+        self.testingModulesDir = options.testingModulesDir
         if options.setup:
           self.setupUtilities()
+          self.setupModules()
           self.setupTestDir()
         if options.localAPK:
           self.remoteAPK = self.remoteJoin(self.remoteBinDir, os.path.basename(options.localAPK))
           self.setAppRoot()
 
     def setAppRoot(self):
         # Determine the application root directory associated with the package
         # name used by the Fennec APK.
@@ -104,18 +108,16 @@ class XPCShellRemote(xpcshell.XPCShellTe
         remoteFile = self.remoteJoin(self.remoteComponentsDir, "test_necko.xpt")
         self.device.pushFile(local, remoteFile)
 
         remoteFile = self.remoteJoin(self.remoteBinDir, os.path.basename(self.options.localAPK))
         self.device.pushFile(self.options.localAPK, remoteFile)
 
         self.pushLibs()
 
-        self.device.chmodDir(self.remoteBinDir)
-
     def pushLibs(self):
         if self.options.localAPK:
           localLib = os.path.join(self.options.objdir, "dist/fennec")
           if not os.path.exists(localLib):
             localLib = os.path.join(self.options.objdir, "fennec/lib")
             if not os.path.exists(localLib):
               print >>sys.stderr, "Error: could not find libs in objdir"
               sys.exit(1)
@@ -134,16 +136,19 @@ class XPCShellRemote(xpcshell.XPCShellTe
         localArmLib = os.path.join(localLib, "lib")
         if os.path.exists(localArmLib):
           for root, dirs, files in os.walk(localArmLib):
             for file in files:
               if (file.endswith(".so")):
                 remoteFile = self.remoteJoin(self.remoteBinDir, file)
                 self.device.pushFile(os.path.join(root, file), remoteFile)
 
+    def setupModules(self):
+        if self.testingModulesDir:
+            self.device.pushDir(self.testingModulesDir, self.remoteModulesDir)
 
     def setupTestDir(self):
         xpcDir = os.path.join(self.options.objdir, "_tests/xpcshell")
         self.device.pushDir(xpcDir, self.remoteScriptsDir)
 
     def buildTestList(self):
         xpcshell.XPCShellTests.buildTestList(self)
         uniqueTestPaths = set([])
@@ -151,29 +156,29 @@ class XPCShellRemote(xpcshell.XPCShellTe
           uniqueTestPaths.add(test['here'])
         for testdir in uniqueTestPaths:
           xpcDir = os.path.join(self.options.objdir, "_tests/xpcshell")
           abbrevTestDir = os.path.relpath(testdir, xpcDir)
           remoteScriptDir = self.remoteJoin(self.remoteScriptsDir, abbrevTestDir)
           self.pathMapping.append(PathMapping(testdir, remoteScriptDir))
 
     def buildXpcsCmd(self, testdir):
-        self.xpcsCmd = [
-           self.remoteJoin(self.remoteBinDir, "xpcshell"),
-           '-r', self.remoteJoin(self.remoteComponentsDir, 'httpd.manifest')]
-        # If using an APK, --greomni must be specified before any -e arguments.
+        # change base class' paths to remote paths and use base class to build command
+        self.xpcshell = self.remoteJoin(self.remoteBinDir, "xpcw")
+        self.headJSPath = self.remoteJoin(self.remoteScriptsDir, 'head.js')
+        self.httpdJSPath = self.remoteJoin(self.remoteComponentsDir, 'httpd.js')
+        self.httpdManifest = self.remoteJoin(self.remoteComponentsDir, 'httpd.manifest')
+        self.testingModulesDir = self.remoteModulesDir
+        self.testharnessdir = self.remoteScriptsDir
+        xpcshell.XPCShellTests.buildXpcsCmd(self, testdir)
+        # remove "-g <dir> -a <dir>" and add "--greomni <apk>"
+        del(self.xpcsCmd[1:5])
         if self.options.localAPK:
-          self.xpcsCmd.extend(['--greomni', self.remoteAPK])
-        self.xpcsCmd.extend([
-           '-m',
-           '-n',
-           '-s',
-           '-e', 'const _HTTPD_JS_PATH = "%s";' % self.remoteJoin(self.remoteComponentsDir, 'httpd.js'),
-           '-e', 'const _HEAD_JS_PATH = "%s";' % self.remoteJoin(self.remoteScriptsDir, 'head.js'),
-           '-f', self.remoteScriptsDir+'/head.js'])
+          self.xpcsCmd.insert(3, '--greomni')
+          self.xpcsCmd.insert(4, self.remoteAPK)
 
         if self.remoteDebugger:
           # for example, "/data/local/gdbserver" "localhost:12345"
           self.xpcsCmd = [
             self.remoteDebugger,
             self.remoteDebuggerArgs,
             self.xpcsCmd]
 
@@ -214,43 +219,61 @@ class XPCShellRemote(xpcshell.XPCShellTe
         return self.profileDir
 
     def logCommand(self, name, completeCmd, testdir):
         self.log.info("TEST-INFO | %s | full command: %r" % (name, completeCmd))
         self.log.info("TEST-INFO | %s | current directory: %r" % (name, self.remoteHere))
         self.log.info("TEST-INFO | %s | environment: %s" % (name, self.env))
 
     def setupLeakLogging(self):
-        # Leak logging disabled on Android because it makes the command
-        # line too long: bug 752126
-
-        # filename = "leaks"
-        # leakLogFile = self.remoteJoin(self.profileDir, filename)
-        # self.env["XPCOM_MEM_LEAK_LOG"] = leakLogFile
-        leakLogFile = ""
-        return leakLogFile
+        self.env["XPCOM_MEM_LEAK_LOG"] = self.remoteJoin(self.profileDir, "leaks.log")
+        return self.env["XPCOM_MEM_LEAK_LOG"]
 
     def setLD_LIBRARY_PATH(self, env):
         env["LD_LIBRARY_PATH"]=self.remoteBinDir
 
+    def pushWrapper(self):
+        # Rather than executing xpcshell directly, this wrapper script is
+        # used. By setting environment variables and the cwd in the script,
+        # the length of the per-test command line is shortened. This is
+        # often important when using ADB, as there is a limit to the length
+        # of the ADB command line.
+        localWrapper = tempfile.mktemp()
+        f = open(localWrapper, "w")
+        f.write("#!/system/bin/sh\n")
+        for envkey, envval in self.env.iteritems():
+            f.write("export %s=%s\n" % (envkey, envval))
+        f.write("cd $1\n")
+        f.write("echo xpcw: cd $1\n")
+        f.write("shift\n")
+        f.write("echo xpcw: xpcshell \"$@\"\n")
+        f.write("%s/xpcshell \"$@\"\n" % self.remoteBinDir)
+        f.close()
+        remoteWrapper = self.remoteJoin(self.remoteBinDir, "xpcw")
+        self.device.pushFile(localWrapper, remoteWrapper)
+        os.remove(localWrapper)
+        self.device.chmodDir(self.remoteBinDir)
+
     def buildEnvironment(self):
         self.env = {}
+        self.buildCoreEnvironment()
         self.setLD_LIBRARY_PATH(self.env)
         self.env["MOZ_LINKER_CACHE"]=self.remoteBinDir
         if self.options.localAPK and self.appRoot:
           self.env["GRE_HOME"]=self.appRoot
         self.env["XPCSHELL_TEST_PROFILE_DIR"]=self.profileDir
         self.env["TMPDIR"]=self.remoteTmpDir
         self.env["HOME"]=self.profileDir
+        self.pushWrapper()
 
     def launchProcess(self, cmd, stdout, stderr, env, cwd):
-        cmd[0] = self.remoteJoin(self.remoteBinDir, "xpcshell")
+        cmd.insert(1, self.remoteHere)
         outputFile = "xpcshelloutput"
         f = open(outputFile, "w+")
-        self.shellReturnCode = self.device.shell(cmd, f, cwd=self.remoteHere, env=env)
+        self.shellReturnCode = self.device.shell(cmd, f)
         f.close()
         # The device manager may have timed out waiting for xpcshell.
         # Guard against an accumulation of hung processes by killing
         # them here. Note also that IPC tests may spawn new instances
         # of xpcshell.
         self.device.killProcess(cmd[0])
         self.device.killProcess("xpcshell")
         return outputFile
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -116,30 +116,35 @@ class XPCShellTests(object):
     if self.xrePath is None:
       self.xrePath = os.path.dirname(self.xpcshell)
     else:
       self.xrePath = os.path.abspath(self.xrePath)
 
     if self.mozInfo is None:
       self.mozInfo = os.path.join(self.testharnessdir, "mozinfo.json")
 
-  def buildEnvironment(self):
+  def buildCoreEnvironment(self):
     """
-      Create and returns a dictionary of self.env to include all the appropriate env variables and values.
-      On a remote system, we overload this to set different values and are missing things like os.environ and PATH.
+      Add environment variables likely to be used across all platforms, including remote systems.
     """
-    self.env = dict(os.environ)
     # Make assertions fatal
     self.env["XPCOM_DEBUG_BREAK"] = "stack-and-abort"
     # Don't launch the crash reporter client
     self.env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
     # Capturing backtraces is very slow on some platforms, and it's
     # disabled by automation.py too
     self.env["NS_TRACE_MALLOC_DISABLE_STACKS"] = "1"
 
+  def buildEnvironment(self):
+    """
+      Create and returns a dictionary of self.env to include all the appropriate env variables and values.
+      On a remote system, we overload this to set different values and are missing things like os.environ and PATH.
+    """
+    self.env = dict(os.environ)
+    self.buildCoreEnvironment()
     if sys.platform == 'win32':
       self.env["PATH"] = self.env["PATH"] + ";" + self.xrePath
     elif sys.platform in ('os2emx', 'os2knix'):
       os.environ["BEGINLIBPATH"] = self.xrePath + ";" + self.env["BEGINLIBPATH"]
       os.environ["LIBPATHSTRICT"] = "T"
     elif sys.platform == 'osx' or sys.platform == "darwin":
       self.env["DYLD_LIBRARY_PATH"] = self.xrePath
     else: # unix or linux?
--- a/toolkit/Makefile.in
+++ b/toolkit/Makefile.in
@@ -46,16 +46,20 @@ endif
 ifneq (,$(filter cocoa,$(MOZ_WIDGET_TOOLKIT)))
 PARALLEL_DIRS += system/osxproxy
 endif
 
 ifneq (,$(filter windows,$(MOZ_WIDGET_TOOLKIT)))
 PARALLEL_DIRS += system/windowsproxy
 endif
 
+ifneq (,$(filter android,$(MOZ_WIDGET_TOOLKIT)))
+PARALLEL_DIRS += system/androidproxy
+endif
+
 ifdef MOZ_CRASHREPORTER
 PARALLEL_DIRS += crashreporter
 endif
 
 DIRS += \
   xre \
   $(NULL)
 
--- a/toolkit/components/osfile/osfile.jsm
+++ b/toolkit/components/osfile/osfile.jsm
@@ -5,14 +5,31 @@
 /**
  * Common front for various implementations of OS.File
  */
 
 if (typeof Components != "undefined") {
   this.EXPORTED_SYMBOLS = ["OS"];
   Components.utils.import("resource://gre/modules/osfile/osfile_async_front.jsm", this);
 } else {
+  // At this stage, we need to import all sources at once to avoid
+  // a unique failure on tbpl + talos that seems caused by a
+  // what looks like a nested event loop bug (see bug 794091).
 #ifdef XP_WIN
-  importScripts("resource://gre/modules/osfile/osfile_win_front.jsm");
+  importScripts(
+    "resource://gre/modules/osfile/osfile_shared_allthreads.jsm",
+    "resource://gre/modules/osfile/osfile_win_allthreads.jsm",
+    "resource://gre/modules/osfile/ospath_win_back.jsm",
+    "resource://gre/modules/osfile/osfile_win_back.jsm",
+    "resource://gre/modules/osfile/osfile_shared_front.jsm",
+    "resource://gre/modules/osfile/osfile_win_front.jsm"
+  );
 #else
-  importScripts("resource://gre/modules/osfile/osfile_unix_front.jsm");
+  importScripts(
+    "resource://gre/modules/osfile/osfile_shared_allthreads.jsm",
+    "resource://gre/modules/osfile/osfile_unix_allthreads.jsm",
+    "resource://gre/modules/osfile/ospath_unix_back.jsm",
+    "resource://gre/modules/osfile/osfile_unix_back.jsm",
+    "resource://gre/modules/osfile/osfile_shared_front.jsm",
+    "resource://gre/modules/osfile/osfile_unix_front.jsm"
+  );