Merge m-c to fx-team.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 24 Jan 2013 21:36:55 -0500
changeset 119637 98ea4d29436917a1f63456b6fd467560ae8ad256
parent 119636 b8d068584ab34cd193b4217ad8a61fd465eeab52 (current diff)
parent 119624 dd0875ef7437c94ef6ba49c2908fb5c276e5ce7d (diff)
child 119638 0a453067b5dea3a36cef6d89c6ca2b9e5856a980
child 119745 3d578ca8e4b364f5ff909530086f525312321478
push id24215
push userpastithas@mozilla.com
push dateThu, 24 Jan 2013 08:16:14 +0000
treeherdermozilla-central@98ea4d294369 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone21.0a1
first release with
nightly linux32
98ea4d294369 / 21.0a1 / 20130124054158 / files
nightly linux64
98ea4d294369 / 21.0a1 / 20130124054158 / files
nightly mac
98ea4d294369 / 21.0a1 / 20130124054158 / files
nightly win32
98ea4d294369 / 21.0a1 / 20130124054158 / files
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
Merge m-c to fx-team.
build/macosx/universal/fix-buildconfig
config/optimizejars.py
content/base/test/badEventFieldName.eventsource
content/base/test/badEventFieldName.eventsource^headers^
mobile/android/themes/core/fonts/LICENSE
mobile/android/themes/core/fonts/opensans-light.ttf
mobile/android/themes/core/fonts/opensans-regular.ttf
toolkit/components/places/tests/unit/test_399606.js
toolkit/mozapps/installer/Packager.pm
toolkit/mozapps/installer/link-manifests.py
toolkit/mozapps/installer/os2/sign.cmd
toolkit/mozapps/installer/os2/strip.cmd
toolkit/mozapps/installer/packager-deps.py
toolkit/mozapps/installer/pkgcp.pl
toolkit/mozapps/installer/xptlink.pl
new file mode 100644
--- /dev/null
+++ b/accessible/defs.mk
@@ -0,0 +1,3 @@
+ifeq ($(OS_TARGET),WINNT)
+NO_PROFILE_GUIDED_OPTIMIZE := 1 # Don't PGO
+endif
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -631,8 +631,12 @@ pref("layers.orientation.sync.timeout", 
 // Don't discard WebGL contexts for foreground apps on memory
 // pressure.
 pref("webgl.can-lose-context-in-foreground", false);
 
 // Allow nsMemoryInfoDumper to create a fifo in the temp directory.  We use
 // this fifo to trigger about:memory dumps, among other things.
 pref("memory_info_dumper.watch_fifo.enabled", true);
 pref("memory_info_dumper.watch_fifo.directory", "/data/local");
+
+// <input type='file'> implementation is not complete. We have to disable the
+// type to web content to help them do feature detection.
+pref("dom.disable_input_file", true);
--- a/b2g/chrome/content/payment.js
+++ b/b2g/chrome/content/payment.js
@@ -56,17 +56,18 @@ function closePaymentFlowDialog(aCallbac
   let browser = Services.wm.getMostRecentWindow("navigator:browser");
   let content = browser.getContentWindow();
   if (!content) {
     return;
   }
 
   let detail = {
     type: kClosePaymentFlowEvent,
-    id: id
+    id: id,
+    requestId: requestId
   };
 
   // In order to avoid race conditions, we wait for the UI to notify that
   // it has successfully closed the payment flow and has recovered the
   // caller app, before notifying the parent process to fire the success
   // or error event over the DOMRequest.
   content.addEventListener("mozContentEvent",
                            function closePaymentFlowReturn(evt) {
--- a/b2g/components/PaymentGlue.js
+++ b/b2g/components/PaymentGlue.js
@@ -49,16 +49,17 @@ PaymentUI.prototype = {
 
     // The UI should listen for mozChromeEvent 'open-payment-confirmation-dialog'
     // type in order to create and show the payment request confirmation frame
     // embeded within a trusted dialog.
     let id = kOpenPaymentConfirmationEvent + "-" + this.getRandomId();
     let detail = {
       type: kOpenPaymentConfirmationEvent,
       id: id,
+      requestId: aRequestId,
       paymentRequests: aRequests
     };
 
     // Once the user confirm the payment request and makes his choice, we get
     // back to the DOM part to get the appropriate payment flow information
     // based on the selected payment provider.
     content.addEventListener("mozContentEvent", function handleSelection(evt) {
       let msg = evt.detail;
@@ -94,16 +95,17 @@ PaymentUI.prototype = {
       _error("NO_CONTENT_WINDOW");
       return;
     }
 
     let id = kOpenPaymentFlowEvent + "-" + this.getRandomId();
     let detail = {
       type: kOpenPaymentFlowEvent,
       id: id,
+      requestId: aRequestId,
       uri: aPaymentFlowInfo.uri,
       method: aPaymentFlowInfo.requestMethod,
       jwt: aPaymentFlowInfo.jwt
     };
 
     // At some point the UI would send the created iframe back so the
     // callbacks for firing DOMRequest events can be loaded on its
     // content.
--- a/b2g/config/mozconfigs/ics_armv7a_gecko/debug
+++ b/b2g/config/mozconfigs/ics_armv7a_gecko/debug
@@ -1,8 +1,10 @@
+. "$topsrcdir/b2g/config/mozconfigs/common"
+
 mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g
 
 ac_add_options --enable-application=b2g
 ac_add_options --enable-b2g-camera
 
 ac_add_options --target=arm-linux-androideabi
 ac_add_options --with-gonk="$topsrcdir/gonk-toolchain"
 export TOOLCHAIN_HOST=linux-x86
--- a/b2g/config/panda/releng-pandaboard.tt
+++ b/b2g/config/panda/releng-pandaboard.tt
@@ -1,8 +1,8 @@
 [
 {
-"size": 676664796,
-"digest": "d50e0a916bb54c12f55961b3155c1bb754e46fccd0cc965f6c37c2142a7080e58dc3980b7f7f1249b078a21553d6ae2edfefce18213cf8c8fc3f593db27bb0e6",
+"size": 676768064,
+"digest": "d51092cc586934f21b84e62447f49d32548cd3f222a092f2b7b8c04ff59231c97969140e0b1d897c22bcb12b8bf6a9c8b24e55891896c7eeb9bc0f190980813d",
 "algorithm": "sha512",
 "filename": "gonk.tar.xz"
 }
 ]
--- a/b2g/config/panda/sources.xml
+++ b/b2g/config/panda/sources.xml
@@ -5,36 +5,36 @@
   <remote fetch="https://android.googlesource.com/" name="aosp"/>
   <remote fetch="git://github.com/mozilla-b2g/" name="b2g"/>
   <remote fetch="git://android.git.linaro.org/" name="linaro"/>
   <remote fetch="git://github.com/mozilla/" name="mozilla"/>
   <remote fetch="http://git.mozilla.org/" name="mozillaorg"/>
   <default remote="linaro" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
 
   <!-- Gonk specific things and forks -->
-  <project name="platform_build" path="build" remote="b2g" revision="69380784721ae11af93ef4e1b5ce8a54e8570574">
+  <project name="platform_build" path="build" remote="b2g" revision="0784cdcb29ae45e5bf903cc03fa1bc206162665b">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="22629c7597d0d658fb472f76f2bf35e7eaaf98fd"/>
-  <project name="rilproxy" path="rilproxy" remote="b2g" revision="167b4c59a82b9130e385de786e8056d89a1cb8c3"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2f8c7d3546bda16b02a61b422786919875c19f15"/>
+  <project name="rilproxy" path="rilproxy" remote="b2g" revision="2d380d27c86263537f6b829cd0238f5dd702c735"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="6ee1f8987ef36d688f97064c003ad57849dfadf2"/>
 
   <!-- Stock Android things -->
   <!-- Information: platform/abi/cpp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <!-- Information: platform/bionic is tagged with android-4.0.4_r2.1 --><project name="platform/bionic" path="bionic" revision="3d11bf0f3f3cf848f6f1e8449bf8736d8d1c78a3"/>
   <!-- Information: platform/bootable/recovery is tagged with android-4.0.4_r2.1 --><project name="platform/bootable/recovery" path="bootable/recovery" revision="fadc5ac81d6400ebdd041f7d4ea64021596d6b7d"/>
   <!-- Information: device/common is tagged with android-sdk-adt_r20 --><project name="device/common" path="device/common" revision="7d4526582f88808a3194e1a3b304abb369d2745c"/>
   <!-- Information: device/sample is tagged with android-4.0.4_r2.1 --><project name="device/sample" path="device/sample" revision="ef228b8b377a9663e94be4b1aeb6c2bf7a07d098"/>
   <!-- Information: platform/external/apache-http is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/external/apache-http" path="external/apache-http" revision="6c9d8c58d3ed710f87c26820d903bb8aad81754f"/>
   <!-- Information: platform/external/bluetooth/bluez is tagged with android-4.0.4_r2.1 --><project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="966afbd88f0bfc325bf80274ad2723c238883fa1"/>
   <!-- Information: platform/external/bluetooth/glib is tagged with android-4.1.1_r6.1 --><project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="1143b9918eab068401b604eb11c3f651f4e38b25"/>
   <!-- Information: platform/external/bluetooth/hcidump is tagged with android-4.1.1_r6.1 --><project name="platform/external/bluetooth/hcidump" path="external/bluetooth/hcidump" revision="7322661808c2006b7848e79e6bb72b37fbcf6710"/>
   <!-- Information: platform/external/bsdiff is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.041 --><project name="platform/external/bsdiff" path="external/bsdiff" revision="81872540236d9bb15cccf963d05b9de48baa5375"/>
-  <project name="platform/external/busybox" path="external/busybox" remote="linaro" revision="4fa5717aed10a5617c52def848dbd42ec7eca35b"/>
+  <project name="platform/external/busybox" path="external/busybox" remote="linaro" revision="0a41b083cdaf2ddd602fb5c955329494da25f2b9"/>
   <!-- Information: platform/external/bzip2 is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/external/bzip2" path="external/bzip2" revision="048dacdca43eed1534689ececcf2781c63e1e4ba"/>
   <!-- Information: platform/external/dbus is tagged with android-4.1.1_r6.1 --><project name="platform/external/dbus" path="external/dbus" revision="537eaff5de9aace3348436166d4cde7adc1e488e"/>
   <!-- Information: platform/external/dhcpcd is tagged with android-sdk-adt_r20 --><project name="platform/external/dhcpcd" path="external/dhcpcd" revision="ddaa48f57b54b2862b3e6dcf18a44c9647f3baaa"/>
   <!-- Information: platform/external/dnsmasq is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.041 --><project name="platform/external/dnsmasq" path="external/dnsmasq" revision="f621afad94df46204c25fc2593a19d704d2637f5"/>
   <!-- Information: platform/external/expat is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/external/expat" path="external/expat" revision="6df134250feab71edb5915ecaa6268210bca76c5"/>
   <!-- Information: platform/external/fdlibm is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/external/fdlibm" path="external/fdlibm" revision="988ffeb12a6e044ae3504838ef1fee3fe0716934"/>
   <!-- Information: platform/external/flac is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/external/flac" path="external/flac" revision="5893fbe890f5dab8e4146d2baa4bd2691c0739e0"/>
   <!-- Information: platform/external/freetype is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.00.00.19.138 --><project name="platform/external/freetype" path="external/freetype" revision="aeb407daf3711a10a27f3bc2223c5eb05158076e"/>
@@ -89,11 +89,11 @@
   <!-- Information: platform/system/netd is tagged with android-4.0.4_r2.1 --><project name="platform/system/netd" path="system/netd" revision="3c903b555975fa59d6688a0a6417ac7512c202e7"/>
   <!-- Information: platform/system/vold is tagged with android-4.0.4_r2.1 --><project name="platform/system/vold" path="system/vold" revision="3ad9072a5d6f6bda32123b367545649364e3c11d"/>
 
   <!-- Pandaboard specific things -->
   <project name="android-device-panda" path="device/ti/panda" remote="b2g" revision="0e9a89187970d6fa99930c8d9cb438b935c2337c"/>
   <!-- Information: platform/hardware/ti/omap4xxx is tagged with android-4.0.4_r2.1 --><project name="platform/hardware/ti/omap4xxx" path="hardware/ti/omap4xxx" revision="8be8e9a68c96b6cf43c08a58e7ecd7708737c599"/>
   <project name="platform/hardware/ti/wlan" path="hardware/ti/wlan" revision="60dfeb6e4448bfed707946ebca6612980f525e69"/>
   <project name="platform/hardware/ti/wpan" path="hardware/ti/wpan" revision="3ece7d9e08052989401e008bc397dbcd2557cfd0"/>
-  <project name="Negatus" path="external/negatus" remote="mozilla" revision="7ed4efcee655f605455f9375a4e6c68cd078c459"/>
+  <project name="Negatus" path="external/negatus" remote="mozilla" revision="151697c638a6781e83c76d4a01fb001aabde4e79"/>
   
 </manifest>
\ No newline at end of file
--- a/b2g/installer/Makefile.in
+++ b/b2g/installer/Makefile.in
@@ -23,22 +23,17 @@ MOZ_NONLOCALIZED_PKG_LIST = \
 MOZ_LOCALIZED_PKG_LIST = $(AB_CD) multilocale
 
 DEFINES += \
 	-DAB_CD=$(AB_CD) \
 	-DMOZ_APP_NAME=$(MOZ_APP_NAME) \
 	-DPREF_DIR=$(PREF_DIR) \
 	$(NULL)
 
-ifeq ($(MOZ_CHROME_FILE_FORMAT),jar)
-JAREXT=.jar
-else
-JAREXT=
-endif
-DEFINES += -DJAREXT=$(JAREXT)
+DEFINES += -DJAREXT=
 
 include $(topsrcdir)/ipc/app/defs.mk
 DEFINES += -DMOZ_CHILD_PROCESS_NAME=$(MOZ_CHILD_PROCESS_NAME)
 
 # Set MSVC dlls version to package, if any.
 ifdef WIN32_REDIST_DIR
 DEFINES += -DMOZ_MSVC_REDIST=$(_MSC_VER)
 endif
@@ -46,17 +41,17 @@ endif
 ifdef ENABLE_MARIONETTE
 DEFINES += -DENABLE_MARIONETTE=1
 endif
 
 ifdef MOZ_PKG_MANIFEST_P
 MOZ_PKG_MANIFEST = package-manifest
 endif
 
-MOZ_POST_STAGING_CMD = find chrome -type f -name *.properties -exec $(PERL) -n -i -e 'print unless /^\#/' {} \;
+MOZ_PACKAGER_MINIFY=1
 
 include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
 
 ifeq (bundle, $(MOZ_FS_LAYOUT))
 BINPATH = $(_BINPATH)
 DEFINES += -DAPPNAME=$(_APPNAME)
 else
 # Every other platform just winds up in dist/bin
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -123,16 +123,18 @@ let SocialUI = {
           if (Social.provider && Social.provider.origin == data) {
             SocialSidebar.setSidebarErrorMessage("frameworker-error");
           }
           break;
 
         case "nsPref:changed":
           if (data == "social.sidebar.open") {
             SocialSidebar.update();
+          } else if (data == "social.toast-notifications.enabled") {
+            SocialToolbar.updateButton();
           }
           break;
       }
     } catch (e) {
       Components.utils.reportError(e + "\n" + e.stack);
       throw e;
     }
   },
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -216,18 +216,16 @@ splitmenu {
   display: none;
 }
 
 /* ::::: location bar ::::: */
 #urlbar {
   -moz-binding: url(chrome://browser/content/urlbarBindings.xml#urlbar);
 }
 
-.uri-element-right-align:-moz-locale-dir(rtl),
-html|input.uri-element-right-align:-moz-locale-dir(rtl),
 .ac-url-text:-moz-locale-dir(rtl),
 .ac-title:-moz-locale-dir(rtl) > description {
   direction: ltr !important;
 }
 
 /* For results that are actions, their description text is shown instead of
    the URL - this needs to follow the locale's direction, unlike URLs. */
 panel:not([noactions]) > richlistbox > richlistitem[type~="action"]:-moz-locale-dir(rtl) > .ac-url-box {
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -160,16 +160,17 @@ endif
                  browser_bug710878.js \
                  browser_bug719271.js \
                  browser_bug724239.js \
                  browser_bug735471.js \
                  browser_bug743421.js \
                  browser_bug749738.js \
                  browser_bug783614.js \
                  browser_bug797677.js \
+                 browser_bug832435.js \
                  browser_canonizeURL.js \
                  browser_customize.js \
                  browser_findbarClose.js \
                  browser_homeDrop.js \
                  browser_keywordBookmarklets.js \
                  browser_contextSearchTabPosition.js \
                  browser_ctrlTab.js \
                  browser_customize_popupNotification.js \
--- a/browser/base/content/test/browser_bookmark_titles.js
+++ b/browser/base/content/test/browser_bookmark_titles.js
@@ -1,37 +1,40 @@
 /* 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/. */
 
 // This file is tests for the default titles that new bookmarks get.
 
 let tests = [
+    // Common page.
     ['http://example.com/browser/browser/base/content/test/dummy_page.html',
      'Dummy test page'],
-    ['data:text/html;charset=utf-8,<title>test data: url</title>',
+    // Data URI.
+    ['data:text/html;charset=utf-8,<title>test%20data:%20url</title>',
      'test data: url'],
-    ['http://unregistered-domain.example',
-     'http://unregistered-domain.example/'],
+    // about:neterror
+    ['data:application/vnd.mozilla.xul+xml,',
+     'data:application/vnd.mozilla.xul+xml,'],
+    // about:certerror
     ['https://untrusted.example.com/somepage.html',
      'https://untrusted.example.com/somepage.html']
 ];
 
 function generatorTest() {
     gBrowser.selectedTab = gBrowser.addTab();
     let browser = gBrowser.selectedBrowser;
+    browser.stop(); // stop the about:blank load.
 
     browser.addEventListener("DOMContentLoaded", nextStep, true);
     registerCleanupFunction(function () {
         browser.removeEventListener("DOMContentLoaded", nextStep, true);
         gBrowser.removeCurrentTab();
     });
 
-    yield; // Wait for the new tab to load.
-
     // Test that a bookmark of each URI gets the corresponding default title.
     for (let i = 0; i < tests.length; ++i) {
         let [uri, title] = tests[i];
         content.location = uri;
         yield;
         checkBookmark(uri, title);
     }
 
@@ -59,17 +62,16 @@ function generatorTest() {
         "Offline mode successfully simulated network outage.");
     checkBookmark(uri, title);
 }
 
 // Bookmark the current page and confirm that the new bookmark has the expected
 // title. (Then delete the bookmark.)
 function checkBookmark(uri, expected_title) {
     PlacesCommandHook.bookmarkCurrentPage(false);
-    
+
     let id = PlacesUtils.getMostRecentBookmarkForURI(PlacesUtils._uri(uri));
+    ok(id > 0, "Found the expected bookmark");
     let title = PlacesUtils.bookmarks.getItemTitle(id);
-
     is(title, expected_title, "Bookmark got a good default title.");
 
     PlacesUtils.bookmarks.removeItem(id);
 }
-
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_bug832435.js
@@ -0,0 +1,19 @@
+/* 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/. */
+
+function test() {
+  waitForExplicitFinish();
+  ok(true, "Starting up");
+
+  gBrowser.selectedBrowser.focus();
+  gURLBar.addEventListener("focus", function onFocus() {
+    gURLBar.removeEventListener("focus", onFocus);
+    ok(true, "Invoked onfocus handler");
+    EventUtils.synthesizeKey("VK_RETURN", { shiftKey: true });
+    ok(true, "Evaluated without crashing");
+    finish();
+  });
+  gURLBar.inputField.value = "javascript: document.body.innerHTML = '11111111'); ";
+  gURLBar.focus();
+}
--- a/browser/base/content/test/browser_gestureSupport.js
+++ b/browser/base/content/test/browser_gestureSupport.js
@@ -12,18 +12,16 @@ let test_utils;
 let test_commandset;
 let test_prefBranch = "browser.gesture.";
 
 function test()
 {
   // Disable the default gestures support during the test
   gGestureSupport.init(false);
 
-  // Enable privileges so we can use nsIDOMWindowUtils interface
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   test_utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
     getInterface(Components.interfaces.nsIDOMWindowUtils);
 
   // Run the tests of "simple gesture" events generally
   test_EnsureConstantsAreDisjoint();
   test_TestEventListeners();
   test_TestEventCreation();
 
--- a/browser/base/content/test/social/browser_social_toolbar.js
+++ b/browser/base/content/test/social/browser_social_toolbar.js
@@ -151,11 +151,20 @@ var tests = {
     is(toggleSidebarMenuitems.length, 2, "Toggle Sidebar menuitems exist");
     let toggleDesktopNotificationsMenuitems = document.getElementsByClassName("social-toggle-notifications-menuitem");
     is(toggleDesktopNotificationsMenuitems.length, 2, "Toggle notifications menuitems exist");
     let toggleSocialMenuitems = document.getElementsByClassName("social-toggle-menuitem");
     is(toggleSocialMenuitems.length, 2, "Toggle Social menuitems exist");
     let removeSocialMenuitems = document.getElementsByClassName("social-remove-menuitem");
     is(removeSocialMenuitems.length, 2, "Remove Social menuitems exist");
     next();
-  }
+  },
+  testToggleNotifications: function(next) {
+    let enabled = Services.prefs.getBoolPref("social.toast-notifications.enabled");
+    let cmd = document.getElementById("Social:ToggleNotifications");
+    is(cmd.getAttribute("checked"), enabled ? "true" : "false");
+    enabled = !enabled;
+    Services.prefs.setBoolPref("social.toast-notifications.enabled", enabled);
+    is(cmd.getAttribute("checked"), enabled ? "true" : "false");
+    Services.prefs.clearUserPref("social.toast-notifications.enabled");
+    next();
+  },
 }
-
--- a/browser/components/downloads/content/downloads.js
+++ b/browser/components/downloads/content/downloads.js
@@ -523,18 +523,18 @@ const DownloadsPanel = {
         this._state = this.kStateHidden;
         return;
       }
 
       if (aAnchor) {
         this.panel.openPopup(aAnchor, "bottomcenter topright", 0, 0, false,
                              null);
       } else {
-        this.panel.openPopup(document.getElementById("TabsToolbar"),
-                             "after_end", 0, 0, false, null);
+        Components.utils.reportError(
+          "Downloads button cannot be found");
       }
     }.bind(this));
   }
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 //// DownloadsOverlayLoader
 
--- a/browser/components/downloads/content/indicator.js
+++ b/browser/components/downloads/content/indicator.js
@@ -533,17 +533,18 @@ const DownloadsIndicatorView = {
     // If dragged item is from our source, do not try to
     // redownload already downloaded file.
     if (dt.mozGetDataAt("application/x-moz-file", 0))
       return;
 
     let name = {};
     let url = browserDragAndDrop.drop(aEvent, name);
     if (url) {
-      saveURL(url, name.value, null, true, true);
+      let sourceDoc = dt.mozSourceNode ? dt.mozSourceNode.ownerDocument : document;
+      saveURL(url, name.value, null, true, true, null, sourceDoc);
       aEvent.preventDefault();
     }
   },
 
   /**
    * Returns a reference to the main indicator element, or null if the element
    * is not present in the browser window yet.
    */
--- a/browser/components/downloads/src/DownloadsUI.js
+++ b/browser/components/downloads/src/DownloadsUI.js
@@ -55,45 +55,45 @@ DownloadsUI.prototype = {
   //////////////////////////////////////////////////////////////////////////////
   //// nsISupports
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDownloadManagerUI]),
 
   //////////////////////////////////////////////////////////////////////////////
   //// nsIDownloadManagerUI
 
-  show: function DUI_show(aWindowContext, aID, aReason, aUsePrivateUI)
+  show: function DUI_show(aWindowContext, aDownload, aReason, aUsePrivateUI)
   {
     if (DownloadsCommon.useToolkitUI) {
-      this._toolkitUI.show(aWindowContext, aID, aReason, aUsePrivateUI);
+      this._toolkitUI.show(aWindowContext, aDownload, aReason, aUsePrivateUI);
       return;
     }
 
     if (!aReason) {
       aReason = Ci.nsIDownloadManagerUI.REASON_USER_INTERACTED;
     }
 
     if (aReason == Ci.nsIDownloadManagerUI.REASON_NEW_DOWNLOAD) {
       const kMinimized = Ci.nsIDOMChromeWindow.STATE_MINIMIZED;
       let browserWin = gBrowserGlue.getMostRecentBrowserWindow();
 
       if (!browserWin || browserWin.windowState == kMinimized) {
-        this._showDownloadManagerUI(aWindowContext, aID, aReason, aUsePrivateUI);
+        this._showDownloadManagerUI(aWindowContext, aUsePrivateUI);
       }
       else {
         // If the indicator is visible, then new download notifications are
         // already handled by the panel service.
         browserWin.DownloadsButton.checkIsVisible(function(isVisible) {
           if (!isVisible) {
-            this._showDownloadManagerUI(aWindowContext, aID, aReason, aUsePrivateUI);
+            this._showDownloadManagerUI(aWindowContext, aUsePrivateUI);
           }
         }.bind(this));
       }
     } else {
-      this._showDownloadManagerUI(aWindowContext, aID, aReason, aUsePrivateUI);
+      this._showDownloadManagerUI(aWindowContext, aUsePrivateUI);
     }
   },
 
   get visible()
   {
     // If we're still using the toolkit downloads manager, delegate the call
     // to it. Otherwise, return true for now, until we decide on how we want
     // to indicate that a new download has started if a browser window is
@@ -107,17 +107,17 @@ DownloadsUI.prototype = {
       this._toolkitUI.getAttention();
     }
   },
 
   /**
    * Helper function that opens the download manager UI.
    */
   _showDownloadManagerUI:
-  function DUI_showDownloadManagerUI(aWindowContext, aID, aReason, aUsePrivateUI)
+  function DUI_showDownloadManagerUI(aWindowContext, aUsePrivateUI)
   {
     // If we weren't given a window context, try to find a browser window
     // to use as our parent - and if that doesn't work, error out and give up.
     let parentWindow = aWindowContext;
     if (!parentWindow) {
       parentWindow = RecentWindow.getMostRecentBrowserWindow({ private: !!aUsePrivateUI });
       if (!parentWindow) {
         Components.utils.reportError(
--- a/browser/config/mozconfigs/linux32/valgrind
+++ b/browser/config/mozconfigs/linux32/valgrind
@@ -1,7 +1,11 @@
 . $topsrcdir/browser/config/mozconfigs/linux32/nightly
 
 ac_add_options --enable-valgrind
 ac_add_options --disable-jemalloc
 ac_add_options --disable-elf-hack
 ac_add_options --enable-optimize="-g -O -freorder-blocks"
 ac_add_options --disable-install-strip
+
+# Include the override mozconfig again (even though the above includes it)
+# since it's supposed to override everything.
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/linux64/valgrind
+++ b/browser/config/mozconfigs/linux64/valgrind
@@ -1,7 +1,11 @@
 . $topsrcdir/browser/config/mozconfigs/linux64/nightly
 
 ac_add_options --enable-valgrind
 ac_add_options --disable-jemalloc
 ac_add_options --disable-elf-hack
 ac_add_options --enable-optimize="-g -O -freorder-blocks"
 ac_add_options --disable-install-strip
+
+# Include the override mozconfig again (even though the above includes it)
+# since it's supposed to override everything.
+. "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win64/debug
+++ b/browser/config/mozconfigs/win64/debug
@@ -1,8 +1,10 @@
+. "$topsrcdir/browser/config/mozconfigs/common"
+
 ac_add_options --target=x86_64-pc-mingw32
 ac_add_options --host=x86_64-pc-mingw32
 
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
 ac_add_options --enable-signmar
 ENABLE_MARIONETTE=1
 
--- a/browser/config/mozconfigs/win64/nightly
+++ b/browser/config/mozconfigs/win64/nightly
@@ -1,8 +1,10 @@
+. "$topsrcdir/browser/config/mozconfigs/common"
+
 ac_add_options --target=x86_64-pc-mingw32
 ac_add_options --host=x86_64-pc-mingw32
 
 # for pgo
 mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) $(MOZ_OBJDIR)/_profile/pgo/profileserver.py'
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,4 +1,4 @@
 This is the pdf.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 0.7.28
+Current extension version is: 0.7.82
 
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -11,24 +11,23 @@
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 var PDFJS = {};
+PDFJS.version = '0.7.82';
+PDFJS.build = 'd467790';
 
 (function pdfjsWrapper() {
   // Use strict in our context only - users might not want it
   'use strict';
 
-  PDFJS.build =
-'e22ee54';
-
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 /* Copyright 2012 Mozilla Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
@@ -1029,17 +1028,24 @@ function isName(v) {
   return v instanceof Name;
 }
 
 function isCmd(v, cmd) {
   return v instanceof Cmd && (!cmd || v.cmd == cmd);
 }
 
 function isDict(v, type) {
-  return v instanceof Dict && (!type || v.get('Type').name == type);
+  if (!(v instanceof Dict)) {
+    return false;
+  }
+  if (!type) {
+    return true;
+  }
+  var dictType = v.get('Type');
+  return isName(dictType) && dictType.name == type;
 }
 
 function isArray(v) {
   return v instanceof Array;
 }
 
 function isStream(v) {
   return typeof v == 'object' && v != null && ('getChar' in v);
@@ -2124,17 +2130,17 @@ function addContextCurrentTransform(ctx)
 
 var CanvasExtraState = (function CanvasExtraStateClosure() {
   function CanvasExtraState(old) {
     // Are soft masks and alpha values shapes or opacities?
     this.alphaIsShape = false;
     this.fontSize = 0;
     this.fontSizeScale = 1;
     this.textMatrix = IDENTITY_MATRIX;
-    this.fontMatrix = IDENTITY_MATRIX;
+    this.fontMatrix = FONT_IDENTITY_MATRIX;
     this.leading = 0;
     // Current point (in user coordinates)
     this.x = 0;
     this.y = 0;
     // Start of text line (in text coordinates)
     this.lineX = 0;
     this.lineY = 0;
     // Character and word spacing
@@ -2210,67 +2216,119 @@ var CanvasGraphics = (function CanvasGra
           buffer[bufferPos] = 0;
         }
         bufferPos += 4;
         mask >>= 1;
       }
     }
   }
 
-  function rescaleImage(pixels, width, height, widthScale, heightScale) {
-    var scaledWidth = Math.ceil(width / widthScale);
-    var scaledHeight = Math.ceil(height / heightScale);
-
-    var itemsSum = new Float32Array(scaledWidth * scaledHeight * 3);
-    var itemsCount = new Float32Array(scaledWidth * scaledHeight);
-    var maxAlphas = new Uint8Array(scaledWidth * scaledHeight);
-    for (var i = 0, position = 0; i < height; i++) {
-      var lineOffset = (0 | (i / heightScale)) * scaledWidth;
-      for (var j = 0; j < width; j++) {
-        var countOffset = lineOffset + (0 | (j / widthScale));
-        var sumOffset = countOffset * 3;
-        var maxAlpha = maxAlphas[countOffset];
-        var currentAlpha = pixels[position + 3];
-        if (maxAlpha < currentAlpha) {
-          // lowering total alpha
-          var scale = 1 - (currentAlpha - maxAlpha) / 255;
-          itemsSum[sumOffset] *= scale;
-          itemsSum[sumOffset + 1] *= scale;
-          itemsSum[sumOffset + 2] *= scale;
-          maxAlphas[countOffset] = maxAlpha = currentAlpha;
-        }
-        if (maxAlpha > currentAlpha) {
-          var scale = 1 - (maxAlpha - currentAlpha) / 255;
-          itemsSum[sumOffset] += pixels[position] * scale;
-          itemsSum[sumOffset + 1] += pixels[position + 1] * scale;
-          itemsSum[sumOffset + 2] += pixels[position + 2] * scale;
-          itemsCount[countOffset] += scale;
-        } else {
-          itemsSum[sumOffset] += pixels[position];
-          itemsSum[sumOffset + 1] += pixels[position + 1];
-          itemsSum[sumOffset + 2] += pixels[position + 2];
-          itemsCount[countOffset]++;
-        }
-        position += 4;
-      }
-    }
-    var tmpCanvas = createScratchCanvas(scaledWidth, scaledHeight);
+  function putBinaryImageData(ctx, data, w, h) {
+    var tmpImgData = 'createImageData' in ctx ? ctx.createImageData(w, h) :
+      ctx.getImageData(0, 0, w, h);
+
+    var tmpImgDataPixels = tmpImgData.data;
+    if ('set' in tmpImgDataPixels)
+      tmpImgDataPixels.set(data);
+    else {
+      // Copy over the imageData pixel by pixel.
+      for (var i = 0, ii = tmpImgDataPixels.length; i < ii; i++)
+        tmpImgDataPixels[i] = data[i];
+    }
+
+    ctx.putImageData(tmpImgData, 0, 0);
+  }
+
+  function prescaleImage(pixels, width, height, widthScale, heightScale) {
+    pixels = new Uint8Array(pixels); // creating a copy
+    while (widthScale > 2 || heightScale > 2) {
+      if (heightScale > 2) {
+        // scaling image twice vertically
+        var rowSize = width * 4;
+        var k = 0, l = 0;
+        for (var i = 0; i < height - 1; i += 2) {
+          for (var j = 0; j < width; j++) {
+            var alpha1 = pixels[k + 3], alpha2 = pixels[k + 3 + rowSize];
+            if (alpha1 === alpha2) {
+              pixels[l] = (pixels[k] + pixels[k + rowSize]) >> 1;
+              pixels[l + 1] = (pixels[k + 1] + pixels[k + 1 + rowSize]) >> 1;
+              pixels[l + 2] = (pixels[k + 2] + pixels[k + 2 + rowSize]) >> 1;
+              pixels[l + 3] = alpha1;
+            } else if (alpha1 < alpha2) {
+              var d = 256 - alpha2 + alpha1;
+              pixels[l] = (pixels[k] * d + (pixels[k + rowSize] << 8)) >> 9;
+              pixels[l + 1] = (pixels[k + 1] * d +
+                              (pixels[k + 1 + rowSize] << 8)) >> 9;
+              pixels[l + 2] = (pixels[k + 2] * d +
+                              (pixels[k + 2 + rowSize] << 8)) >> 9;
+              pixels[l + 3] = alpha2;
+            } else {
+              var d = 256 - alpha1 + alpha2;
+              pixels[l] = ((pixels[k] << 8) + pixels[k + rowSize] * d) >> 9;
+              pixels[l + 1] = ((pixels[k + 1] << 8) +
+                              pixels[k + 1 + rowSize] * d) >> 9;
+              pixels[l + 2] = ((pixels[k + 2] << 8) +
+                              pixels[k + 2 + rowSize] * d) >> 9;
+              pixels[l + 3] = alpha1;
+            }
+            k += 4; l += 4;
+          }
+          k += rowSize;
+        }
+        if (height & 1) {
+          for (var i = 0; i < rowSize; i++) {
+            pixels[l++] = pixels[k++];
+          }
+        }
+        height = (height + 1) >> 1;
+        heightScale /= 2;
+      }
+      if (widthScale > 2) {
+        // scaling image twice horizontally
+        var k = 0, l = 0;
+        for (var i = 0; i < height; i++) {
+          for (var j = 0; j < width - 1; j += 2) {
+            var alpha1 = pixels[k + 3], alpha2 = pixels[k + 7];
+            if (alpha1 === alpha2) {
+              pixels[l] = (pixels[k] + pixels[k + 4]) >> 1;
+              pixels[l + 1] = (pixels[k + 1] + pixels[k + 5]) >> 1;
+              pixels[l + 2] = (pixels[k + 2] + pixels[k + 6]) >> 1;
+              pixels[l + 3] = alpha1;
+            } else if (alpha1 < alpha2) {
+              var d = 256 - alpha2 + alpha1;
+              pixels[l] = (pixels[k] * d + (pixels[k + 4] << 8)) >> 9;
+              pixels[l + 1] = (pixels[k + 1] * d + (pixels[k + 5] << 8)) >> 9;
+              pixels[l + 2] = (pixels[k + 2] * d + (pixels[k + 6] << 8)) >> 9;
+              pixels[l + 3] = alpha2;
+            } else {
+              var d = 256 - alpha1 + alpha2;
+              pixels[l] = ((pixels[k] << 8) + pixels[k + 4] * d) >> 9;
+              pixels[l + 1] = ((pixels[k + 1] << 8) + pixels[k + 5] * d) >> 9;
+              pixels[l + 2] = ((pixels[k + 2] << 8) + pixels[k + 6] * d) >> 9;
+              pixels[l + 3] = alpha1;
+            }
+            k += 8; l += 4;
+          }
+          if (width & 1) {
+            pixels[l++] = pixels[k++];
+            pixels[l++] = pixels[k++];
+            pixels[l++] = pixels[k++];
+            pixels[l++] = pixels[k++];
+          }
+        }
+        width = (width + 1) >> 1;
+        widthScale /= 2;
+      }
+    }
+
+    var tmpCanvas = createScratchCanvas(width, height);
     var tmpCtx = tmpCanvas.getContext('2d');
-    var imgData = tmpCtx.getImageData(0, 0, scaledWidth, scaledHeight);
-    pixels = imgData.data;
-    var j = 0, q = 0;
-    for (var i = 0, ii = scaledWidth * scaledHeight; i < ii; i++) {
-      var count = itemsCount[i];
-      pixels[j] = itemsSum[q++] / count;
-      pixels[j + 1] = itemsSum[q++] / count;
-      pixels[j + 2] = itemsSum[q++] / count;
-      pixels[j + 3] = maxAlphas[i];
-      j += 4;
-    }
-    tmpCtx.putImageData(imgData, 0, 0);
+    putBinaryImageData(tmpCtx, pixels.subarray(0, width * height * 4),
+                               width, height);
+
     return tmpCanvas;
   }
 
   var LINE_CAP_STYLES = ['butt', 'round', 'square'];
   var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
   var NORMAL_CLIP = {};
   var EO_CLIP = {};
 
@@ -2681,36 +2739,33 @@ var CanvasGraphics = (function CanvasGra
     },
     setFont: function CanvasGraphics_setFont(fontRefName, size) {
       var fontObj = this.commonObjs.get(fontRefName);
       var current = this.current;
 
       if (!fontObj)
         error('Can\'t find font for ' + fontRefName);
 
-      // Slice-clone matrix so we can manipulate it without affecting original
-      if (fontObj.fontMatrix)
-        current.fontMatrix = fontObj.fontMatrix.slice(0);
-      else
-        current.fontMatrix = IDENTITY_MATRIX.slice(0);
+      current.fontMatrix = fontObj.fontMatrix ? fontObj.fontMatrix :
+                                                FONT_IDENTITY_MATRIX;
 
       // A valid matrix needs all main diagonal elements to be non-zero
       // This also ensures we bypass FF bugzilla bug #719844.
       if (current.fontMatrix[0] === 0 ||
           current.fontMatrix[3] === 0) {
         warn('Invalid font matrix for font ' + fontRefName);
       }
 
       // The spec for Tf (setFont) says that 'size' specifies the font 'scale',
       // and in some docs this can be negative (inverted x-y axes).
-      // We implement this condition with fontMatrix.
       if (size < 0) {
         size = -size;
-        current.fontMatrix[0] *= -1;
-        current.fontMatrix[3] *= -1;
+        current.fontDirection = -1;
+      } else {
+        current.fontDirection = 1;
       }
 
       this.current.font = fontObj;
       this.current.fontSize = size;
 
       if (fontObj.coded)
         return; // we don't need ctx.font for Type3 fonts
 
@@ -2753,24 +2808,23 @@ var CanvasGraphics = (function CanvasGra
       this.current.y = this.current.lineY = 0;
     },
     nextLine: function CanvasGraphics_nextLine() {
       this.moveText(0, this.current.leading);
     },
     applyTextTransforms: function CanvasGraphics_applyTextTransforms() {
       var ctx = this.ctx;
       var current = this.current;
-      var textHScale = current.textHScale;
-      var fontMatrix = current.fontMatrix || IDENTITY_MATRIX;
-
       ctx.transform.apply(ctx, current.textMatrix);
-      ctx.scale(1, -1);
-      ctx.translate(current.x, -current.y - current.textRise);
-      ctx.transform.apply(ctx, fontMatrix);
-      ctx.scale(textHScale, 1);
+      ctx.translate(current.x, current.y + current.textRise);
+      if (current.fontDirection > 0) {
+        ctx.scale(current.textHScale, -1);
+      } else {
+        ctx.scale(-current.textHScale, 1);
+      }
     },
     createTextGeometry: function CanvasGraphics_createTextGeometry() {
       var geometry = {};
       var ctx = this.ctx;
       var font = this.current.font;
       var ctxMatrix = ctx.mozCurrentTransform;
       if (ctxMatrix) {
         var bl = Util.applyTransform([0, 0], ctxMatrix);
@@ -2791,19 +2845,18 @@ var CanvasGraphics = (function CanvasGra
       var ctx = this.ctx;
       var current = this.current;
       var font = current.font;
       var glyphs = font.charsToGlyphs(str);
       var fontSize = current.fontSize;
       var fontSizeScale = current.fontSizeScale;
       var charSpacing = current.charSpacing;
       var wordSpacing = current.wordSpacing;
-      var textHScale = current.textHScale;
-      var fontMatrix = current.fontMatrix || IDENTITY_MATRIX;
-      var textHScale2 = textHScale * fontMatrix[0];
+      var textHScale = current.textHScale * current.fontDirection;
+      var fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX;
       var glyphsLength = glyphs.length;
       var textLayer = this.textLayer;
       var geom;
       var textSelection = textLayer && !skipTextSelection ? true : false;
       var textRenderingMode = current.textRenderingMode;
       var canvasWidth = 0.0;
 
       // Type3 fonts - each glyph is a "mini-PDF"
@@ -2832,33 +2885,32 @@ var CanvasGraphics = (function CanvasGra
 
           this.save();
           ctx.scale(fontSize, fontSize);
           ctx.transform.apply(ctx, fontMatrix);
           this.executeOperatorList(glyph.operatorList);
           this.restore();
 
           var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
-          var width = transformed[0] * fontSize +
-              Util.sign(current.fontMatrix[0]) * charSpacing;
+          var width = (transformed[0] * fontSize + charSpacing) *
+                      current.fontDirection;
 
           ctx.translate(width, 0);
           current.x += width * textHScale;
 
           canvasWidth += width;
         }
         ctx.restore();
       } else {
         ctx.save();
         this.applyTextTransforms();
 
         var lineWidth = current.lineWidth;
         var a1 = current.textMatrix[0], b1 = current.textMatrix[1];
-        var a2 = fontMatrix[0], b2 = fontMatrix[1];
-        var scale = Math.sqrt((a1 * a1 + b1 * b1) * (a2 * a2 + b2 * b2));
+        var scale = Math.sqrt(a1 * a1 + b1 * b1);
         if (scale == 0 || lineWidth == 0)
           lineWidth = this.getSinglePixelWidth();
         else
           lineWidth /= scale;
 
         if (textSelection)
           geom = this.createTextGeometry();
 
@@ -2869,23 +2921,23 @@ var CanvasGraphics = (function CanvasGra
 
         ctx.lineWidth = lineWidth;
 
         var x = 0;
         for (var i = 0; i < glyphsLength; ++i) {
           var glyph = glyphs[i];
           if (glyph === null) {
             // word break
-            x += Util.sign(current.fontMatrix[0]) * wordSpacing;
+            x += current.fontDirection * wordSpacing;
             continue;
           }
 
           var character = glyph.fontChar;
-          var charWidth = glyph.width * fontSize * 0.001 +
-              Util.sign(current.fontMatrix[0]) * charSpacing;
+          var charWidth = glyph.width * fontSize * current.fontMatrix[0] +
+                          charSpacing * current.fontDirection;
 
           if (!glyph.disabled) {
             var scaledX = x / fontSizeScale;
             switch (textRenderingMode) {
               default: // other unsupported rendering modes
               case TextRenderingMode.FILL:
               case TextRenderingMode.FILL_ADD_TO_PATH:
                 ctx.fillText(character, scaledX, 0);
@@ -2908,59 +2960,52 @@ var CanvasGraphics = (function CanvasGra
               clipCtx.fillText(character, scaledX, 0);
             }
           }
 
           x += charWidth;
 
           canvasWidth += charWidth;
         }
-        current.x += x * textHScale2;
+        current.x += x * textHScale;
         ctx.restore();
       }
 
       if (textSelection) {
         geom.canvasWidth = canvasWidth;
         this.textLayer.appendText(geom);
       }
 
       return canvasWidth;
     },
     showSpacedText: function CanvasGraphics_showSpacedText(arr) {
       var ctx = this.ctx;
       var current = this.current;
       var font = current.font;
       var fontSize = current.fontSize;
-      var textHScale = current.textHScale;
-      if (!font.coded)
-        textHScale *= (current.fontMatrix || IDENTITY_MATRIX)[0];
+      var textHScale = current.textHScale * (current.fontMatrix && !font.coded ?
+        current.fontMatrix[0] : FONT_IDENTITY_MATRIX[0]) *
+        current.fontDirection;
       var arrLength = arr.length;
       var textLayer = this.textLayer;
       var geom;
       var canvasWidth = 0.0;
       var textSelection = textLayer ? true : false;
 
       if (textSelection) {
         ctx.save();
-        // Type3 fonts - each glyph is a "mini-PDF" (see also showText)
-        if (font.coded) {
-          ctx.transform.apply(ctx, current.textMatrix);
-          ctx.scale(1, -1);
-          ctx.translate(current.x, -1 * current.y);
-          ctx.scale(textHScale, 1);
-        } else
-          this.applyTextTransforms();
+        this.applyTextTransforms();
         geom = this.createTextGeometry();
         ctx.restore();
       }
 
       for (var i = 0; i < arrLength; ++i) {
         var e = arr[i];
         if (isNum(e)) {
-          var spacingLength = -e * 0.001 * fontSize * textHScale;
+          var spacingLength = -e * fontSize * textHScale;
           current.x += spacingLength;
 
           if (textSelection)
             canvasWidth += spacingLength;
         } else if (isString(e)) {
           var shownCanvasWidth = this.showText(e, true);
 
           if (textSelection)
@@ -3279,75 +3324,56 @@ var CanvasGraphics = (function CanvasGra
       ctx.scale(1 / width, -1 / height);
 
       var currentTransform = ctx.mozCurrentTransformInverse;
       var widthScale = Math.max(Math.abs(currentTransform[0]), 1);
       var heightScale = Math.max(Math.abs(currentTransform[3]), 1);
       var tmpCanvas = createScratchCanvas(width, height);
       var tmpCtx = tmpCanvas.getContext('2d');
 
-      if (widthScale >= 2 || heightScale >= 2) {
+      if (widthScale > 2 || heightScale > 2) {
         // canvas does not resize well large images to small -- using simple
         // algorithm to perform pre-scaling
-        tmpCanvas = rescaleImage(imgData.data,
+        tmpCanvas = prescaleImage(imgData.data,
                                  width, height,
                                  widthScale, heightScale);
-        ctx.scale(widthScale, heightScale);
-        ctx.drawImage(tmpCanvas, 0, -height / heightScale);
+        ctx.drawImage(tmpCanvas, 0, 0, tmpCanvas.width, tmpCanvas.height,
+                                 0, -height, width, height);
       } else {
         if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) {
           tmpCtx.putImageData(imgData, 0, 0);
         } else {
-          this.putBinaryImageData(tmpCtx, imgData);
+          putBinaryImageData(tmpCtx, imgData.data, width, height);
         }
         ctx.drawImage(tmpCanvas, 0, -height);
       }
       this.restore();
     },
 
     paintInlineImageXObjectGroup:
       function CanvasGraphics_paintInlineImageXObjectGroup(imgData, map) {
       var ctx = this.ctx;
       var w = imgData.width;
       var h = imgData.height;
 
       var tmpCanvas = createScratchCanvas(w, h);
       var tmpCtx = tmpCanvas.getContext('2d');
-      this.putBinaryImageData(tmpCtx, imgData);
+      putBinaryImageData(tmpCtx, imgData.data, w, h);
 
       for (var i = 0, ii = map.length; i < ii; i++) {
         var entry = map[i];
         ctx.save();
         ctx.transform.apply(ctx, entry.transform);
         ctx.scale(1, -1);
         ctx.drawImage(tmpCanvas, entry.x, entry.y, entry.w, entry.h,
                       0, -1, 1, 1);
         ctx.restore();
       }
     },
 
-    putBinaryImageData: function CanvasGraphics_putBinaryImageData(ctx,
-                                                                   imgData) {
-      var w = imgData.width, h = imgData.height;
-      var tmpImgData = 'createImageData' in ctx ? ctx.createImageData(w, h) :
-        ctx.getImageData(0, 0, w, h);
-
-      var tmpImgDataPixels = tmpImgData.data;
-      var data = imgData.data;
-      if ('set' in tmpImgDataPixels)
-        tmpImgDataPixels.set(data);
-      else {
-        // Copy over the imageData pixel by pixel.
-        for (var i = 0, ii = tmpImgDataPixels.length; i < ii; i++)
-          tmpImgDataPixels[i] = data[i];
-      }
-
-      ctx.putImageData(tmpImgData, 0, 0);
-    },
-
     // Marked content
 
     markPoint: function CanvasGraphics_markPoint(tag) {
       // TODO Marked content.
     },
     markPointProps: function CanvasGraphics_markPointProps(tag, properties) {
       // TODO Marked content.
     },
@@ -3732,18 +3758,19 @@ var XRef = (function XRefClosure() {
     var trailerDict = this.readXRef(startXRef);
     trailerDict.assignXref(this);
     this.trailer = trailerDict;
     // prepare the XRef cache
     this.cache = [];
 
     var encrypt = trailerDict.get('Encrypt');
     if (encrypt) {
-      var fileId = trailerDict.get('ID');
-      this.encrypt = new CipherTransformFactory(encrypt, fileId[0], password);
+      var ids = trailerDict.get('ID');
+      var fileId = (ids && ids.length) ? ids[0] : '';
+      this.encrypt = new CipherTransformFactory(encrypt, fileId, password);
     }
 
     // get the root dictionary (catalog) object
     if (!(this.root = trailerDict.get('Root')))
       error('Invalid root reference');
   }
 
   XRef.prototype = {
@@ -14174,111 +14201,114 @@ var PartialEvaluator = (function Partial
     this.xref = xref;
     this.handler = handler;
     this.pageIndex = pageIndex;
     this.uniquePrefix = uniquePrefix;
     this.objIdCounter = 0;
     this.fontIdCounter = 0;
   }
 
+  // Specifies properties for each command
+  //
+  // If variableArgs === true: [0, `numArgs`] expected
+  // If variableArgs === false: exactly `numArgs` expected
   var OP_MAP = {
-    // Graphics state
-    w: 'setLineWidth',
-    J: 'setLineCap',
-    j: 'setLineJoin',
-    M: 'setMiterLimit',
-    d: 'setDash',
-    ri: 'setRenderingIntent',
-    i: 'setFlatness',
-    gs: 'setGState',
-    q: 'save',
-    Q: 'restore',
-    cm: 'transform',
+    // Graphic state
+    w: { fnName: 'setLineWidth', numArgs: 1, variableArgs: false },
+    J: { fnName: 'setLineCap', numArgs: 1, variableArgs: false },
+    j: { fnName: 'setLineJoin', numArgs: 1, variableArgs: false },
+    M: { fnName: 'setMiterLimit', numArgs: 1, variableArgs: false },
+    d: { fnName: 'setDash', numArgs: 2, variableArgs: false },
+    ri: { fnName: 'setRenderingIntent', numArgs: 1, variableArgs: false },
+    i: { fnName: 'setFlatness', numArgs: 1, variableArgs: false },
+    gs: { fnName: 'setGState', numArgs: 1, variableArgs: false },
+    q: { fnName: 'save', numArgs: 0, variableArgs: false },
+    Q: { fnName: 'restore', numArgs: 0, variableArgs: false },
+    cm: { fnName: 'transform', numArgs: 6, variableArgs: false },
 
     // Path
-    m: 'moveTo',
-    l: 'lineTo',
-    c: 'curveTo',
-    v: 'curveTo2',
-    y: 'curveTo3',
-    h: 'closePath',
-    re: 'rectangle',
-    S: 'stroke',
-    s: 'closeStroke',
-    f: 'fill',
-    F: 'fill',
-    'f*': 'eoFill',
-    B: 'fillStroke',
-    'B*': 'eoFillStroke',
-    b: 'closeFillStroke',
-    'b*': 'closeEOFillStroke',
-    n: 'endPath',
+    m: { fnName: 'moveTo', numArgs: 2, variableArgs: false },
+    l: { fnName: 'lineTo', numArgs: 2, variableArgs: false },
+    c: { fnName: 'curveTo', numArgs: 6, variableArgs: false },
+    v: { fnName: 'curveTo2', numArgs: 4, variableArgs: false },
+    y: { fnName: 'curveTo3', numArgs: 4, variableArgs: false },
+    h: { fnName: 'closePath', numArgs: 0, variableArgs: false },
+    re: { fnName: 'rectangle', numArgs: 4, variableArgs: false },
+    S: { fnName: 'stroke', numArgs: 0, variableArgs: false },
+    s: { fnName: 'closeStroke', numArgs: 0, variableArgs: false },
+    f: { fnName: 'fill', numArgs: 0, variableArgs: false },
+    F: { fnName: 'fill', numArgs: 0, variableArgs: false },
+    'f*': { fnName: 'eoFill', numArgs: 0, variableArgs: false },
+    B: { fnName: 'fillStroke', numArgs: 0, variableArgs: false },
+    'B*': { fnName: 'eoFillStroke', numArgs: 0, variableArgs: false },
+    b: { fnName: 'closeFillStroke', numArgs: 0, variableArgs: false },
+    'b*': { fnName: 'closeEOFillStroke', numArgs: 0, variableArgs: false },
+    n: { fnName: 'endPath', numArgs: 0, variableArgs: false },
 
     // Clipping
-    W: 'clip',
-    'W*': 'eoClip',
+    W: { fnName: 'clip', numArgs: 0, variableArgs: false },
+    'W*': { fnName: 'eoClip', numArgs: 0, variableArgs: false },
 
     // Text
-    BT: 'beginText',
-    ET: 'endText',
-    Tc: 'setCharSpacing',
-    Tw: 'setWordSpacing',
-    Tz: 'setHScale',
-    TL: 'setLeading',
-    Tf: 'setFont',
-    Tr: 'setTextRenderingMode',
-    Ts: 'setTextRise',
-    Td: 'moveText',
-    TD: 'setLeadingMoveText',
-    Tm: 'setTextMatrix',
-    'T*': 'nextLine',
-    Tj: 'showText',
-    TJ: 'showSpacedText',
-    "'": 'nextLineShowText',
-    '"': 'nextLineSetSpacingShowText',
+    BT: { fnName: 'beginText', numArgs: 0, variableArgs: false },
+    ET: { fnName: 'endText', numArgs: 0, variableArgs: false },
+    Tc: { fnName: 'setCharSpacing', numArgs: 1, variableArgs: false },
+    Tw: { fnName: 'setWordSpacing', numArgs: 1, variableArgs: false },
+    Tz: { fnName: 'setHScale', numArgs: 1, variableArgs: false },
+    TL: { fnName: 'setLeading', numArgs: 1, variableArgs: false },
+    Tf: { fnName: 'setFont', numArgs: 2, variableArgs: false },
+    Tr: { fnName: 'setTextRenderingMode', numArgs: 1, variableArgs: false },
+    Ts: { fnName: 'setTextRise', numArgs: 1, variableArgs: false },
+    Td: { fnName: 'moveText', numArgs: 2, variableArgs: false },
+    TD: { fnName: 'setLeadingMoveText', numArgs: 2, variableArgs: false },
+    Tm: { fnName: 'setTextMatrix', numArgs: 6, variableArgs: false },
+    'T*': { fnName: 'nextLine', numArgs: 0, variableArgs: false },
+    Tj: { fnName: 'showText', numArgs: 1, variableArgs: false },
+    TJ: { fnName: 'showSpacedText', numArgs: 1, variableArgs: false },
+    '\'': { fnName: 'nextLineShowText', numArgs: 1, variableArgs: false },
+    '"': { fnName: 'nextLineSetSpacingShowText', numArgs: 3,
+      variableArgs: false },
 
     // Type3 fonts
-    d0: 'setCharWidth',
-    d1: 'setCharWidthAndBounds',
+    d0: { fnName: 'setCharWidth', numArgs: 2, variableArgs: false },
+    d1: { fnName: 'setCharWidthAndBounds', numArgs: 6, variableArgs: false },
 
     // Color
-    CS: 'setStrokeColorSpace',
-    cs: 'setFillColorSpace',
-    SC: 'setStrokeColor',
-    SCN: 'setStrokeColorN',
-    sc: 'setFillColor',
-    scn: 'setFillColorN',
-    G: 'setStrokeGray',
-    g: 'setFillGray',
-    RG: 'setStrokeRGBColor',
-    rg: 'setFillRGBColor',
-    K: 'setStrokeCMYKColor',
-    k: 'setFillCMYKColor',
+    CS: { fnName: 'setStrokeColorSpace', numArgs: 1, variableArgs: false },
+    cs: { fnName: 'setFillColorSpace', numArgs: 1, variableArgs: false },
+    SC: { fnName: 'setStrokeColor', numArgs: 4, variableArgs: true },
+    SCN: { fnName: 'setStrokeColorN', numArgs: 33, variableArgs: true },
+    sc: { fnName: 'setFillColor', numArgs: 4, variableArgs: true },
+    scn: { fnName: 'setFillColorN', numArgs: 33, variableArgs: true },
+    G: { fnName: 'setStrokeGray', numArgs: 1, variableArgs: false },
+    g: { fnName: 'setFillGray', numArgs: 1, variableArgs: false },
+    RG: { fnName: 'setStrokeRGBColor', numArgs: 3, variableArgs: false },
+    rg: { fnName: 'setFillRGBColor', numArgs: 3, variableArgs: false },
+    K: { fnName: 'setStrokeCMYKColor', numArgs: 4, variableArgs: false },
+    k: { fnName: 'setFillCMYKColor', numArgs: 4, variableArgs: false },
 
     // Shading
-    sh: 'shadingFill',
+    sh: { fnName: 'shadingFill', numArgs: 1, variableArgs: false },
 
     // Images
-    BI: 'beginInlineImage',
-    ID: 'beginImageData',
-    EI: 'endInlineImage',
+    BI: { fnName: 'beginInlineImage', numArgs: 0, variableArgs: false },
+    ID: { fnName: 'beginImageData', numArgs: 0, variableArgs: false },
+    EI: { fnName: 'endInlineImage', numArgs: 0, variableArgs: false },
 
     // XObjects
-    Do: 'paintXObject',
-
-    // Marked content
-    MP: 'markPoint',
-    DP: 'markPointProps',
-    BMC: 'beginMarkedContent',
-    BDC: 'beginMarkedContentProps',
-    EMC: 'endMarkedContent',
+    Do: { fnName: 'paintXObject', numArgs: 1, variableArgs: false },
+    MP: { fnName: 'markPoint', numArgs: 1, variableArgs: false },
+    DP: { fnName: 'markPointProps', numArgs: 2, variableArgs: false },
+    BMC: { fnName: 'beginMarkedContent', numArgs: 1, variableArgs: false },
+    BDC: { fnName: 'beginMarkedContentProps', numArgs: 2, variableArgs: false },
+    EMC: { fnName: 'endMarkedContent', numArgs: 0, variableArgs: false },
 
     // Compatibility
-    BX: 'beginCompat',
-    EX: 'endCompat',
+    BX: { fnName: 'beginCompat', numArgs: 0, variableArgs: false },
+    EX: { fnName: 'endCompat', numArgs: 0, variableArgs: false },
 
     // (reserved partial commands for the lexer)
     BM: null,
     BD: null,
     'true': null,
     fa: null,
     fal: null,
     fals: null,
@@ -14458,30 +14488,61 @@ var PartialEvaluator = (function Partial
       }
 
       var fnArray = queue.fnArray, argsArray = queue.argsArray;
       var dependencyArray = dependency || [];
 
       resources = resources || new Dict();
       var xobjs = resources.get('XObject') || new Dict();
       var patterns = resources.get('Pattern') || new Dict();
+      // TODO(mduan): pass array of knownCommands rather than OP_MAP
+      // dictionary
       var parser = new Parser(new Lexer(stream, OP_MAP), false, xref);
       var res = resources;
       var args = [], obj;
       var TILING_PATTERN = 1, SHADING_PATTERN = 2;
 
       while (true) {
         obj = parser.getObj();
-        if (isEOF(obj))
-          break;
+        if (isEOF(obj)) {
+          break;
+        }
 
         if (isCmd(obj)) {
           var cmd = obj.cmd;
-          var fn = OP_MAP[cmd];
-          assertWellFormed(fn, 'Unknown command "' + cmd + '"');
+
+          // Check that the command is valid
+          var opSpec = OP_MAP[cmd];
+          if (!opSpec) {
+            warn('Unknown command "' + cmd + '"');
+            continue;
+          }
+
+          var fn = opSpec.fnName;
+
+          // Validate the number of arguments for the command
+          if (opSpec.variableArgs) {
+            if (args.length > opSpec.numArgs) {
+              info('Command ' + fn + ': expected [0,' + opSpec.numArgs +
+                  '] args, but received ' + args.length + ' args');
+            }
+          } else {
+            if (args.length < opSpec.numArgs) {
+              // If we receive too few args, it's not possible to possible
+              // to execute the command, so skip the command
+              info('Command ' + fn + ': because expected ' + opSpec.numArgs +
+                  ' args, but received ' + args.length + ' args; skipping');
+              args = [];
+              continue;
+            } else if (args.length > opSpec.numArgs) {
+              info('Command ' + fn + ': expected ' + opSpec.numArgs +
+                  ' args, but received ' + args.length + ' args');
+            }
+          }
+
           // TODO figure out how to type-check vararg functions
 
           if ((cmd == 'SCN' || cmd == 'scn') && !args[args.length - 1].code) {
             // compile tiling patterns
             var patternName = args[args.length - 1];
             // SCN/scn applies patterns along with normal colors
             if (isName(patternName)) {
               var pattern = patterns.get(patternName.name);
@@ -14653,18 +14714,18 @@ var PartialEvaluator = (function Partial
               args = [gsStateObj];
               break;
           } // switch
 
           fnArray.push(fn);
           argsArray.push(args);
           args = [];
         } else if (obj != null) {
+          args.push(obj instanceof Dict ? obj.getAll() : obj);
           assertWellFormed(args.length <= 33, 'Too many arguments');
-          args.push(obj instanceof Dict ? obj.getAll() : obj);
         }
       }
 
       return queue;
     },
 
     optimizeQueue: function PartialEvaluator_optimizeQueue(queue) {
       var fnArray = queue.fnArray, argsArray = queue.argsArray;
@@ -14935,16 +14996,20 @@ var PartialEvaluator = (function Partial
         if (isDict(cidSystemInfo)) {
           properties.cidSystemInfo = {
             registry: cidSystemInfo.get('Registry'),
             ordering: cidSystemInfo.get('Ordering'),
             supplement: cidSystemInfo.get('Supplement')
           };
         }
 
+        var cidEncoding = baseDict.get('Encoding');
+        if (isName(cidEncoding))
+          properties.cidEncoding = cidEncoding.name;
+
         var cidToGidMap = dict.get('CIDToGIDMap');
         if (isStream(cidToGidMap))
           properties.cidToGidMap = this.readCidToGidMap(cidToGidMap);
       }
 
       var flags = properties.flags;
       var differences = [];
       var baseEncoding = Encodings.StandardEncoding;
@@ -15195,19 +15260,40 @@ var PartialEvaluator = (function Partial
       }
       if (isMonospace)
         properties.flags |= FontFlags.FixedPitch;
 
       properties.defaultWidth = defaultWidth;
       properties.widths = glyphsWidths;
     },
 
+    isSerifFont: function PartialEvaluator_isSerifFont(baseFontName) {
+
+      // Simulating descriptor flags attribute
+      var fontNameWoStyle = baseFontName.split('-')[0];
+      return (fontNameWoStyle in serifFonts) ||
+          (fontNameWoStyle.search(/serif/gi) !== -1);
+    },
+
     getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) {
       var defaultWidth = 0, widths = [], monospace = false;
-      var glyphWidths = Metrics[stdFontMap[name] || name];
+
+      var lookupName = stdFontMap[name] || name;
+
+      if (!(lookupName in Metrics)) {
+        // Use default fonts for looking up font metrics if the passed
+        // font is not a base font
+        if (this.isSerifFont(name)) {
+          lookupName = 'Times-Roman';
+        } else {
+          lookupName = 'Helvetica';
+        }
+      }
+      var glyphWidths = Metrics[lookupName];
+
       if (isNum(glyphWidths)) {
         defaultWidth = glyphWidths;
         monospace = true;
       } else {
         widths = glyphWidths;
       }
 
       return {
@@ -15259,18 +15345,18 @@ var PartialEvaluator = (function Partial
             error('Base font is not specified');
 
           // Using base font name as a font name.
           baseFontName = baseFontName.name.replace(/[,_]/g, '-');
           var metrics = this.getBaseFontMetrics(baseFontName);
 
           // Simulating descriptor flags attribute
           var fontNameWoStyle = baseFontName.split('-')[0];
-          var flags = (serifFonts[fontNameWoStyle] ||
-            (fontNameWoStyle.search(/serif/gi) != -1) ? FontFlags.Serif : 0) |
+          var flags = (
+            this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) |
             (metrics.monospace ? FontFlags.FixedPitch : 0) |
             (symbolsFonts[fontNameWoStyle] ? FontFlags.Symbolic :
             FontFlags.Nonsymbolic);
 
           var properties = {
             type: type.name,
             widths: metrics.widths,
             defaultWidth: metrics.defaultWidth,
@@ -15286,20 +15372,36 @@ var PartialEvaluator = (function Partial
 
       // According to the spec if 'FontDescriptor' is declared, 'FirstChar',
       // 'LastChar' and 'Widths' should exist too, but some PDF encoders seem
       // to ignore this rule when a variant of a standart font is used.
       // TODO Fill the width array depending on which of the base font this is
       // a variant.
       var firstChar = dict.get('FirstChar') || 0;
       var lastChar = dict.get('LastChar') || maxCharIndex;
+
       var fontName = descriptor.get('FontName');
+      var baseFont = baseDict.get('BaseFont');
       // Some bad pdf's have a string as the font name.
-      if (isString(fontName))
+      if (isString(fontName)) {
         fontName = new Name(fontName);
+      }
+      if (isString(baseFont)) {
+        baseFont = new Name(baseFont);
+      }
+
+      var fontNameStr = fontName && fontName.name;
+      var baseFontStr = baseFont && baseFont.name;
+      if (fontNameStr !== baseFontStr) {
+        warn('The FontDescriptor\'s FontName is "' + fontNameStr +
+            '" but should be the same as the Font\'s BaseFont "' +
+            baseFontStr + '"');
+      }
+      fontName = fontName || baseFont;
+
       assertWellFormed(isName(fontName), 'invalid font name');
 
       var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3');
       if (fontFile) {
         if (fontFile.dict) {
           var subtype = fontFile.dict.get('Subtype');
           if (subtype)
             subtype = subtype.name;
@@ -15315,17 +15417,17 @@ var PartialEvaluator = (function Partial
         subtype: subtype,
         file: fontFile,
         length1: length1,
         length2: length2,
         loadedName: baseDict.loadedName,
         composite: composite,
         wideChars: composite,
         fixedPitch: false,
-        fontMatrix: dict.get('FontMatrix') || IDENTITY_MATRIX,
+        fontMatrix: dict.get('FontMatrix') || FONT_IDENTITY_MATRIX,
         firstChar: firstChar || 0,
         lastChar: lastChar || maxCharIndex,
         bbox: descriptor.get('FontBBox'),
         ascent: descriptor.get('Ascent'),
         descent: descriptor.get('Descent'),
         xHeight: descriptor.get('XHeight'),
         capHeight: descriptor.get('CapHeight'),
         flags: descriptor.get('Flags'),
@@ -15378,16 +15480,18 @@ var SYMBOLIC_FONT_GLYPH_OFFSET = 0xF000;
 
 // PDF Glyph Space Units are one Thousandth of a TextSpace Unit
 // except for Type 3 fonts
 var PDF_GLYPH_SPACE_UNITS = 1000;
 
 // Until hinting is fully supported this constant can be used
 var HINTING_ENABLED = false;
 
+var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
+
 var FontFlags = {
   FixedPitch: 1,
   Serif: 2,
   Symbolic: 4,
   Script: 8,
   Nonsymbolic: 32,
   Italic: 64,
   AllCap: 65536,
@@ -15748,16 +15852,58 @@ var serifFonts = {
   'Versailles': true, 'Wanted': true, 'Weiss': true,
   'Wide Latin': true, 'Windsor': true, 'XITS': true
 };
 
 var symbolsFonts = {
   'Dingbats': true, 'Symbol': true, 'ZapfDingbats': true
 };
 
+var CMapConverterList = {
+  'H': jis7ToUnicode,
+  'V': jis7ToUnicode,
+  'EUC-H': eucjpToUnicode,
+  'EUC-V': eucjpToUnicode,
+  '90ms-RKSJ-H': sjisToUnicode,
+  '90ms-RKSJ-V': sjisToUnicode,
+  '90msp-RKSJ-H': sjisToUnicode,
+  '90msp-RKSJ-V': sjisToUnicode
+};
+
+var decodeBytes;
+if (typeof TextDecoder !== 'undefined') {
+  decodeBytes = function(bytes, encoding) {
+    return new TextDecoder(encoding).decode(bytes);
+  };
+} else if (typeof FileReaderSync !== 'undefined') {
+  decodeBytes = function(bytes, encoding) {
+    return new FileReaderSync().readAsText(new Blob([bytes]), encoding);
+  };
+} else {
+  // Clear the list so that decodeBytes will never be called.
+  CMapConverterList = {};
+}
+
+function jis7ToUnicode(str) {
+  var bytes = stringToBytes(str);
+  var length = bytes.length;
+  for (var i = 0; i < length; ++i) {
+    bytes[i] |= 0x80;
+  }
+  return decodeBytes(bytes, 'euc-jp');
+}
+
+function eucjpToUnicode(str) {
+  return decodeBytes(stringToBytes(str), 'euc-jp');
+}
+
+function sjisToUnicode(str) {
+  return decodeBytes(stringToBytes(str), 'shift_jis');
+}
+
 // Some characters, e.g. copyrightserif, mapped to the private use area and
 // might not be displayed using standard fonts. Mapping/hacking well-known chars
 // to the similar equivalents in the normal characters range.
 function mapPrivateUseChars(code) {
   switch (code) {
     case 0xF8E9: // copyrightsans
     case 0xF6D9: // copyrightserif
       return 0x00A9; // copyright
@@ -17377,16 +17523,29 @@ function fontCharsToUnicode(charCodes, f
     var glyphUnicode = glyph.unicode;
     if (glyphUnicode in NormalizedUnicodes)
       glyphUnicode = NormalizedUnicodes[glyphUnicode];
     result += reverseIfRtl(glyphUnicode);
   }
   return result;
 }
 
+function adjustWidths(properties) {
+  if (properties.fontMatrix[0] === FONT_IDENTITY_MATRIX[0]) {
+    return;
+  }
+  // adjusting width to fontMatrix scale
+  var scale = 0.001 / properties.fontMatrix[0];
+  var glyphsWidths = properties.widths;
+  for (var glyph in glyphsWidths) {
+    glyphsWidths[glyph] *= scale;
+  }
+  properties.defaultWidth *= scale;
+}
+
 /**
  * 'Font' is the class the outside world should use, it encapsulate all the font
  * decoding logics whatever type it is (assuming the font type is supported).
  *
  * For example to read a Type1 font and to attach it to the document:
  *   var type1Font = new Font("MyFontName", binaryFile, propertiesObject);
  *   type1Font.bind();
  */
@@ -17423,24 +17582,24 @@ var Font = (function FontClosure() {
     this.differences = properties.differences;
     this.widths = properties.widths;
     this.defaultWidth = properties.defaultWidth;
     this.composite = properties.composite;
     this.wideChars = properties.wideChars;
     this.hasEncoding = properties.hasEncoding;
 
     this.fontMatrix = properties.fontMatrix;
-    this.widthMultiplier = 1.0;
     if (properties.type == 'Type3') {
       this.encoding = properties.baseEncoding;
       return;
     }
 
     // Trying to fix encoding using glyph CIDSystemInfo.
     this.loadCidToUnicode(properties);
+    this.cidEncoding = properties.cidEncoding;
 
     if (properties.toUnicode)
       this.toUnicode = properties.toUnicode;
     else
       this.rebuildToUnicode(properties);
 
     this.toFontChar = this.buildToFontChar(this.toUnicode);
 
@@ -17481,16 +17640,18 @@ var Font = (function FontClosure() {
     switch (type) {
       case 'Type1':
       case 'CIDFontType0':
         this.mimetype = 'font/opentype';
 
         var cff = (subtype == 'Type1C' || subtype == 'CIDFontType0C') ?
           new CFFFont(file, properties) : new Type1Font(name, file, properties);
 
+        adjustWidths(properties);
+
         // Wrap the CFF data inside an OTF font file
         data = this.convert(name, cff, properties);
         break;
 
       case 'TrueType':
       case 'CIDFontType2':
         this.mimetype = 'font/opentype';
 
@@ -17500,20 +17661,23 @@ var Font = (function FontClosure() {
         break;
 
       default:
         warn('Font ' + type + ' is not supported');
         break;
     }
 
     this.data = data;
+
+    // Transfer some properties again that could change during font conversion
     this.fontMatrix = properties.fontMatrix;
-    this.widthMultiplier = !properties.fontMatrix ? 1.0 :
-      1.0 / properties.fontMatrix[0];
+    this.widths = properties.widths;
+    this.defaultWidth = properties.defaultWidth;
     this.encoding = properties.baseEncoding;
+
     this.loading = true;
   };
 
   var numFonts = 0;
   function getUniqueName() {
     return 'pdfFont' + numFonts++;
   }
 
@@ -17790,35 +17954,35 @@ var Font = (function FontClosure() {
         }
       }
     } else {
       // TODO
       firstCharIndex = 0;
       lastCharIndex = 255;
     }
 
-    var unitsPerEm = override.unitsPerEm || PDF_GLYPH_SPACE_UNITS;
-    var typoAscent = override.ascent || properties.ascent;
-    var typoDescent = override.descent || properties.descent;
+    var bbox = properties.bbox || [0, 0, 0, 0];
+    var unitsPerEm = override.unitsPerEm ||
+      1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0];
+
+    // if the font units differ to the PDF glyph space units
+    // then scale up the values
+    var scale = properties.ascentScaled ? 1.0 :
+      unitsPerEm / PDF_GLYPH_SPACE_UNITS;
+
+    var typoAscent = override.ascent || Math.round(scale *
+      (properties.ascent || bbox[3]));
+    var typoDescent = override.descent || Math.round(scale *
+      (properties.descent || bbox[1]));
+    if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) {
+      typoDescent = -typoDescent; // fixing incorrect descent
+    }
     var winAscent = override.yMax || typoAscent;
     var winDescent = -override.yMin || -typoDescent;
 
-    // if there is a units per em value but no other override
-    // then scale the calculated ascent
-    if (unitsPerEm != PDF_GLYPH_SPACE_UNITS &&
-        'undefined' == typeof(override.ascent)) {
-      // if the font units differ to the PDF glyph space units
-      // then scale up the values
-      typoAscent = Math.round(typoAscent * unitsPerEm / PDF_GLYPH_SPACE_UNITS);
-      typoDescent = Math.round(typoDescent * unitsPerEm /
-        PDF_GLYPH_SPACE_UNITS);
-      winAscent = typoAscent;
-      winDescent = -typoDescent;
-    }
-
     return '\x00\x03' + // version
            '\x02\x24' + // xAvgCharWidth
            '\x01\xF4' + // usWeightClass
            '\x00\x05' + // usWidthClass
            '\x00\x00' + // fstype (0 to let the font loads via font-face on IE)
            '\x02\x8A' + // ySubscriptXSize
            '\x02\xBB' + // ySubscriptYSize
            '\x00\x00' + // ySubscriptXOffset
@@ -19094,17 +19258,17 @@ var Font = (function FontClosure() {
       if (properties.subtype == 'CIDFontType0C') {
         var toFontChar = [];
         for (var i = 0; i < charstrings.length; ++i) {
           var charstring = charstrings[i];
           toFontChar[charstring.code] = charstring.unicode;
         }
         this.toFontChar = toFontChar;
       }
-      var unitsPerEm = properties.unitsPerEm || 1000; // defaulting to 1000
+      var unitsPerEm = 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0];
 
       var fields = {
         // PostScript Font Program
         'CFF ': font.data,
 
         // OS/2 and Windows Specific metrics
         'OS/2': stringToArray(createOS2Table(properties, charstrings)),
 
@@ -19270,16 +19434,25 @@ var Font = (function FontClosure() {
             cid += unicode.s;
         } else if (unicode) {
           cidToUnicodeMap[cid] = unicode;
           unicodeToCIDMap[unicode] = cid;
           cid++;
         } else
           cid++;
       }
+
+      var cidEncoding = properties.cidEncoding;
+      if (cidEncoding && cidEncoding.indexOf('Identity-') !== 0) {
+        // input is already Unicode for non-Identity CMap encodings.
+        // However, Unicode-to-CID conversion is needed
+        // regardless of the CMap encoding. So we can't reset
+        // unicodeToCID.
+        this.cidToUnicode = [];
+      }
     },
 
     bindDOM: function Font_bindDOM() {
       if (!this.data)
         return null;
 
       var data = bytesToString(this.data);
       var fontName = this.loadedName;
@@ -19333,42 +19506,38 @@ var Font = (function FontClosure() {
         // setting it to unicode if negative or undefined
         if (!(charcode > 0))
           charcode = glyphUnicode;
         // trying to get width via charcode
         width = this.widths[charcode];
         if (width)
           break; // the non-zero width found
       }
-      width = (width || this.defaultWidth) * this.widthMultiplier;
+      width = width || this.defaultWidth;
       // Do not shadow the property here. See discussion:
       // https://github.com/mozilla/pdf.js/pull/2127#discussion_r1662280
       this._shadowWidth = width;
       return width;
     },
 
     charToGlyph: function Font_charToGlyph(charcode) {
       var fontCharCode, width, operatorList, disabled;
 
       var width = this.widths[charcode];
 
       switch (this.type) {
         case 'CIDFontType0':
           if (this.noUnicodeAdaptation) {
             width = this.widths[this.unicodeToCID[charcode] || charcode];
-            fontCharCode = mapPrivateUseChars(charcode);
-            break;
           }
           fontCharCode = this.toFontChar[charcode] || charcode;
           break;
         case 'CIDFontType2':
           if (this.noUnicodeAdaptation) {
             width = this.widths[this.unicodeToCID[charcode] || charcode];
-            fontCharCode = mapPrivateUseChars(charcode);
-            break;
           }
           fontCharCode = this.toFontChar[charcode] || charcode;
           break;
         case 'Type1':
           var glyphName = this.differences[charcode] || this.encoding[charcode];
           if (!isNum(width))
             width = this.widths[glyphName];
           if (this.noUnicodeAdaptation) {
@@ -19414,17 +19583,17 @@ var Font = (function FontClosure() {
           break;
       }
 
       var unicodeChars = !('toUnicode' in this) ? charcode :
         this.toUnicode[charcode] || charcode;
       if (typeof unicodeChars === 'number')
         unicodeChars = String.fromCharCode(unicodeChars);
 
-      width = (isNum(width) ? width : this.defaultWidth) * this.widthMultiplier;
+      width = isNum(width) ? width : this.defaultWidth;
       disabled = this.unicodeIsEnabled ?
         !this.unicodeIsEnabled[fontCharCode] : false;
 
       return {
         fontChar: String.fromCharCode(fontCharCode),
         unicode: unicodeChars,
         width: width,
         disabled: disabled,
@@ -19443,18 +19612,30 @@ var Font = (function FontClosure() {
           return glyphs;
       }
 
       // lazily create the translation cache
       if (!charsCache)
         charsCache = this.charsCache = Object.create(null);
 
       glyphs = [];
-
-      if (this.wideChars) {
+      var charsCacheKey = chars;
+
+      var converter;
+      var cidEncoding = this.cidEncoding;
+      if (cidEncoding) {
+        converter = CMapConverterList[cidEncoding];
+        if (converter) {
+          chars = converter(chars);
+        } else if (cidEncoding.indexOf('Uni') !== 0 &&
+                   cidEncoding.indexOf('Identity-') !== 0) {
+          warn('Unsupported CMap: ' + cidEncoding);
+        }
+      }
+      if (!converter && this.wideChars) {
         // composite fonts have multi-byte strings convert the string from
         // single-byte to multi-byte
         // XXX assuming CIDFonts are two-byte - later need to extract the
         // correct byte encoding according to the PDF spec
         var length = chars.length - 1; // looping over two bytes at a time so
                                        // loop should never end on the last byte
         for (var i = 0; i < length; i++) {
           var charcode = int16([chars.charCodeAt(i++), chars.charCodeAt(i)]);
@@ -19471,17 +19652,17 @@ var Font = (function FontClosure() {
           var glyph = this.charToGlyph(charcode);
           glyphs.push(glyph);
           if (charcode == 0x20)
             glyphs.push(null);
         }
       }
 
       // Enter the translated string into the cache
-      return (charsCache[chars] = glyphs);
+      return (charsCache[charsCacheKey] = glyphs);
     }
   };
 
   return Font;
 })();
 
 var ErrorFont = (function ErrorFontClosure() {
   function ErrorFont(error) {
@@ -19606,16 +19787,17 @@ var Type1Parser = function type1Parser()
       // return [vhstem] instead.
       '1': 'vstem',
       '2': 'hstem',
 
       '6': 'endchar', // seac
       // Type1 only command with command not (yet) built-in ,throw an error
       '7': -1, // sbw
 
+      '10': 'add',
       '11': 'sub',
       '12': 'div',
 
       // callothersubr is a mechanism to make calls on the postscript
       // interpreter, this is not supported by Type2 charstring but hopefully
       // most of the default commands can be ignored safely.
       '16': 'callothersubr',
 
@@ -19670,26 +19852,16 @@ var Type1Parser = function type1Parser()
         index--;
       } else {
         warn('Malformed charsting stack: found bad token ' + token + '.');
       }
     }
     return args;
   }
 
-  // Remove the same number of args from the stack that are in the args
-  // parameter. Args should be built from breakUpArgs().
-  function popArgs(stack, args) {
-    for (var i = 0, ii = args.length; i < ii; i++) {
-      for (var j = 0, jj = args[i].arg.length; j < jj; j++) {
-        stack.pop();
-      }
-    }
-  }
-
   function decodeCharString(array) {
     var charstring = [];
     var lsb = 0;
     var width = 0;
     var flexing = false;
 
     var value = '';
     var count = array.length;
@@ -19780,57 +19952,59 @@ var Type1Parser = function type1Parser()
               // example of this yet so we'll keep doing it here.
               var subrNumber = charstring.pop();
               switch (subrNumber) {
                 case 1:
                   flexing = true; // prepare for flex coordinates
                   break;
                 case 0:
                   var flexArgs = breakUpArgs(charstring, 17);
-                  popArgs(charstring, flexArgs);
-
-                  charstring.push(
-                    flexArgs[2].value + flexArgs[0].value, // bcp1x + rpx
-                    flexArgs[3].value + flexArgs[1].value, // bcp1y + rpy
-                    flexArgs[4].value, // bcp2x
-                    flexArgs[5].value, // bcp2y
-                    flexArgs[6].value, // p2x
-                    flexArgs[7].value, // p2y
-                    flexArgs[8].value, // bcp3x
-                    flexArgs[9].value, // bcp3y
-                    flexArgs[10].value, // bcp4x
-                    flexArgs[11].value, // bcp4y
-                    flexArgs[12].value, // p3x
-                    flexArgs[13].value, // p3y
-                    flexArgs[14].value, // flexDepth
+
+                  // removing all flex arguments from the stack
+                  charstring.splice(flexArgs[0].offset,
+                                    charstring.length - flexArgs[0].offset);
+
+                  charstring = charstring.concat(
+                    flexArgs[0].arg, // bcp1x +
+                    flexArgs[2].arg, // rpx
+                    ['add'],
+                    flexArgs[1].arg, // bcp1y +
+                    flexArgs[3].arg, // rpy
+                    ['add'],
+                    flexArgs[4].arg, // bcp2x
+                    flexArgs[5].arg, // bcp2y
+                    flexArgs[6].arg, // p2x
+                    flexArgs[7].arg, // p2y
+                    flexArgs[8].arg, // bcp3x
+                    flexArgs[9].arg, // bcp3y
+                    flexArgs[10].arg, // bcp4x
+                    flexArgs[11].arg, // bcp4y
+                    flexArgs[12].arg, // p3x
+                    flexArgs[13].arg, // p3y
+                    flexArgs[14].arg, // flexDepth
                     // 15 = finalx unused by flex
                     // 16 = finaly unused by flex
-                    'flex'
+                    ['flex']
                   );
 
                   flexing = false;
                   break;
               }
               continue;
             }
           } else if (value == 21 && flexing) { // rmoveto
             continue; // ignoring rmoveto
           } else if (value == 22 && flexing) { // hmoveto
             // Add the dy for flex.
             charstring.push(0);
             continue; // ignoring hmoveto
           } else if (value == 4 && flexing) { // vmoveto
-            // Add the dx for flex and but also swap the values so they are the
-            // right order.
-            var vArgs = breakUpArgs(charstring, 1);
-            popArgs(charstring, vArgs);
-            charstring.push(0);
-            for (var t = 0, tt = vArgs[0].arg.length; t < tt; t++) {
-              charstring.push(vArgs[0].arg[t]);
-            }
+            // Insert the dx for flex before dy.
+            var flexArgs = breakUpArgs(charstring, 1);
+            charstring.splice(flexArgs[0].offset, 0, 0);
             continue; // ignoring vmoveto
           } else if (!HINTING_ENABLED && (value == 1 || value == 3)) {
             charstring.push('drop', 'drop');
             continue;
           }
           command = charStringDictionary[value];
         }
 
@@ -19909,16 +20083,33 @@ var Type1Parser = function type1Parser()
 
     var count = 0;
     while (str[index++] != ' ')
       count++;
 
     return parseFloat(str.substr(start, count) || 0);
   }
 
+  function readBoolean(str, index) {
+    while (str[index] == ' ')
+      index++;
+
+    var start = index;
+
+    var count = 0;
+    var length = str.length;
+    while (index < length && str[index++] != ' ') {
+      count++;
+    }
+
+    // Use 1 and 0 since that's what type2 charstrings use.
+    return str.substr(start, count) === 'true' ? 1 : 0;
+  }
+
+
   function isSeparator(c) {
     return c == ' ' || c == '\n' || c == '\x0d';
   }
 
   this.extractFontProgram = function Type1Parser_extractFontProgram(stream) {
     var eexec = decrypt(stream, EEXEC_ENCRYPT_KEY, 4);
     var eexecStr = '';
     for (var i = 0, ii = eexec.length; i < ii; i++)
@@ -20010,38 +20201,46 @@ var Type1Parser = function type1Parser()
                 program.subrs[index] = str.charstring;
               }
               break;
             case '/BlueValues':
             case '/OtherBlues':
             case '/FamilyBlues':
             case '/FamilyOtherBlues':
               var blueArray = readNumberArray(eexecStr, i + 1);
-              if (blueArray.length > 0 && (blueArray.length % 2) == 0)
+              // *Blue* values may contain invalid data: disables reading of
+              // those values when hinting is disabled.
+              if (blueArray.length > 0 && (blueArray.length % 2) == 0 &&
+                  HINTING_ENABLED) {
                 program.properties.privateData[token.substring(1)] = blueArray;
+              }
               break;
             case '/StemSnapH':
             case '/StemSnapV':
               program.properties.privateData[token.substring(1)] =
                 readNumberArray(eexecStr, i + 1);
               break;
             case '/StdHW':
             case '/StdVW':
               program.properties.privateData[token.substring(1)] =
-                readNumberArray(eexecStr, i + 2)[0];
+                readNumberArray(eexecStr, i + 1)[0];
               break;
             case '/BlueShift':
             case '/lenIV':
             case '/BlueFuzz':
             case '/BlueScale':
             case '/LanguageGroup':
             case '/ExpansionFactor':
               program.properties.privateData[token.substring(1)] =
                 readNumber(eexecStr, i + 1);
               break;
+            case '/ForceBold':
+              program.properties.privateData[token.substring(1)] =
+                readBoolean(eexecStr, i + 1);
+              break;
           }
         } else if (c == '/') {
           token = glyph = '';
           while ((c = eexecStr[++i]) != ' ')
             glyph += c;
         }
       }
     }
@@ -20072,24 +20271,16 @@ var Type1Parser = function type1Parser()
         return token;
       };
 
       var c = headerString[i];
       if (isSeparator(c)) {
         switch (token) {
           case '/FontMatrix':
             var matrix = readNumberArray(headerString, i + 1);
-
-            // The FontMatrix is in unitPerEm, so make it pixels
-            for (var j = 0, jj = matrix.length; j < jj; j++)
-              matrix[j] *= 1000;
-
-            // Make the angle into the right direction
-            matrix[2] *= -1;
-
             properties.fontMatrix = matrix;
             break;
           case '/Encoding':
             var encodingArg = getToken();
             var encoding;
             if (!/^\d+$/.test(encodingArg)) {
               // encoding name is specified
               encoding = Encodings[encodingArg];
@@ -20287,16 +20478,17 @@ Type1Font.prototype = {
     'vstem': 3,
     'vmoveto': 4,
     'rlineto': 5,
     'hlineto': 6,
     'vlineto': 7,
     'rrcurveto': 8,
     'callsubr': 10,
     'return': 11,
+    'add': [12, 10],
     'sub': [12, 11],
     'div': [12, 12],
     'exch': [12, 28],
     'flex': [12, 35],
     'drop' : [12, 18],
     'endchar': 14,
     'rmoveto': 21,
     'hmoveto': 22,
@@ -20354,16 +20546,17 @@ Type1Font.prototype = {
 
     var topDict = new CFFTopDict();
     topDict.setByName('version', 0);
     topDict.setByName('Notice', 1);
     topDict.setByName('FullName', 2);
     topDict.setByName('FamilyName', 3);
     topDict.setByName('Weight', 4);
     topDict.setByName('Encoding', null); // placeholder
+    topDict.setByName('FontMatrix', properties.fontMatrix);
     topDict.setByName('FontBBox', properties.bbox);
     topDict.setByName('charset', null); // placeholder
     topDict.setByName('CharStrings', null); // placeholder
     topDict.setByName('Private', null); // placeholder
     cff.topDict = topDict;
 
     var strings = new CFFStrings();
     strings.add('Version 0.11'); // Version
@@ -20395,28 +20588,30 @@ Type1Font.prototype = {
     for (var i = 0; i < count; i++) {
       charStringsIndex.add(glyphs[i]);
     }
     cff.charStrings = charStringsIndex;
 
     var privateDict = new CFFPrivateDict();
     privateDict.setByName('Subrs', null); // placeholder
     var fields = [
-      // TODO: missing StdHW, StdVW, ForceBold
       'BlueValues',
       'OtherBlues',
       'FamilyBlues',
       'FamilyOtherBlues',
       'StemSnapH',
       'StemSnapV',
       'BlueShift',
       'BlueFuzz',
       'BlueScale',
       'LanguageGroup',
-      'ExpansionFactor'
+      'ExpansionFactor',
+      'ForceBold',
+      'StdHW',
+      'StdVW'
     ];
     for (var i = 0, ii = fields.length; i < ii; i++) {
       var field = fields[i];
       if (!properties.privateData.hasOwnProperty(field))
         continue;
       privateDict.setByName(field, properties.privateData[field]);
     }
     cff.topDict.privateDict = privateDict;
@@ -20628,25 +20823,25 @@ var CFFParser = (function CFFParserClosu
 
       cff.isCIDFont = topDict.hasName('ROS');
 
       var charStringOffset = topDict.getByName('CharStrings');
       cff.charStrings = this.parseCharStrings(charStringOffset);
 
       var fontMatrix = topDict.getByName('FontMatrix');
       if (fontMatrix) {
-        // estimating unitsPerEM for the font
-        properties.unitsPerEm = 1 / fontMatrix[0];
+        properties.fontMatrix = fontMatrix;
       }
 
       var fontBBox = topDict.getByName('FontBBox');
       if (fontBBox) {
         // adjusting ascent/descent
         properties.ascent = fontBBox[3];
         properties.descent = fontBBox[1];
+        properties.ascentScaled = true;
       }
 
       var charset, encoding;
       if (cff.isCIDFont) {
         var fdArrayIndex = this.parseIndex(topDict.getByName('FDArray')).obj;
         for (var i = 0, ii = fdArrayIndex.count; i < ii; ++i) {
           var dictRaw = fdArrayIndex.get(i);
           var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw),
@@ -20676,17 +20871,24 @@ var CFFParser = (function CFFParserClosu
       // DirectWrite does not like CID fonts data. Trying to convert/flatten
       // the font data and remove CID properties.
       if (cff.fdArray.length !== 1) {
         warn('Unable to normalize CID font in CFF data -- using font as is');
         return cff;
       }
 
       var fontDict = cff.fdArray[0];
+      // Make the sanitizer happy and remove anything that is only for CID
+      // fonts.
       fontDict.setByKey(17, topDict.getByName('CharStrings'));
+      fontDict.removeByName('CIDFontVersion');
+      fontDict.removeByName('CIDFontRevision');
+      fontDict.removeByName('CIDFontType');
+      fontDict.removeByName('CIDCount');
+      fontDict.removeByName('UIDBase');
       cff.topDict = fontDict;
       cff.isCIDFont = false;
       delete cff.fdArray;
       delete cff.fdSelect;
 
       return cff;
     },
     parseHeader: function CFFParser_parseHeader() {
@@ -21547,47 +21749,36 @@ var CFFCompiler = (function CFFCompilerC
       return output.data;
     },
     encodeNumber: function CFFCompiler_encodeNumber(value) {
       if (parseFloat(value) == parseInt(value) && !isNaN(value)) // isInt
         return this.encodeInteger(value);
       else
         return this.encodeFloat(value);
     },
-    encodeFloat: function CFFCompiler_encodeFloat(value) {
-      value = value.toString();
-      // Strip off the any leading zeros.
-      if (value.substr(0, 2) === '0.')
-        value = value.substr(1);
-      else if (value.substr(0, 3) === '-0.')
-        value = '-' + value.substr(2);
-      var nibbles = [];
+    encodeFloat: function CFFCompiler_encodeFloat(num) {
+      var value = num.toString();
+      var nibbles = '';
       for (var i = 0, ii = value.length; i < ii; ++i) {
-        var a = value.charAt(i), b = value.charAt(i + 1);
-        var nibble;
-        if (a === 'e' && b === '-') {
-          nibble = 0xc;
-          ++i;
+        var a = value[i];
+        if (a === 'e') {
+          nibbles += value[++i] === '-' ? 'c' : 'b';
         } else if (a === '.') {
-          nibble = 0xa;
-        } else if (a === 'E') {
-          nibble = 0xb;
+          nibbles += 'a';
         } else if (a === '-') {
-          nibble = 0xe;
-        } else {
-          nibble = a;
-        }
-        nibbles.push(nibble);
-      }
-      nibbles.push(0xf);
-      if (nibbles.length % 2)
-        nibbles.push(0xf);
+          nibbles += 'e';
+        } else {
+          nibbles += a;
+        }
+      }
+      nibbles += (nibbles.length & 1) ? 'f' : 'ff';
       var out = [30];
-      for (var i = 0, ii = nibbles.length; i < ii; i += 2)
-        out.push(nibbles[i] << 4 | nibbles[i + 1]);
+      for (var i = 0, ii = nibbles.length; i < ii; i += 2) {
+        out.push(parseInt(nibbles.substr(i, 2), 16));
+      }
       return out;
     },
     encodeInteger: function CFFCompiler_encodeInteger(value) {
       var code;
       if (value >= -107 && value <= 107) {
         code = [value + 139];
       } else if (value >= 108 && value <= 1131) {
         value = [value - 108];
@@ -29855,38 +30046,44 @@ var Lexer = (function LexerClosure() {
       if (str.length > 128)
         error('Warning: name token is longer than allowed by the spec: ' +
               str.length);
       return new Name(str);
     },
     getHexString: function Lexer_getHexString(ch) {
       var str = '';
       var stream = this.stream;
-      for (;;) {
+      var isFirstHex = true;
+      var firstDigit;
+      var secondDigit;
+      while (true) {
         ch = stream.getChar();
-        if (ch == '>') {
-          break;
-        }
         if (!ch) {
           warn('Unterminated hex string');
           break;
-        }
-        if (specialChars[ch.charCodeAt(0)] != 1) {
-          var x, x2;
-          if ((x = toHexDigit(ch)) == -1)
-            error('Illegal character in hex string: ' + ch);
-
-          ch = stream.getChar();
-          while (specialChars[ch.charCodeAt(0)] == 1)
-            ch = stream.getChar();
-
-          if ((x2 = toHexDigit(ch)) == -1)
-            error('Illegal character in hex string: ' + ch);
-
-          str += String.fromCharCode((x << 4) | x2);
+        } else if (ch === '>') {
+          break;
+        } else if (specialChars[ch.charCodeAt(0)] === 1) {
+          continue;
+        } else {
+          if (isFirstHex) {
+            firstDigit = toHexDigit(ch);
+            if (firstDigit === -1) {
+              warn("Ignoring invalid character '" + ch + "' in hex string");
+              continue;
+            }
+          } else {
+            secondDigit = toHexDigit(ch);
+            if (secondDigit === -1) {
+              warn("Ignoring invalid character '" + ch + "' in hex string");
+              continue;
+            }
+            str += String.fromCharCode((firstDigit << 4) | secondDigit);
+          }
+          isFirstHex = !isFirstHex;
         }
       }
       return str;
     },
     getObj: function Lexer_getObj() {
       // skip whitespace and comments
       var comment = false;
       var stream = this.stream;
@@ -32902,17 +33099,29 @@ var WorkerMessageHandler = {
         info: pdfModel.getDocumentInfo(),
         metadata: pdfModel.catalog.metadata,
         encrypted: !!pdfModel.xref.encrypt
       };
       handler.send('GetDoc', {pdfInfo: doc});
     }
 
     handler.on('test', function wphSetupTest(data) {
-      handler.send('test', data instanceof Uint8Array);
+      // check if Uint8Array can be sent to worker
+      if (!(data instanceof Uint8Array)) {
+        handler.send('test', false);
+        return;
+      }
+      // check if the response property is supported by xhr
+      var xhr = new XMLHttpRequest();
+      if (!('response' in xhr || 'mozResponse' in xhr ||
+          'responseArrayBuffer' in xhr || 'mozResponseArrayBuffer' in xhr)) {
+        handler.send('test', false);
+        return;
+      }
+      handler.send('test', true);
     });
 
     handler.on('GetDocRequest', function wphSetupDoc(data) {
       var source = data.source;
       if (source.data) {
         // the data is array, instantiating directly from it
         loadDocument(source.data, source);
         return;
@@ -35845,16 +36054,18 @@ var Jbig2Image = (function Jbig2ImageClo
         pageInfo.lossless = !!(pageSegmentFlags & 1);
         pageInfo.refinement = !!(pageSegmentFlags & 2);
         pageInfo.defaultPixelValue = (pageSegmentFlags >> 2) & 1;
         pageInfo.combinationOperator = (pageSegmentFlags >> 3) & 3;
         pageInfo.requiresBuffer = !!(pageSegmentFlags & 32);
         pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64);
         args = [pageInfo];
         break;
+      case 49: // EndOfPage
+        break;
       case 50: // EndOfStripe
         break;
       case 51: // EndOfFile
         break;
       default:
         error('JBIG2 error: segment type ' + header.typeName + '(' +
               header.type + ') is not implemented');
     }
--- a/browser/extensions/pdfjs/content/web/viewer.css
+++ b/browser/extensions/pdfjs/content/web/viewer.css
@@ -962,34 +962,45 @@ a:focus > .thumbnail > .thumbnailSelecti
   top: 0;
   bottom: 0;
   padding: 4px 4px 0;
   overflow: auto;
   -webkit-user-select:none;
   -moz-user-select:none;
 }
 
-.outlineItem > .outlineItems {
+html[dir='ltr'] .outlineItem > .outlineItems {
   margin-left: 20px;
 }
 
+html[dir='rtl'] .outlineItem > .outlineItems {
+  margin-right: 20px;
+}
+
 .outlineItem > a {
   text-decoration: none;
   display: inline-block;
   min-width: 95%;
-  height: 20px;
-  padding: 2px 0 0 10px;
+  height: auto;
   margin-bottom: 1px;
   border-radius: 2px;
   color: hsla(0,0%,100%,.8);
   font-size: 13px;
   line-height: 15px;
   -moz-user-select:none;
   cursor: default;
-  white-space: nowrap;
+  white-space: normal;
+}
+
+html[dir='ltr'] .outlineItem > a {
+  padding: 2px 0 5px 10px;
+}
+
+html[dir='rtl'] .outlineItem > a {
+  padding: 2px 10px 5px 0;
 }
 
 .outlineItem > a:hover {
   background-color: hsla(0,0%,100%,.02);
   background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
   background-clip: padding-box;
   box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
               0 0 1px hsla(0,0%,100%,.2) inset,
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -746,16 +746,17 @@ var PDFView = {
   pageViewScroll: null,
   thumbnailViewScroll: null,
   isFullscreen: false,
   previousScale: null,
   pageRotation: 0,
   mouseScrollTimeStamp: 0,
   mouseScrollDelta: 0,
   lastScroll: 0,
+  previousPageNumber: 1,
 
   // called once when the document is loaded
   initialize: function pdfViewInitialize() {
     var self = this;
     var container = this.container = document.getElementById('viewerContainer');
     this.pageViewScroll = {};
     this.watchScroll(container, this.pageViewScroll, updateViewarea);
 
@@ -868,22 +869,24 @@ var PDFView = {
 
   set page(val) {
     var pages = this.pages;
     var input = document.getElementById('pageNumber');
     var event = document.createEvent('UIEvents');
     event.initUIEvent('pagechange', false, false, window, 0);
 
     if (!(0 < val && val <= pages.length)) {
+      this.previousPageNumber = val;
       event.pageNumber = this.page;
       window.dispatchEvent(event);
       return;
     }
 
     pages[val - 1].updateStats();
+    this.previousPageNumber = currentPageNumber;
     currentPageNumber = val;
     event.pageNumber = val;
     window.dispatchEvent(event);
 
     // checking if the this.page was called from the updateViewarea function:
     // avoiding the creation of two "set page" method (internal and public)
     if (updateViewarea.inProgress)
       return;
@@ -1164,18 +1167,19 @@ var PDFView = {
   /**
    * Show the error box.
    * @param {String} message A message that is human readable.
    * @param {Object} moreInfo (optional) Further information about the error
    *                            that is more technical.  Should have a 'message'
    *                            and optionally a 'stack' property.
    */
   error: function pdfViewError(message, moreInfo) {
-    var moreInfoText = mozL10n.get('error_build', {build: PDFJS.build},
-      'PDF.JS Build: {{build}}') + '\n';
+    var moreInfoText = mozL10n.get('error_version_info',
+      {version: PDFJS.version || '?', build: PDFJS.build || '?'},
+      'PDF.js v{{version}} (build: {{build}})') + '\n';
     if (moreInfo) {
       moreInfoText +=
         mozL10n.get('error_message', {message: moreInfo.message},
         'Message: {{message}}');
       if (moreInfo.stack) {
         moreInfoText += '\n' +
           mozL10n.get('error_stack', {stack: moreInfo.stack},
           'Stack: {{stack}}');
@@ -1303,17 +1307,18 @@ var PDFView = {
     pdfDocument.getMetadata().then(function(data) {
       var info = data.info, metadata = data.metadata;
       self.documentInfo = info;
       self.metadata = metadata;
 
       // Provides some basic debug information
       console.log('PDF ' + pdfDocument.fingerprint + ' [' +
                   info.PDFFormatVersion + ' ' + (info.Producer || '-') +
-                  ' / ' + (info.Creator || '-') + ']');
+                  ' / ' + (info.Creator || '-') + ']' +
+                  (PDFJS.version ? ' (PDF.js: ' + PDFJS.version + ')' : ''));
 
       var pdfTitle;
       if (metadata) {
         if (metadata.has('dc:title'))
           pdfTitle = metadata.get('dc:title');
       }
 
       if (!pdfTitle && info && info['Title'])
@@ -1471,22 +1476,31 @@ var PDFView = {
     var thumbsView = document.getElementById('thumbnailView');
     var outlineView = document.getElementById('outlineView');
 
     var thumbsButton = document.getElementById('viewThumbnail');
     var outlineButton = document.getElementById('viewOutline');
 
     switch (view) {
       case 'thumbs':
+        var wasOutlineViewVisible = thumbsView.classList.contains('hidden');
+
         thumbsButton.classList.add('toggled');
         outlineButton.classList.remove('toggled');
         thumbsView.classList.remove('hidden');
         outlineView.classList.add('hidden');
 
         PDFView.renderHighestPriority();
+
+        if (wasOutlineViewVisible) {
+          // Ensure that the thumbnail of the current page is visible
+          // when switching from the outline view.
+          scrollIntoView(document.getElementById('thumbnailContainer' +
+                                                 this.page));
+        }
         break;
 
       case 'outline':
         thumbsButton.classList.remove('toggled');
         outlineButton.classList.add('toggled');
         thumbsView.classList.add('hidden');
         outlineView.classList.remove('hidden');
 
@@ -2203,16 +2217,22 @@ var ThumbnailView = function thumbnailVi
   var canvasHeight = canvasWidth / this.width * this.height;
   var scaleX = this.scaleX = (canvasWidth / pageWidth);
   var scaleY = this.scaleY = (canvasHeight / pageHeight);
 
   var div = this.el = document.createElement('div');
   div.id = 'thumbnailContainer' + id;
   div.className = 'thumbnail';
 
+  if (id === 1) {
+    // Highlight the thumbnail of the first page when no page number is
+    // specified (or exists in cache) when the document is loaded.
+    div.classList.add('selected');
+  }
+
   var ring = document.createElement('div');
   ring.className = 'thumbnailSelectionRing';
   ring.style.width = canvasWidth + 'px';
   ring.style.height = canvasHeight + 'px';
 
   div.appendChild(ring);
   anchor.appendChild(div);
   container.appendChild(anchor);
@@ -3039,17 +3059,17 @@ window.addEventListener('scalechange', f
     customScaleOption.selected = true;
   }
 
   updateViewarea();
 }, true);
 
 window.addEventListener('pagechange', function pagechange(evt) {
   var page = evt.pageNumber;
-  if (document.getElementById('pageNumber').value != page) {
+  if (PDFView.previousPageNumber !== page) {
     document.getElementById('pageNumber').value = page;
     var selected = document.querySelector('.thumbnail.selected');
     if (selected)
       selected.classList.remove('selected');
     var thumbnail = document.getElementById('thumbnailContainer' + page);
     thumbnail.classList.add('selected');
     var visibleThumbs = PDFView.getVisibleThumbs();
     var numVisibleThumbs = visibleThumbs.views.length;
@@ -3167,34 +3187,34 @@ window.addEventListener('keydown', funct
     curElement = curElement.parentNode;
   }
 
   if (cmd == 0) { // no control key pressed at all.
     switch (evt.keyCode) {
       case 38: // up arrow
       case 33: // pg up
       case 8: // backspace
-        if (!PDFView.isFullscreen) {
+        if (!PDFView.isFullscreen && PDFView.currentScaleValue !== 'page-fit') {
           break;
         }
         //  in fullscreen mode falls throw here
       case 37: // left arrow
         // horizontal scrolling using arrow keys
         if (PDFView.isHorizontalScrollbarEnabled) {
           break;
         }
       case 75: // 'k'
       case 80: // 'p'
         PDFView.page--;
         handled = true;
         break;
       case 40: // down arrow
       case 34: // pg down
       case 32: // spacebar
-        if (!PDFView.isFullscreen) {
+        if (!PDFView.isFullscreen && PDFView.currentScaleValue !== 'page-fit') {
           break;
         }
         //  in fullscreen mode falls throw here
       case 39: // right arrow
         // horizontal scrolling using arrow keys
         if (PDFView.isHorizontalScrollbarEnabled) {
           break;
         }
--- a/browser/installer/Makefile.in
+++ b/browser/installer/Makefile.in
@@ -55,21 +55,17 @@ endif
 ifdef NSS_DISABLE_DBM
 DEFINES += -DNSS_DISABLE_DBM=1
 endif
 
 ifdef _MSC_VER
 DEFINES += -D_MSC_VER=$(_MSC_VER)
 endif
 
-ifeq ($(MOZ_CHROME_FILE_FORMAT),jar)
-DEFINES += -DJAREXT=.jar
-else
 DEFINES += -DJAREXT=
-endif
 
 ifdef MOZ_ANGLE_RENDERER
 DEFINES += -DMOZ_ANGLE_RENDERER=$(MOZ_ANGLE_RENDERER)
 DEFINES += -DMOZ_D3DX9_DLL=$(MOZ_D3DX9_DLL)
 DEFINES += -DMOZ_D3DCOMPILER_DLL=$(MOZ_D3DCOMPILER_DLL)
 endif
 
 include $(topsrcdir)/ipc/app/defs.mk
@@ -147,16 +143,16 @@ endif
 package-compare:: $(MOZ_PKG_MANIFEST)
 ifdef MOZ_PKG_MANIFEST_P
 	cd $(DIST); find $(PKGCOMP_FIND_OPTS) $(FINDPATH) -type f | sort > bin-list.txt
 	grep "^$(BINPATH)" $(MOZ_PKG_MANIFEST) | sed -e 's/^\///' | sort > $(DIST)/pack-list.txt
 	-diff -u $(DIST)/pack-list.txt $(DIST)/bin-list.txt
 	rm -f $(DIST)/pack-list.txt $(DIST)/bin-list.txt
 endif
 
-installer:: removed-files
+installer::
 ifdef INSTALLER_DIR
 	$(MAKE) -C $(INSTALLER_DIR)
 endif
 
 ifdef ENABLE_MARIONETTE
 DEFINES += -DENABLE_MARIONETTE=1
 endif
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -559,17 +559,16 @@
 @BINPATH@/chrome/icons/default/default16.png
 @BINPATH@/chrome/icons/default/default32.png
 @BINPATH@/chrome/icons/default/default48.png
 #endif
 
 ; shell icons
 #ifdef XP_UNIX
 #ifndef XP_MACOSX
-@BINPATH@/icons/*.xpm
 @BINPATH@/icons/*.png
 #endif
 #endif
 
 ; [Default Preferences]
 ; All the pref files must be part of base to prevent migration bugs
 @BINPATH@/@PREF_DIR@/firefox.js
 @BINPATH@/@PREF_DIR@/firefox-branding.js
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -879,21 +879,21 @@ xpicleanup@BIN_SUFFIX@
   chrome/browser.jar
   chrome/localized.manifest
   chrome/nonlocalized.manifest
   chrome/pippki.jar
   chrome/toolkit.jar
   components/addonManager.js
   components/amContentHandler.js
   components/amWebInstallListener.js
+  components/binary.manifest
   components/browser.xpt
   components/BrowserElementParent.js
   components/BrowserElementParent.manifest
   components/BrowserElementPromptService.jsm
-  components/components.manifest
   components/contentAreaDropListener.js
   components/contentSecurityPolicy.js
   components/crypto-SDR.js
   components/FeedConverter.js
   components/FeedProcessor.js
   components/FeedWriter.js
   components/fuelApplication.js
   components/GPSDGeolocationProvider.js
--- a/browser/locales/Makefile.in
+++ b/browser/locales/Makefile.in
@@ -243,10 +243,10 @@ endif
 # test target, depends on make package
 # try to repack x-test, with just toolkit/defines.inc being there
 l10n-check:: INNER_UNMAKE_PACKAGE=true
 l10n-check::
 	$(RM) -rf x-test
 	$(NSINSTALL) -D x-test/toolkit
 	echo "#define MOZ_LANG_TITLE Just testing" > x-test/toolkit/defines.inc
 	$(MAKE) installers-x-test L10NBASEDIR="$(PWD)" LOCALE_MERGEDIR="$(PWD)/mergedir"
-	cd $(DIST)/l10n-stage && $(UNMAKE_PACKAGE)
+	$(PYTHON) $(topsrcdir)/toolkit/mozapps/installer/unpack.py $(DIST)/l10n-stage/$(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)
 	cd $(DIST)/l10n-stage && test $$(cat $(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)/update.locale) = x-test
--- a/browser/locales/en-US/pdfviewer/viewer.properties
+++ b/browser/locales/en-US/pdfviewer/viewer.properties
@@ -81,19 +81,19 @@ find_match_case_label=Match case
 find_reached_top=Reached top of document, continued from bottom
 find_reached_bottom=Reached end of document, continued from top
 find_not_found=Phrase not found
 
 # Error panel labels
 error_more_info=More Information
 error_less_info=Less Information
 error_close=Close
-# LOCALIZATION NOTE (error_build): "{{build}}" will be replaced by the PDF.JS
-# build ID.
-error_build=PDF.JS Build: {{build}}
+# LOCALIZATION NOTE (error_version_info): "{{version}}" and "{{build}}" will be
+# replaced by the PDF.JS version and build ID.
+error_version_info=PDF.js v{{version}} (build: {{build}})
 # LOCALIZATION NOTE (error_message): "{{message}}" will be replaced by an
 # english string describing the error.
 error_message=Message: {{message}}
 # LOCALIZATION NOTE (error_stack): "{{stack}}" will be replaced with a stack
 # trace.
 error_stack=Stack: {{stack}}
 # LOCALIZATION NOTE (error_file): "{{file}}" will be replaced with a filename
 error_file=File: {{file}}
--- a/browser/themes/gnomestripe/aboutSocialError.css
+++ b/browser/themes/gnomestripe/aboutSocialError.css
@@ -65,34 +65,34 @@ button {
   background-clip: padding-box;
   border: 1px solid hsla(210,15%,25%,.4);
   border-color: hsla(210,15%,25%,.3) hsla(210,15%,25%,.35) hsla(210,15%,25%,.4);
   border-radius: 3px;
   box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
               0 0 0 1px hsla(0,0%,100%,.3) inset,
               0 1px 0 hsla(0,0%,100%,.1);
 
-  -moz-transition-property: background-color, border-color, box-shadow;
-  -moz-transition-duration: 150ms;
-  -moz-transition-timing-function: ease;
+  transition-property: background-color, border-color, box-shadow;
+  transition-duration: 150ms;
+  transition-timing-function: ease;
 
 }
 
 button:hover {
   background-color: hsla(210,30%,95%,.8);
   border-color: hsla(210,15%,25%,.45) hsla(210,15%,25%,.5) hsla(210,15%,25%,.55);
   box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
               0 0 0 1px hsla(0,0%,100%,.3) inset,
               0 1px 0 hsla(0,0%,100%,.1),
               0 0 3px hsla(210,15%,25%,.1);
-  -moz-transition-property: background-color, border-color, box-shadow;
-  -moz-transition-duration: 150ms;
-  -moz-transition-timing-function: ease;
+  transition-property: background-color, border-color, box-shadow;
+  transition-duration: 150ms;
+  transition-timing-function: ease;
 }
 
 button:hover:active {
   background-color: hsla(210,15%,25%,.2);
   box-shadow: 0 1px 1px hsla(210,15%,25%,.2) inset,
               0 0 2px hsla(210,15%,25%,.4) inset;
-  -moz-transition-property: background-color, border-color, box-shadow;
-  -moz-transition-duration: 10ms;
-  -moz-transition-timing-function: linear;
+  transition-property: background-color, border-color, box-shadow;
+  transition-duration: 10ms;
+  transition-timing-function: linear;
 }
--- a/browser/themes/gnomestripe/tabview/tabview.css
+++ b/browser/themes/gnomestripe/tabview/tabview.css
@@ -5,17 +5,17 @@
 body {
   font: -moz-window;
   color: WindowText;
   font-size: 12px;
 }
 
 #bg {
   background-color: window;
-  background-image: -moz-linear-gradient(rgba(0,0,0,0.1),rgba(0,0,0,.2));
+  background-image: linear-gradient(rgba(0,0,0,0.1), rgba(0,0,0,0.2));
 }
 
 /* Tabs
 ----------------------------------*/
 
 .tab {
   margin: 4px;
   padding-top: 4px;
@@ -192,17 +192,17 @@ html[dir=rtl] .stack-trayed .tab-title {
 
 /* Tab GroupItem
 ----------------------------------*/
 
 .groupItem {
   cursor: pointer;
   border: 1px solid rgba(230,230,230,1);
   background-color: window;
-  background-image: -moz-linear-gradient(rgba(255,255,255,.3),rgba(255,255,255,.1));
+  background-image: linear-gradient(rgba(255,255,255,0.3), rgba(255,255,255,0.1));
   border-radius: 0.4em;
   box-shadow:
     inset rgba(255, 255, 255, 0.6) 0 0 0 2px,
     rgba(0,0,0,0.2) 1px 1px 3px;
 }
 
 html[dir=rtl] .groupItem {
   box-shadow:
--- a/browser/themes/pinstripe/aboutSocialError.css
+++ b/browser/themes/pinstripe/aboutSocialError.css
@@ -65,34 +65,34 @@ button {
   background-clip: padding-box;
   border: 1px solid hsla(210,15%,25%,.4);
   border-color: hsla(210,15%,25%,.3) hsla(210,15%,25%,.35) hsla(210,15%,25%,.4);
   border-radius: 3px;
   box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
               0 0 0 1px hsla(0,0%,100%,.3) inset,
               0 1px 0 hsla(0,0%,100%,.1);
 
-  -moz-transition-property: background-color, border-color, box-shadow;
-  -moz-transition-duration: 150ms;
-  -moz-transition-timing-function: ease;
+  transition-property: background-color, border-color, box-shadow;
+  transition-duration: 150ms;
+  transition-timing-function: ease;
 
 }
 
 button:hover {
   background-color: hsla(210,30%,95%,.8);
   border-color: hsla(210,15%,25%,.45) hsla(210,15%,25%,.5) hsla(210,15%,25%,.55);
   box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
               0 0 0 1px hsla(0,0%,100%,.3) inset,
               0 1px 0 hsla(0,0%,100%,.1),
               0 0 3px hsla(210,15%,25%,.1);
-  -moz-transition-property: background-color, border-color, box-shadow;
-  -moz-transition-duration: 150ms;
-  -moz-transition-timing-function: ease;
+  transition-property: background-color, border-color, box-shadow;
+  transition-duration: 150ms;
+  transition-timing-function: ease;
 }
 
 button:hover:active {
   background-color: hsla(210,15%,25%,.2);
   box-shadow: 0 1px 1px hsla(210,15%,25%,.2) inset,
               0 0 2px hsla(210,15%,25%,.4) inset;
-  -moz-transition-property: background-color, border-color, box-shadow;
-  -moz-transition-duration: 10ms;
-  -moz-transition-timing-function: linear;
+  transition-property: background-color, border-color, box-shadow;
+  transition-duration: 10ms;
+  transition-timing-function: linear;
 }
--- a/browser/themes/pinstripe/preferences/aboutPermissions.css
+++ b/browser/themes/pinstripe/preferences/aboutPermissions.css
@@ -15,17 +15,17 @@
 #sites-filter {
   margin: 0;
 }
 
 #sites-list {
   -moz-appearance: none;
   border: 1px solid rgba(60,73,97,0.5);
   box-shadow: inset 0 1px 1px rgba(0,0,0,0.15), 0 1px rgba(255,255,255,0.25);
-  background: -moz-linear-gradient(rgba(255,255,255,0.2), rgba(255,255,255,0.3));
+  background: linear-gradient(rgba(255,255,255,0.2), rgba(255,255,255,0.3));
   margin: 5px 0 0 0;
 }
 
 .site {
   padding: 4px;
   border-bottom: 1px solid ThreeDLightShadow;
 }
 
--- a/browser/themes/pinstripe/preferences/in-content/preferences.css
+++ b/browser/themes/pinstripe/preferences/in-content/preferences.css
@@ -146,26 +146,26 @@ description > html|a {
 .header-button {
   -moz-appearance: none;
   padding: 0 4px;
   margin: 0;
   height: 22px;
   border: 1px solid rgba(60,73,97,0.5);
   border-radius: @toolbarbuttonCornerRadius@;
   box-shadow: inset 0 1px rgba(255,255,255,0.25), 0 1px rgba(255,255,255,0.25);
-  background: -moz-linear-gradient(rgba(255,255,255,0.45), rgba(255,255,255,0));
+  background: linear-gradient(rgba(255,255,255,0.45), rgba(255,255,255,0));
   background-clip: padding-box;
 }
 
 .header-button .toolbarbutton-text {
   display: none;
 }
 
 .header-button[disabled="true"] .toolbarbutton-icon {
   opacity: 0.4;
 }
 
 .header-button:not([disabled="true"]):active:hover,
 .header-button[open="true"] {
   border-color: rgba(45,54,71,0.7);
   box-shadow: inset 0 0 4px rgb(45,54,71), 0 1px rgba(255,255,255,0.25);
-  background-image: -moz-linear-gradient(rgba(45,54,71,0.6), rgba(45,54,71,0));
+  background-image: linear-gradient(rgba(45,54,71,0.6), rgba(45,54,71,0));
 }
--- a/browser/themes/pinstripe/tabview/tabview.css
+++ b/browser/themes/pinstripe/tabview/tabview.css
@@ -5,21 +5,21 @@
 body {
   background-color: transparent;  
   font: message-box;
   color: rgba(0, 0, 0, 0.6);
   font-size: 12px;
 }
 
 #bg {
-  background: -moz-linear-gradient(#C4C4C4,#9E9E9E);
+  background: linear-gradient(#C4C4C4, #9E9E9E);
 }
 
 #bg:-moz-window-inactive {
-  background: -moz-linear-gradient(rgb(237,237,237),rgb(216,216,216));
+  background: linear-gradient(#EDEDED, #D8D8D8);
 }
 
 /* Tabs
 ----------------------------------*/
 
 .tab {
   margin: 8px;
   padding-top: 4px;
@@ -536,17 +536,17 @@ html[dir=rtl] .iq-resizable-se {
 ----------------------------------*/
 #searchshade{
   background-color: rgba(0,0,0,.42);
   width: 100%;
   height: 100%;
 }
 
 #searchshade:-moz-window-inactive {
-  background: -moz-linear-gradient(rgba(237,237,237,.42),rgba(216,216,216,.42));
+  background: linear-gradient(rgba(237,237,237,0.42), rgba(216,216,216,0.42));
 }
 
 #search{
   width: 100%;
   height: 100%;
 }
 
 #searchbox {
--- a/browser/themes/winstripe/aboutSocialError.css
+++ b/browser/themes/winstripe/aboutSocialError.css
@@ -65,34 +65,34 @@ button {
   background-clip: padding-box;
   border: 1px solid hsla(210,15%,25%,.4);
   border-color: hsla(210,15%,25%,.3) hsla(210,15%,25%,.35) hsla(210,15%,25%,.4);
   border-radius: 3px;
   box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
               0 0 0 1px hsla(0,0%,100%,.3) inset,
               0 1px 0 hsla(0,0%,100%,.1);
 
-  -moz-transition-property: background-color, border-color, box-shadow;
-  -moz-transition-duration: 150ms;
-  -moz-transition-timing-function: ease;
+  transition-property: background-color, border-color, box-shadow;
+  transition-duration: 150ms;
+  transition-timing-function: ease;
 
 }
 
 button:hover {
   background-color: hsla(210,30%,95%,.8);
   border-color: hsla(210,15%,25%,.45) hsla(210,15%,25%,.5) hsla(210,15%,25%,.55);
   box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
               0 0 0 1px hsla(0,0%,100%,.3) inset,
               0 1px 0 hsla(0,0%,100%,.1),
               0 0 3px hsla(210,15%,25%,.1);
-  -moz-transition-property: background-color, border-color, box-shadow;
-  -moz-transition-duration: 150ms;
-  -moz-transition-timing-function: ease;
+  transition-property: background-color, border-color, box-shadow;
+  transition-duration: 150ms;
+  transition-timing-function: ease;
 }
 
 button:hover:active {
   background-color: hsla(210,15%,25%,.2);
   box-shadow: 0 1px 1px hsla(210,15%,25%,.2) inset,
               0 0 2px hsla(210,15%,25%,.4) inset;
-  -moz-transition-property: background-color, border-color, box-shadow;
-  -moz-transition-duration: 10ms;
-  -moz-transition-timing-function: linear;
+  transition-property: background-color, border-color, box-shadow;
+  transition-duration: 10ms;
+  transition-timing-function: linear;
 }
--- a/browser/themes/winstripe/preferences/in-content/preferences.css
+++ b/browser/themes/winstripe/preferences/in-content/preferences.css
@@ -148,19 +148,21 @@ description > html|a {
   opacity: 0.8;
 }
 
 .header-button {
   -moz-appearance: none;
   padding: 1px 3px;
   color: #444;
   text-shadow: 0 0 3px white;
-  background: -moz-linear-gradient(
-                    rgba(251,252,253,0.95), rgba(246,247,248,0) 49%,
-                    rgba(211,212,213,0.45) 51%, rgba(225,226,229, 0.3));
+  background: linear-gradient(
+                rgba(251,252,253,0.95),
+                rgba(246,247,248,0) 49%,
+                rgba(211,212,213,0.45) 51%,
+                rgba(225,226,229, 0.3));
   background-clip: padding-box;
   border-radius: 2.5px;
   border: 1px solid rgba(31,64,100,0.4);
   border-top-color: rgba(31,64,100,0.3);
   box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.25) inset,
               0 0 2px 1px rgba(255, 255, 255, 0.25) inset;
 }
 
--- a/browser/themes/winstripe/tabview/tabview.css
+++ b/browser/themes/winstripe/tabview/tabview.css
@@ -5,17 +5,17 @@
 body {
   font: message-box;
   color: rgba(0, 0, 0, 0.6);
   font-size: 13px;
 }
 
 #bg:not(:-moz-system-metric(windows-compositor)) {
   background: url("chrome://browser/skin/tabview/grain.png") repeat scroll center top,
-              -moz-linear-gradient(center top , #CCD9EA, #C7D5E7) repeat scroll 0 0 transparent;
+              linear-gradient(#CCD9EA, #C7D5E7) repeat scroll 0 0;
 }
 
 /* Tabs
 ----------------------------------*/
 
 .tab {
   margin: 4px;
   padding-top: 4px;
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -173,96 +173,16 @@ endif
 
 ifdef ENABLE_TESTS
 libs:: $(topsrcdir)/tools/rb/fix_stack_using_bpsyms.py
 	$(INSTALL) $< $(DIST)/bin
 
 ifeq ($(OS_ARCH),Darwin)
 libs:: $(topsrcdir)/tools/rb/fix_macosx_stack.py
 	$(INSTALL) $< $(DIST)/bin
-
-# Basic unit tests for some stuff in the unify script
-check::
-# build x64/i386 binaries, and unify them
-	rm -f unify-test-x64 unify-test-i386 unify-test-universal
-	$(HOST_CC) -arch x86_64 $(srcdir)/unify-test.c -o unify-test-x64
-	$(HOST_CC) -arch i386 $(srcdir)/unify-test.c -o unify-test-i386
-	@if ! $(srcdir)/macosx/universal/unify ./unify-test-x64 ./unify-test-i386 \
-          ./unify-test-universal; then \
-          echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to produce a universal binary!"; \
-          false; \
-        fi
-	@if test ! -f ./unify-test-universal; then \
-          echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to produce a universal binary!"; \
-          false; \
-        fi
-	@if ! file -b ./unify-test-universal | head -n1 | grep -q "^Mach-O universal binary"; then \
-          echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to produce a universal binary!"; \
-          false; \
-        else \
-          echo "TEST-PASS | build/ | unify produced a universal binary!"; \
-        fi
-# try building an x86-64 binary. if that succeeds, try unifying it
-# with an i386 binary
-	rm -f unify-test-x86_64 unify-test-universal-64
-	-$(HOST_CC) -arch x86_64 $(srcdir)/unify-test.c -o unify-test-x86_64
-	@if test -f ./unify-test-x86_64; then \
-          if ! $(srcdir)/macosx/universal/unify ./unify-test-x86_64 ./unify-test-i386 \
-            ./unify-test-universal-64; then \
-            echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to produce a universal binary with a 64-bit input!"; \
-            false; \
-          fi; \
-          if test ! -f ./unify-test-universal-64; then \
-            echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to produce a universal binary with a 64-bit input!"; \
-            false; \
-          fi; \
-          if ! file -b ./unify-test-universal-64 | head -n1 | grep -q "^Mach-O universal binary"; then \
-            echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to produce a universal binary with a 64-bit input!"; \
-            false; \
-          else \
-            echo "TEST-PASS | build/ | unify produced a universal binary with a 64-bit input!"; \
-          fi \
-        fi
-# try unifying two identical Java class files
-	rm -f unifytesta.class unifytestb.class unifytestc.class
-	cp $(srcdir)/unifytest.class ./unifytesta.class
-	cp $(srcdir)/unifytest.class ./unifytestb.class
-	@if ! $(srcdir)/macosx/universal/unify ./unifytesta.class ./unifytestb.class \
-          ./unifytestc.class; then \
-          echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to unify a Java class file!"; \
-          false; \
-        fi
-	@if test ! -f ./unifytestc.class; then \
-          echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to unify a Java class file!"; \
-          false; \
-        fi
-	@if ! diff -q ./unifytesta.class ./unifytestc.class; then \
-          echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to unify a Java class file!"; \
-          false; \
-        else \
-          echo "TEST-PASS | build/ | unify unified a Java class file!"; \
-        fi
-# try unifying some files that differ only in line ordering
-	rm -rf unify-sort-test
-	mkdir unify-sort-test unify-sort-test/a unify-sort-test/b
-	printf "lmn\nabc\nxyz\n" > unify-sort-test/a/file.foo
-	printf "xyz\nlmn\nabc" > unify-sort-test/b/file.foo
-	printf "lmn\nabc\nxyz\n" > unify-sort-test/expected-result
-	@if ! $(srcdir)/macosx/universal/unify --unify-with-sort "\.foo$$" \
-          ./unify-sort-test/a ./unify-sort-test/b \
-          ./unify-sort-test/c; then \
-          echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to unify files with differing line ordering!"; \
-          false; \
-        fi
-	@if ! diff -q ./unify-sort-test/expected-result ./unify-sort-test/c/file.foo; then \
-          echo "TEST-UNEXPECTED-FAIL | build/ | unify failed to unify files with differing line ordering!"; \
-          false; \
-        else \
-          echo "TEST-PASS | build/ | unify unified files with differing line ordering!"; \
-        fi
 endif
 
 ifeq ($(OS_ARCH),Linux)
 libs:: $(topsrcdir)/tools/rb/fix-linux-stack.pl
 	$(INSTALL) $< $(DIST)/bin
 endif
 
 GARBAGE += $(srcdir)/automationutils.pyc
--- a/build/autoconf/toolchain.m4
+++ b/build/autoconf/toolchain.m4
@@ -12,17 +12,25 @@ CC_VERSION='N/A'
 CXX_VERSION='N/A'
 if test "$GCC" = "yes"; then
     GNU_CC=1
     CC_VERSION=`$CC -v 2>&1 | grep 'gcc version'`
 fi
 if test "$GXX" = "yes"; then
     GNU_CXX=1
     CXX_VERSION=`$CXX -v 2>&1 | grep 'gcc version'`
+    changequote(,)
+    GCC_VERSION_FULL=`echo "$CXX_VERSION" | $PERL -pe 's/^.*gcc version ([^ ]*).*/$1/'`
+    GCC_VERSION=`echo "$GCC_VERSION_FULL" | $PERL -pe '(split(/\./))[0]>=4&&s/(^\d*\.\d*).*/$1/;'`
+    changequote([,])
+
+    GCC_MAJOR_VERSION=`echo ${GCC_VERSION} | $AWK -F\. '{ print $1 }'`
+    GCC_MINOR_VERSION=`echo ${GCC_VERSION} | $AWK -F\. '{ print $2 }'`
 fi
+
 if test "`echo | $AS -o conftest.out -v 2>&1 | grep -c GNU`" != "0"; then
     GNU_AS=1
 fi
 rm -f conftest.out
 if test "`echo | $LD -v 2>&1 | grep -c GNU`" != "0"; then
     GNU_LD=1
 fi
 if test "$GNU_CC"; then
--- a/build/automation-build.mk
+++ b/build/automation-build.mk
@@ -55,13 +55,19 @@ AUTOMATION_PPARGS += -DIS_DEBUG_BUILD=0
 endif
 
 ifdef MOZ_CRASHREPORTER
 AUTOMATION_PPARGS += -DCRASHREPORTER=1
 else
 AUTOMATION_PPARGS += -DCRASHREPORTER=0
 endif
 
+ifdef MOZ_ASAN
+AUTOMATION_PPARGS += -DIS_ASAN=1
+else
+AUTOMATION_PPARGS += -DIS_ASAN=0
+endif
+
 automation.py: $(MOZILLA_DIR)/build/automation.py.in $(MOZILLA_DIR)/build/automation-build.mk
 	$(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \
 	$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
 
 GARBAGE += automation.py automation.pyc
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -48,16 +48,17 @@ import automationutils
 #expand _BIN_SUFFIX = __BIN_SUFFIX__
 #expand _PERL = __PERL__
 
 #expand _DEFAULT_APP = "./" + __BROWSER_PATH__
 #expand _CERTS_SRC_DIR = __CERTS_SRC_DIR__
 #expand _IS_TEST_BUILD = __IS_TEST_BUILD__
 #expand _IS_DEBUG_BUILD = __IS_DEBUG_BUILD__
 #expand _CRASHREPORTER = __CRASHREPORTER__ == 1
+#expand _IS_ASAN = __IS_ASAN__ == 1
 
 
 if _IS_WIN32:
   import ctypes, ctypes.wintypes, time, msvcrt
 else:
   import errno
 
 
@@ -116,16 +117,17 @@ class Automation(object):
 
   UNIXISH = not IS_WIN32 and not IS_MAC
 
   DEFAULT_APP = _DEFAULT_APP
   CERTS_SRC_DIR = _CERTS_SRC_DIR
   IS_TEST_BUILD = _IS_TEST_BUILD
   IS_DEBUG_BUILD = _IS_DEBUG_BUILD
   CRASHREPORTER = _CRASHREPORTER
+  IS_ASAN = _IS_ASAN
 
   # timeout, in seconds
   DEFAULT_TIMEOUT = 60.0
   DEFAULT_WEB_SERVER = _DEFAULT_WEB_SERVER
   DEFAULT_HTTP_PORT = _DEFAULT_HTTP_PORT
   DEFAULT_SSL_PORT = _DEFAULT_SSL_PORT
   DEFAULT_WEBSOCKET_PORT = _DEFAULT_WEBSOCKET_PORT
 
@@ -521,16 +523,19 @@ user_pref("plugins.update.url", "http://
 // Make enablePrivilege continue to work for test code. :-(
 user_pref("security.turn_off_all_security_so_that_viruses_can_take_over_this_computer", true);
 
 // Get network events.
 user_pref("network.activity.blipIntervalMilliseconds", 250);
 
 // Don't allow the Data Reporting service to prompt for policy acceptance.
 user_pref("datareporting.policy.dataSubmissionPolicyBypassAcceptance", true);
+
+// Make sure CSS error reporting is enabled for tests
+user_pref("layout.css.report_errors", true);
 """ % { "server" : self.webServer + ":" + str(self.httpPort) }
     prefs.append(part)
 
     if useServerLocations:
       # We need to proxy every server but the primary one.
       origins = ["'%s://%s:%s'" % (l.scheme, l.host, l.port)
                 for l in filter(lambda l: "primary" not in l.options, locations)]
       origins = ", ".join(origins)
@@ -805,16 +810,33 @@ user_pref("camino.use_system_proxy_setti
       env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
       env['MOZ_CRASHREPORTER'] = '1'
     else:
       env['MOZ_CRASHREPORTER_DISABLE'] = '1'
 
     env['GNOME_DISABLE_CRASH_DIALOG'] = '1'
     env['XRE_NO_WINDOWS_CRASH_DIALOG'] = '1'
     env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1'
+
+    # ASan specific environment stuff
+    if self.IS_ASAN and (self.IS_LINUX or self.IS_MAC):
+      try:
+        totalMemory = int(os.popen("free").readlines()[1].split()[1])
+
+        # Only 2 GB RAM or less available? Use custom ASan options to reduce
+        # the amount of resources required to do the tests. Standard options 
+        # will otherwise lead to OOM conditions on the current test slaves.
+        if totalMemory <= 1024 * 1024 * 2:
+          self.log.info("INFO | automation.py | ASan running in low-memory configuration")
+          env["ASAN_OPTIONS"] = "quarantine_size=50331648:redzone=64"
+      except OSError,err:
+        self.log.info("Failed determine available memory, disabling ASan low-memory configuration: %s", err.strerror)
+      except:
+        self.log.info("Failed determine available memory, disabling ASan low-memory configuration")
+
     return env
 
   if IS_WIN32:
     PeekNamedPipe = ctypes.windll.kernel32.PeekNamedPipe
     GetLastError = ctypes.windll.kernel32.GetLastError
 
     def readWithTimeout(self, f, timeout):
       """Try to read a line of output from the file object |f|.
--- a/build/buildconfig.py
+++ b/build/buildconfig.py
@@ -11,17 +11,20 @@ while not os.path.exists(os.path.join(pa
     parent = os.path.normpath(os.path.join(path, os.pardir))
     if parent == path:
         raise Exception("Can't find config.status")
     path = parent
 
 path = os.path.join(path, 'config.status')
 config = imp.load_module('_buildconfig', open(path), path, ('', 'r', imp.PY_SOURCE))
 
-for var in os.environ:
-    if var in config.substs:
-        config.substs[var] = os.environ[var]
-
+# Copy values from the config.status namespace into this module namespace.
+# This effectively imports topsrcdir, topobjdir, defines, substs, files,
+# headers and non_global_defines
 for var in config.__all__:
     value = getattr(config, var)
     if isinstance(value, list) and value and isinstance(value[0], tuple):
         value = dict(value)
     setattr(sys.modules[__name__], var, value)
+
+for var in os.environ:
+    if var != 'SHELL' and var in substs:
+        substs[var] = os.environ[var]
deleted file mode 100755
--- a/build/macosx/universal/fix-buildconfig
+++ /dev/null
@@ -1,144 +0,0 @@
-#!/usr/bin/perl
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-use strict;
-use warnings;
-
-use Archive::Zip(':ERROR_CODES');
-
-my ($BUILDCONFIG);
-
-sub fixBuildconfig($$$);
-
-$BUILDCONFIG = 'content/global/buildconfig.html';
-
-if (scalar(@ARGV) != 3) {
-  print STDERR ("usage: fix-buildconfig <jar|file> <file1> <file2>\n");
-  exit(1);
-}
-
-if (!fixBuildconfig($ARGV[0], $ARGV[1], $ARGV[2])) {
-  exit(1);
-}
-
-exit(0);
-
-sub fixBuildconfig($$$) {
-  my ($mode, $path1, $path2);
-  ($mode, $path1, $path2) = @_;
-
-  if ($mode ne 'jar' && $mode ne 'file') {
-    print STDERR ($0.': must specify jar or file\n');
-    return 0;
-  }
-
-  my ($contents1, $contents2);
-  my ($ze, $zip1, $zip2);
-
-  if ($mode eq 'jar') {
-    $zip1 = Archive::Zip->new();
-    if (($ze = $zip1->read($path1)) != AZ_OK) {
-      print STDERR ($0.': could not read "'.$path1.'": error '.$ze."\n");
-      return 0;
-    }
-    $zip2 = Archive::Zip->new();
-    if (($ze = $zip2->read($path2)) != AZ_OK) {
-      print STDERR ($0.': could not read "'.$path2.'": error '.$ze."\n");
-      return 0;
-    }
-
-    $contents1 = $zip1->contents($BUILDCONFIG);
-    $contents2 = $zip2->contents($BUILDCONFIG);
-  } elsif ($mode eq 'file') {
-    local($/);
-    my ($file1, $file2);
-
-    open($file1, '<'.$path1.$BUILDCONFIG) or return 0;
-    open($file2, '<'.$path2.$BUILDCONFIG) or return 0;
-
-    $contents1 = <$file1>;
-    $contents2 = <$file2>;
-
-    close($file1);
-    close($file2);
-  }
-
-  if (!defined($contents1)) {
-    print STDERR ($0.': could not get "'.$BUILDCONFIG.'" from "'.$path1.'"'.
-                  "\n");
-    return 0;
-  }
-  if (!defined($contents2)) {
-    print STDERR ($0.': could not get "'.$BUILDCONFIG.'" from "'.$path2.'"'.
-                  "\n");
-    return 0;
-  }
-
-  my (@lines1, @lines2);
-  @lines1 = split(/\n/, $contents1);
-  @lines2 = split(/\n/, $contents2);
-
-  my ($line, @linesNew);
-  @linesNew = ();
-
-  # Copy everything from the first file up to the end of its <body>.
-  while ($line = shift(@lines1)) {
-    if ($line eq '</body>') {
-      last;
-    }
-    push(@linesNew, $line);
-  }
-
-  # Insert a <hr> between the two files.
-  push (@linesNew, '<hr> </hr>');
-
-  # Copy the second file's content beginning after its leading <h1>.
-  while ($line = shift(@lines2)) {
-    if ($line eq '<h1>about:buildconfig</h1>') {
-      last;
-    }
-  }
-  while ($line = shift(@lines2)) {
-    push(@linesNew, $line);
-  }
-
-  my ($contentsNew);
-  $contentsNew = join("\n", @linesNew);
-
-  if ($mode eq 'jar') {
-    if (!defined($zip1->contents($BUILDCONFIG, $contentsNew))) {
-      print STDERR ($0.': could not set "'.$BUILDCONFIG.'" to "'.$path1.'"'.
-                    "\n");
-      return 0;
-    }
-    if (!defined($zip2->contents($BUILDCONFIG, $contentsNew))) {
-      print STDERR ($0.': could not set "'.$BUILDCONFIG.'" to "'.$path2.'"'.
-                    "\n");
-      return 0;
-    }
-
-    if (($ze = $zip1->overwrite()) != AZ_OK) {
-      print STDERR ($0.': could not write "'.$path1.'": error '.$ze."\n");
-      return 0;
-    }
-    if (($ze = $zip2->overwrite()) != AZ_OK) {
-      print STDERR ($0.': could not write "'.$path2.'": error '.$ze."\n");
-      return 0;
-    }
-  } elsif ($mode eq 'file') {
-    my ($file1, $file2);
-
-    open($file1, '>'.$path1.$BUILDCONFIG) or return 0;
-    open($file2, '>'.$path2.$BUILDCONFIG) or return 0;
-
-    print $file1 ($contentsNew);
-    print $file2 ($contentsNew);
-
-    close($file1);
-    close($file2);
-  }
-
-  return 1;
-}
--- a/build/macosx/universal/flight.mk
+++ b/build/macosx/universal/flight.mk
@@ -17,79 +17,21 @@ endif
 
 topsrcdir = $(TOPSRCDIR)
 include $(OBJDIR)/config/autoconf.mk
 
 core_abspath = $(if $(filter /%,$(1)),$(1),$(CURDIR)/$(1))
 
 DIST = $(OBJDIR)/dist
 
-ifdef LIBXUL_SDK # {
-APP_CONTENTS = Contents/Frameworks/XUL.framework
-else # } {
-APP_CONTENTS = Contents/MacOS
-endif # } LIBXUL_SDK
-
-ifeq ($(MOZ_BUILD_APP),camino) # {
-INSTALLER_DIR = camino/installer
-MOZ_PKG_APPNAME = camino
-APPNAME = Camino.app
-BUILDCONFIG_BASE = Contents/MacOS/chrome
-else # } {
-MOZ_PKG_APPNAME = $(MOZ_APP_NAME)
-APPNAME = $(MOZ_MACBUNDLE_NAME)
-INSTALLER_DIR = $(MOZ_BUILD_APP)/installer
-ifeq ($(MOZ_BUILD_APP),xulrunner) # {
-APPNAME = XUL.framework
-APP_CONTENTS = Versions/Current
-endif # } xulrunner
-BUILDCONFIG_BASE = $(APP_CONTENTS)/chrome
-endif # } !camino
-
-ifeq ($(MOZ_CHROME_FILE_FORMAT),jar)
-BUILDCONFIG = $(BUILDCONFIG_BASE)/toolkit.jar
-FIX_MODE = jar
-else
-BUILDCONFIG = $(BUILDCONFIG_BASE)/toolkit/
-FIX_MODE = file
-endif
-
 postflight_all:
-# Build the universal package out of only the bits that would be released.
-# Call the packager to set this up.  Set UNIVERSAL_BINARY= to avoid producing
-# a universal binary too early, before the unified bits have been staged.
-# Set SIGN_NSS= to skip shlibsign.
-	$(MAKE) -C $(OBJDIR_ARCH_1)/$(INSTALLER_DIR) \
-          UNIVERSAL_BINARY= SIGN_NSS= PKG_SKIP_STRIP=1 stage-package
-	$(MAKE) -C $(OBJDIR_ARCH_2)/$(INSTALLER_DIR) \
-          UNIVERSAL_BINARY= SIGN_NSS= PKG_SKIP_STRIP=1 stage-package
-# Remove .chk files that may have been copied from the NSS build.  These will
-# cause unify to warn or fail if present.  New .chk files that are
-# appropriate for the merged libraries will be generated when the universal
-# dmg is built.
-	rm -f $(DIST_ARCH_1)/$(MOZ_PKG_APPNAME)/$(APPNAME)/$(APP_CONTENTS)/*.chk \
-	      $(DIST_ARCH_2)/$(MOZ_PKG_APPNAME)/$(APPNAME)/$(APP_CONTENTS)/*.chk
-# The only difference betewen the two trees now should be the
-# about:buildconfig page.  Fix it up.
-	$(TOPSRCDIR)/build/macosx/universal/fix-buildconfig $(FIX_MODE) \
-	  $(DIST_ARCH_1)/$(MOZ_PKG_APPNAME)/$(APPNAME)/$(BUILDCONFIG) \
-	  $(DIST_ARCH_2)/$(MOZ_PKG_APPNAME)/$(APPNAME)/$(BUILDCONFIG)
+ifdef ENABLE_TESTS
 	mkdir -p $(DIST_UNI)/$(MOZ_PKG_APPNAME)
 	rm -f $(DIST_ARCH_2)/universal
 	ln -s $(call core_abspath,$(DIST_UNI)) $(DIST_ARCH_2)/universal
-	rm -rf $(DIST_UNI)/$(MOZ_PKG_APPNAME)/$(APPNAME)
-	$(TOPSRCDIR)/build/macosx/universal/unify \
-          --unify-with-sort "\.manifest$$" \
-          --unify-with-sort "components\.list$$" \
-	  $(DIST_ARCH_1)/$(MOZ_PKG_APPNAME)/$(APPNAME) \
-	  $(DIST_ARCH_2)/$(MOZ_PKG_APPNAME)/$(APPNAME) \
-	  $(DIST_UNI)/$(MOZ_PKG_APPNAME)/$(APPNAME)
-# A universal .dmg can now be produced by making in either architecture's
-# INSTALLER_DIR.
-ifdef ENABLE_TESTS
 # Now, repeat the process for the test package.
 	$(MAKE) -C $(OBJDIR_ARCH_1) UNIVERSAL_BINARY= CHROME_JAR= package-tests
 	$(MAKE) -C $(OBJDIR_ARCH_2) UNIVERSAL_BINARY= CHROME_JAR= package-tests
 	rm -rf $(DIST_UNI)/test-package-stage
 # automation.py differs because it hardcodes a path to
 # dist/bin. It doesn't matter which one we use.
 	if test -d $(DIST_ARCH_1)/test-package-stage -a                 \
                 -d $(DIST_ARCH_2)/test-package-stage; then              \
--- a/build/macosx/universal/mozconfig.common
+++ b/build/macosx/universal/mozconfig.common
@@ -4,16 +4,18 @@
 
 mk_add_options MOZ_UNIFY_BDATE=1
 
 mk_add_options MOZ_POSTFLIGHT_ALL+=build/macosx/universal/flight.mk
 
 DARWIN_VERSION=`uname -r`
 ac_add_app_options i386 --target=i386-apple-darwin$DARWIN_VERSION
 ac_add_app_options x86_64 --target=x86_64-apple-darwin$DARWIN_VERSION
+ac_add_app_options i386 --with-unify-dist=../x86_64/dist
+ac_add_app_options x86_64 --with-unify-dist=../i386/dist
 
 ac_add_options --with-macos-sdk=/Developer/SDKs/MacOSX10.6.sdk
 
 . $topsrcdir/build/macosx/mozconfig.common
 
 # $MOZ_BUILD_APP is only defined when sourced by configure.  That's not a
 # problem, because the variables it affects only need to be set for
 # configure.
--- a/build/unix/elfhack/Makefile.in
+++ b/build/unix/elfhack/Makefile.in
@@ -43,20 +43,16 @@ CSRCS := \
   $(NULL)
 
 ifndef CROSS_COMPILE
 CSRCS += dummy.c
 endif
 
 WRAP_LDFLAGS=
 
-# need this to suppress errors due to /usr/include/linux/byteorder/swab.h
-# on mozilla buildbots
-OS_CXXFLAGS := $(filter-out -pedantic,$(OS_CXXFLAGS))
-
 include $(topsrcdir)/config/rules.mk
 
 test-array$(DLL_SUFFIX) test-ctors$(DLL_SUFFIX): %$(DLL_SUFFIX): %.$(OBJ_SUFFIX) elfhack $(filter inject/%,$(CSRCS:.c=.$(OBJ_SUFFIX)))
 	$(MKSHLIB) $(LDFLAGS) $< -nostartfiles
 	@echo ===
 	@echo === If you get failures below, please file a bug describing the error
 	@echo === and your environment \(compiler and linker versions\), and use
 	@echo === --disable-elf-hack until this is fixed.
--- a/build/unix/mozconfig.asan
+++ b/build/unix/mozconfig.asan
@@ -1,8 +1,10 @@
+. "$topsrcdir/build/mozconfig.common"
+
 # Use Clang as specified in manifest
 export CC="$topsrcdir/clang/bin/clang -fgnu89-inline"
 export CXX="$topsrcdir/clang/bin/clang++"
 
 # Mandatory flags for ASan
 export ASANFLAGS="-faddress-sanitizer -Dxmalloc=myxmalloc -fPIC"
 export CFLAGS="$ASANFLAGS"
 export CXXFLAGS="$ASANFLAGS"
--- a/build/virtualenv/packages.txt
+++ b/build/virtualenv/packages.txt
@@ -16,9 +16,10 @@ mach.pth:python/mach
 mozbuild.pth:python/mozbuild
 pymake.pth:build/pymake
 optional:setup.py:python/psutil:build_ext:--inplace
 optional:psutil.pth:python/psutil
 which.pth:python/which
 mock.pth:python/mock-1.0.0
 mozilla.pth:build
 mozilla.pth:config
+mozilla.pth:xpcom/typelib/xpt/tools
 copy:build/buildconfig.py
--- a/config/config.mk
+++ b/config/config.mk
@@ -547,40 +547,16 @@ endif
 ifndef CROSS_COMPILE
 ifdef USE_ELF_DYNSTR_GC
 ifdef MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS
 ELF_DYNSTR_GC 	= $(DEPTH)/config/elf-dynstr-gc
 endif
 endif
 endif
 
-ifeq ($(OS_ARCH),Darwin)
-ifdef NEXT_ROOT
-export NEXT_ROOT
-PBBUILD = NEXT_ROOT= $(PBBUILD_BIN)
-else # NEXT_ROOT
-PBBUILD = $(PBBUILD_BIN)
-endif # NEXT_ROOT
-PBBUILD_SETTINGS = GCC_VERSION="$(GCC_VERSION)" SYMROOT=build ARCHS="$(OS_TEST)"
-ifdef MACOS_SDK_DIR
-PBBUILD_SETTINGS += SDKROOT="$(MACOS_SDK_DIR)"
-endif # MACOS_SDK_DIR
-ifdef MACOSX_DEPLOYMENT_TARGET
-export MACOSX_DEPLOYMENT_TARGET
-PBBUILD_SETTINGS += MACOSX_DEPLOYMENT_TARGET="$(MACOSX_DEPLOYMENT_TARGET)"
-endif # MACOSX_DEPLOYMENT_TARGET
-
-ifdef MOZ_OPTIMIZE
-ifeq (2,$(MOZ_OPTIMIZE))
-# Only override project defaults if the config specified explicit settings
-PBBUILD_SETTINGS += GCC_MODEL_TUNING= OPTIMIZATION_CFLAGS="$(MOZ_OPTIMIZE_FLAGS)"
-endif # MOZ_OPTIMIZE=2
-endif # MOZ_OPTIMIZE
-endif # OS_ARCH=Darwin
-
 ifdef MOZ_USING_CCACHE
 ifdef CLANG_CXX
 export CCACHE_CPP2=1
 endif
 endif
 
 # Set link flags according to whether we want a console.
 ifdef MOZ_WINCONSOLE
@@ -746,18 +722,16 @@ ifdef MOZ_DEBUG
 JAVAC_FLAGS += -g
 endif
 
 ifdef TIERS
 DIRS += $(foreach tier,$(TIERS),$(tier_$(tier)_dirs))
 STATIC_DIRS += $(foreach tier,$(TIERS),$(tier_$(tier)_staticdirs))
 endif
 
-OPTIMIZE_JARS_CMD = $(PYTHON) $(call core_abspath,$(topsrcdir)/config/optimizejars.py)
-
 CREATE_PRECOMPLETE_CMD = $(PYTHON) $(call core_abspath,$(topsrcdir)/config/createprecomplete.py)
 
 # MDDEPDIR is the subdirectory where dependency files are stored
 MDDEPDIR := .deps
 
 EXPAND_LIBS_EXEC = $(PYTHON) $(topsrcdir)/config/expandlibs_exec.py $(if $@,--depend $(MDDEPDIR)/$(@F).pp --target $@)
 EXPAND_LIBS_GEN = $(PYTHON) $(topsrcdir)/config/expandlibs_gen.py $(if $@,--depend $(MDDEPDIR)/$(@F).pp)
 EXPAND_AR = $(EXPAND_LIBS_EXEC) --extract -- $(AR)
deleted file mode 100644
--- a/config/optimizejars.py
+++ /dev/null
@@ -1,341 +0,0 @@
-# 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 sys, os, subprocess, struct, re
-
-local_file_header = [
-    ("signature", "uint32"),
-    ("min_version", "uint16"),
-    ("general_flag", "uint16"),
-    ("compression", "uint16"),
-    ("lastmod_time", "uint16"),
-    ("lastmod_date", "uint16"),
-    ("crc32", "uint32"),
-    ("compressed_size", "uint32"),
-    ("uncompressed_size", "uint32"),
-    ("filename_size", "uint16"),
-    ("extra_field_size", "uint16"),
-    ("filename", "filename_size"),
-    ("extra_field", "extra_field_size"),
-    ("data", "compressed_size")
-]
-
-cdir_entry = [
-    ("signature", "uint32"),
-    ("creator_version", "uint16"),
-    ("min_version", "uint16"),
-    ("general_flag", "uint16"),
-    ("compression", "uint16"),
-    ("lastmod_time", "uint16"),
-    ("lastmod_date", "uint16"),
-    ("crc32", "uint32"),
-    ("compressed_size", "uint32"),
-    ("uncompressed_size", "uint32"),
-    ("filename_size", "uint16"),
-    ("extrafield_size", "uint16"),
-    ("filecomment_size", "uint16"),
-    ("disknum", "uint16"),
-    ("internal_attr", "uint16"),
-    ("external_attr", "uint32"),
-    ("offset", "uint32"),
-    ("filename", "filename_size"),
-    ("extrafield", "extrafield_size"),
-    ("filecomment", "filecomment_size"),
-]
-
-cdir_end = [
-    ("signature", "uint32"),
-    ("disk_num", "uint16"),
-    ("cdir_disk", "uint16"),
-    ("disk_entries", "uint16"),
-    ("cdir_entries", "uint16"),
-    ("cdir_size", "uint32"),
-    ("cdir_offset", "uint32"),
-    ("comment_size", "uint16"),
-]
-
-type_mapping = { "uint32":"I", "uint16":"H"}
-
-def format_struct (format):
-    string_fields = {}
-    fmt = "<"
-    for (name,value) in iter(format):
-        try:
-            fmt += type_mapping[value][0]
-        except KeyError:
-            string_fields[name] = value
-    return (fmt, string_fields)
-
-def size_of(format):
-    return struct.calcsize(format_struct(format)[0])
-
-class MyStruct:
-    def __init__(self, format, string_fields):
-        self.__dict__["struct_members"] = {}
-        self.__dict__["format"] = format
-        self.__dict__["string_fields"] = string_fields
-
-    def addMember(self, name, value):
-        self.__dict__["struct_members"][name] = value
-
-    def __getattr__(self, item):
-        try:
-            return self.__dict__["struct_members"][item]
-        except:
-            pass
-        print("no %s" %item)
-        print(self.__dict__["struct_members"])
-        raise AttributeError
-
-    def __setattr__(self, item, value):
-        if item in self.__dict__["struct_members"]:
-            self.__dict__["struct_members"][item] = value
-        else:
-            raise AttributeError
-
-    def pack(self):
-        extra_data = ""
-        values = []
-        string_fields = self.__dict__["string_fields"]
-        struct_members = self.__dict__["struct_members"]
-        format = self.__dict__["format"]
-        for (name,_) in format:
-            if name in string_fields:
-                extra_data = extra_data + struct_members[name]
-            else:
-                values.append(struct_members[name]);
-        return struct.pack(format_struct(format)[0], *values) + extra_data
-   
-ENDSIG = 0x06054b50
-
-def assert_true(cond, msg):
-    if not cond:
-        raise Exception(msg)
-        exit(1)
-
-class BinaryBlob:
-    def __init__(self, f):
-       self.data = open(f, "rb").read()
-       self.offset = 0
-       self.length = len(self.data)
-
-    def readAt(self, pos, length):
-        self.offset = pos + length
-        return self.data[pos:self.offset]
-
-    def read_struct (self, format, offset = None):
-        if offset == None:
-            offset = self.offset
-        (fstr, string_fields) = format_struct(format)
-        size = struct.calcsize(fstr)
-        data = self.readAt(offset, size)
-        ret = struct.unpack(fstr, data)
-        retstruct = MyStruct(format, string_fields)
-        i = 0
-        for (name,_) in iter(format):
-            member_desc = None
-            if not name in string_fields:
-                member_data = ret[i]
-                i = i + 1
-            else:
-                # zip has data fields which are described by other struct fields, this does 
-                # additional reads to fill em in
-                member_desc = string_fields[name]
-                member_data = self.readAt(self.offset, retstruct.__getattr__(member_desc))
-            retstruct.addMember(name, member_data)
-        # sanity check serialization code
-        data = self.readAt(offset, self.offset - offset)
-        out_data = retstruct.pack()
-        assert_true(out_data == data, "Serialization fail %d !=%d"% (len(out_data), len(data)))
-        return retstruct
-
-def optimizejar(jar, outjar, inlog = None):
-    if inlog is not None:
-        inlog = open(inlog).read().rstrip()
-        # in the case of an empty log still move the index forward
-        if len(inlog) == 0:
-            inlog = []
-        else:
-            inlog = inlog.split("\n")
-    outlog = []
-    jarblob = BinaryBlob(jar)
-    dirend = jarblob.read_struct(cdir_end, jarblob.length - size_of(cdir_end))
-    assert_true(dirend.signature == ENDSIG, "no signature in the end");
-    cdir_offset = dirend.cdir_offset
-    readahead = 0
-    if inlog is None and cdir_offset == 4:
-        readahead = struct.unpack("<I", jarblob.readAt(0, 4))[0]
-        print("%s: startup data ends at byte %d" % (outjar, readahead));
-
-    total_stripped = 0;
-    jarblob.offset = cdir_offset
-    central_directory = []
-    for i in range(0, dirend.cdir_entries):
-        entry = jarblob.read_struct(cdir_entry)
-        if entry.filename[-1:] == "/":
-            total_stripped += len(entry.pack())
-        else:
-            total_stripped += entry.extrafield_size
-        central_directory.append(entry)
-        
-    reordered_count = 0
-    if inlog is not None:
-        dup_guard = set()
-        for ordered_name in inlog:
-            if ordered_name in dup_guard:
-                continue
-            else:
-                dup_guard.add(ordered_name)
-            found = False
-            for i in range(reordered_count, len(central_directory)):
-                if central_directory[i].filename == ordered_name:
-                    # swap the cdir entries
-                    tmp = central_directory[i]
-                    central_directory[i] = central_directory[reordered_count]
-                    central_directory[reordered_count] = tmp
-                    reordered_count = reordered_count + 1
-                    found = True
-                    break
-            if not found:
-                print( "Can't find '%s' in %s" % (ordered_name, jar))
-
-    outfd = open(outjar, "wb")
-    out_offset = 0
-    if inlog is not None:
-        # have to put central directory at offset 4 cos 0 confuses some tools.
-        # This also lets us specify how many entries should be preread
-        dirend.cdir_offset = 4
-        # make room for central dir + end of dir + 4 extra bytes at front
-        out_offset = dirend.cdir_offset + dirend.cdir_size + size_of(cdir_end) - total_stripped
-        outfd.seek(out_offset)
-
-    cdir_data = ""
-    written_count = 0
-    crc_mapping = {}
-    dups_found = 0
-    dupe_bytes = 0
-    # store number of bytes suggested for readahead
-    for entry in central_directory:
-        # read in the header twice..first for comparison, second time for convenience when writing out
-        jarfile = jarblob.read_struct(local_file_header, entry.offset)
-        assert_true(jarfile.filename == entry.filename, "Directory/Localheader mismatch")
-        # drop directory entries
-        if entry.filename[-1:] == "/":
-            total_stripped += len(jarfile.pack())
-            dirend.cdir_entries -= 1
-            continue
-        # drop extra field data
-        else:
-            total_stripped += jarfile.extra_field_size;
-        entry.extrafield = jarfile.extra_field = ""
-        entry.extrafield_size = jarfile.extra_field_size = 0
-        # January 1st, 2010
-        entry.lastmod_date = jarfile.lastmod_date = ((2010 - 1980) << 9) | (1 << 5) | 1
-        entry.lastmod_time = jarfile.lastmod_time = 0
-        data = jarfile.pack()
-        outfd.write(data)
-        old_entry_offset = entry.offset
-        entry.offset = out_offset
-        out_offset = out_offset + len(data)
-        entry_data = entry.pack()
-        cdir_data += entry_data
-        expected_len = entry.filename_size + entry.extrafield_size + entry.filecomment_size
-        assert_true(len(entry_data) != expected_len,
-                    "%s entry size - expected:%d got:%d" % (entry.filename, len(entry_data), expected_len))
-        written_count += 1
-
-        if entry.crc32 in crc_mapping:
-            dups_found += 1
-            dupe_bytes += entry.compressed_size + len(data) + len(entry_data)
-            print("%s\n\tis a duplicate of\n%s\n---"%(entry.filename, crc_mapping[entry.crc32]))
-        else:
-            crc_mapping[entry.crc32] = entry.filename;
-
-        if inlog is not None:
-            if written_count == reordered_count:
-                readahead = out_offset
-                print("%s: startup data ends at byte %d"%( outjar, readahead));
-            elif written_count < reordered_count:
-                pass
-                #print("%s @ %d" % (entry.filename, out_offset))
-        elif readahead >= old_entry_offset + len(data):
-            outlog.append(entry.filename)
-            reordered_count += 1
-
-    if inlog is None:
-        dirend.cdir_offset = out_offset
-
-    if dups_found > 0:
-        print("WARNING: Found %d duplicate files taking %d bytes"%(dups_found, dupe_bytes))
-
-    dirend.cdir_size = len(cdir_data)
-    dirend.disk_entries = dirend.cdir_entries
-    dirend_data = dirend.pack()
-    assert_true(size_of(cdir_end) == len(dirend_data), "Failed to serialize directory end correctly. Serialized size;%d, expected:%d"%(len(dirend_data), size_of(cdir_end)));
-
-    outfd.seek(dirend.cdir_offset)
-    outfd.write(cdir_data)
-    outfd.write(dirend_data)
-
-    # for ordered jars the central directory is written in the begining of the file, so a second central-directory
-    # entry has to be written in the end of the file
-    if inlog is not None:
-        outfd.seek(0)
-        outfd.write(struct.pack("<I", readahead));
-        outfd.seek(out_offset)
-        outfd.write(dirend_data)
-
-    print "Stripped %d bytes" % total_stripped
-    print "%s %d/%d in %s" % (("Ordered" if inlog is not None else "Deoptimized"),
-                              reordered_count, len(central_directory), outjar)
-    outfd.close()
-    return outlog
-        
-if len(sys.argv) != 5:
-    print "Usage: --optimize|--deoptimize %s JAR_LOG_DIR IN_JAR_DIR OUT_JAR_DIR" % sys.argv[0]
-    exit(1)
-
-jar_regex = re.compile("\\.jar?$")
-
-def optimize(JAR_LOG_DIR, IN_JAR_DIR, OUT_JAR_DIR):
-    ls = os.listdir(IN_JAR_DIR)
-    for jarfile in ls:
-        if not re.search(jar_regex, jarfile):
-            continue
-        injarfile = os.path.join(IN_JAR_DIR, jarfile)
-        outjarfile = os.path.join(OUT_JAR_DIR, jarfile) 
-        logfile = os.path.join(JAR_LOG_DIR, jarfile + ".log")
-        if not os.path.isfile(logfile):
-            logfile = None
-        optimizejar(injarfile, outjarfile, logfile)
-
-def deoptimize(JAR_LOG_DIR, IN_JAR_DIR, OUT_JAR_DIR):
-    if not os.path.exists(JAR_LOG_DIR):
-        os.makedirs(JAR_LOG_DIR)
-
-    ls = os.listdir(IN_JAR_DIR)
-    for jarfile in ls:
-        if not re.search(jar_regex, jarfile):
-            continue
-        injarfile = os.path.join(IN_JAR_DIR, jarfile)
-        outjarfile = os.path.join(OUT_JAR_DIR, jarfile) 
-        logfile = os.path.join(JAR_LOG_DIR, jarfile + ".log")
-        log = optimizejar(injarfile, outjarfile, None)
-        open(logfile, "wb").write("\n".join(log))
-
-def main():        
-    MODE = sys.argv[1]
-    JAR_LOG_DIR = sys.argv[2]
-    IN_JAR_DIR = sys.argv[3]
-    OUT_JAR_DIR = sys.argv[4]
-    if MODE == "--optimize":
-        optimize(JAR_LOG_DIR, IN_JAR_DIR, OUT_JAR_DIR)
-    elif MODE == "--deoptimize":
-        deoptimize(JAR_LOG_DIR, IN_JAR_DIR, OUT_JAR_DIR)
-    else:
-        print("Unknown mode %s" % MODE)
-        exit(1)
-
-if __name__ == '__main__':
-    main()
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1560,22 +1560,24 @@ endif
 # FOO_DEST := target_path
 # INSTALL_TARGETS += FOO
 #
 # Additionally, a FOO_TARGET variable may be added to indicate the target for
 # which the files and executables are installed. Default is "libs".
 
 # If we're using binary nsinstall and it's not built yet, fallback to python nsinstall.
 ifneq (,$(filter $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX),$(install_cmd)))
-nsinstall_is_usable = $(if $(wildcard $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX)),$(eval nsinstall_is_usable := yes)yes)
+ifeq (,$(wildcard $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX)))
+nsinstall_is_usable = $(if $(wildcard $(CONFIG_TOOLS)/nsinstall$(HOST_BIN_SUFFIX)),yes)
 
 define install_cmd_override
 $(1): install_cmd = $$(if $$(nsinstall_is_usable),$$(INSTALL),$$(NSINSTALL_PY)) $$(1)
 endef
 endif
+endif
 
 define install_file_template
 $(or $(3),libs):: $(2)/$(notdir $(1))
 $(call install_cmd_override,$(2)/$(notdir $(1)))
 $(2)/$(notdir $(1)): $(1) $$(call mkdir_deps,$(2))
 	$$(call install_cmd,$(4) "$$<" "$${@D}")
 endef
 $(foreach category,$(INSTALL_TARGETS),\
--- a/configure.in
+++ b/configure.in
@@ -395,16 +395,23 @@ else
 fi
 
 if test -n "$MOZ_WINCONSOLE"; then
     AC_DEFINE(MOZ_WINCONSOLE)
 fi
 
 MOZ_TOOL_VARIABLES
 
+if test -n "$GNU_CC" -a -z "$CLANG_CC" ; then
+    if test "$GCC_MAJOR_VERSION" -eq 4 -a "$GCC_MINOR_VERSION" -lt 4 ||
+       test "$GCC_MAJOR_VERSION" -lt 4; then
+        AC_MSG_ERROR([Only GCC 4.4 or newer supported])
+    fi
+fi
+
 dnl ========================================================
 dnl Special win32 checks
 dnl ========================================================
 
 MOZ_ARG_ENABLE_BOOL(metro,
 [  --enable-metro           Enable Windows Metro build targets],
     MOZ_METRO=1,
     MOZ_METRO=)
@@ -860,58 +867,39 @@ MOZ_PATH_PROG(RPMBUILD, rpmbuild, :)
 AC_SUBST(RPMBUILD)
 
 if test "$COMPILE_ENVIRONMENT"; then
 
 dnl ========================================================
 dnl = Mac OS X toolchain support
 dnl ========================================================
 
-case "$target_os" in
-darwin*)
-    dnl Current known valid versions for GCC_VERSION are 2.95.2 3.1 3.3 4.0.
-    dnl 4.0 identifies itself as 4.0.x, so strip the decidecimal for
-    dnl the environment and includedir purposes (when using an SDK, below),
-    dnl but remember the full version number for the libdir (SDK).
-    changequote(,)
-    GCC_VERSION_FULL=`echo $CXX_VERSION | $PERL -pe 's/^.*gcc version ([^ ]*).*/$1/'`
-    GCC_VERSION=`echo $GCC_VERSION_FULL | $PERL -pe '(split(/\./))[0]>=4&&s/(^\d*\.\d*).*/$1/;'`
-    changequote([,])
-    if test "$GCC_VERSION_FULL" = "4.0.0" ; then
-        dnl Bug 280479, but this keeps popping up in bug 292530 too because
-        dnl 4.0.0/4061 is the default compiler in Tiger.
-        changequote(,)
-        GCC_BUILD=`echo $CXX_VERSION | $PERL -pe 's/^.*build ([^ )]*).*/$1/'`
-        changequote([,])
-        if test "$GCC_BUILD" = "4061" ; then
-            AC_MSG_ERROR([You are attempting to use Apple gcc 4.0 build 4061.
-This compiler was supplied with Xcode 2.0, and contains bugs that prevent it
-from building Mozilla. Upgrade to Xcode 2.1 or later.])
-        fi
-    fi
-
-    dnl xcodebuild needs GCC_VERSION defined in the environment, since it
-    dnl doesn't respect the CC/CXX setting.  With GCC_VERSION set, it will use
-    dnl /usr/bin/g(cc|++)-$GCC_VERSION.
-    MOZ_PATH_PROGS(PBBUILD_BIN, pbbuild xcodebuild pbxbuild)
-
-    dnl sdp was formerly in /Developer/Tools.  As of Mac OS X 10.4 (Darwin 8),
-    dnl it has moved into /usr/bin.
-    MOZ_PATH_PROG(SDP, sdp, :, [$PATH:/usr/bin:/Developer/Tools])
-    ;;
-esac
-
-AC_SUBST(GCC_VERSION)
-
 dnl The universal machinery sets UNIVERSAL_BINARY to inform packager.mk
 dnl that a universal binary is being produced and MOZ_CAN_RUN_PROGRAMS
 dnl when we can run target binaries.
 AC_SUBST(UNIVERSAL_BINARY)
 AC_SUBST(MOZ_CAN_RUN_PROGRAMS)
 
+MOZ_ARG_WITH_STRING(unify-dist,
+[  --with-unify-dist=dir   Location of the dist directory to unify with at packaging time (Mac OS X universal build only)],
+    UNIFY_DIST=$withval)
+if test -n "$UNIVERSAL_BINARY"; then
+    if test -z "$UNIFY_DIST"; then
+        AC_MSG_ERROR([You need to provide the --with-unify-dist=dir argument when performing a universal build])
+    fi
+    case "$UNIFY_DIST" in
+    /*)
+        ;;
+    *)
+        UNIFY_DIST="${MOZ_BUILD_ROOT}/${UNIFY_DIST}"
+        ;;
+    esac
+fi
+AC_SUBST(UNIFY_DIST)
+
 dnl ========================================================
 dnl Check for MacOS deployment target version
 dnl ========================================================
 
 MOZ_ARG_ENABLE_STRING(macos-target,
                       [  --enable-macos-target=VER (default=10.6)
                           Set the minimum MacOS version needed at runtime],
                       [_MACOSX_DEPLOYMENT_TARGET=$enableval])
@@ -951,36 +939,22 @@ if test "$MACOS_SDK_DIR"; then
   dnl the libIDL checks (below) and xpidl build.
 
   if test ! -d "$MACOS_SDK_DIR"; then
     AC_MSG_ERROR([SDK not found.  When using --with-macos-sdk, you must
 specify a valid SDK.  SDKs are installed when the optional cross-development
 tools are selected during the Xcode/Developer Tools installation.])
   fi
 
-  GCC_VERSION_MAJOR=`echo $GCC_VERSION_FULL | $PERL -pe 's/(^\d*).*/$1/;'`
-  if test "$GCC_VERSION_MAJOR" -lt "4" ; then
-    AC_MSG_ERROR([You need to upgrade the compiler version to 4.x])
-  else
-    CFLAGS="$CFLAGS -isysroot ${MACOS_SDK_DIR}"
-    CXXFLAGS="$CXXFLAGS -isysroot ${MACOS_SDK_DIR}"
-
-    dnl CPP/CXXCPP needs to be set for MOZ_CHECK_HEADER.
-    CPP="$CPP -isysroot ${MACOS_SDK_DIR}"
-    CXXCPP="$CXXCPP -isysroot ${MACOS_SDK_DIR}"
-
-    if test "$GCC_VERSION_FULL" = "4.0.0" ; then
-      dnl If gcc >= 4.0, we're guaranteed to be on Tiger, which has an ld
-      dnl that supports -syslibroot.  Don't set NEXT_ROOT because it will
-      dnl be ignored and cause warnings when -syslibroot is specified.
-      dnl gcc 4.0.1 will pass -syslibroot to ld automatically based on
-      dnl the -isysroot it receives, so this is only needed with 4.0.0.
-      LDFLAGS="$LDFLAGS -Wl,-syslibroot,${MACOS_SDK_DIR}"
-    fi
-  fi
+  CFLAGS="$CFLAGS -isysroot ${MACOS_SDK_DIR}"
+  CXXFLAGS="$CXXFLAGS -isysroot ${MACOS_SDK_DIR}"
+
+  dnl CPP/CXXCPP needs to be set for MOZ_CHECK_HEADER.
+  CPP="$CPP -isysroot ${MACOS_SDK_DIR}"
+  CXXCPP="$CXXCPP -isysroot ${MACOS_SDK_DIR}"
 
   AC_LANG_SAVE
   AC_MSG_CHECKING([for valid compiler/Mac OS X SDK combination])
   AC_LANG_CPLUSPLUS
   AC_TRY_COMPILE([#include <new>],[],
    result=yes,
    result=no)
   AC_LANG_RESTORE
@@ -1393,17 +1367,22 @@ if test "$GNU_CC"; then
         # Some tools like ASan use a runtime library that is only
         # linked against executables, so we must allow undefined
         # symbols for shared objects in some cases.
         if test -z "$MOZ_NO_WLZDEFS"; then
             # Don't allow undefined symbols in libraries
             DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
         fi
     fi
-    WARNINGS_AS_ERRORS='-Werror -Wno-error=uninitialized'
+    WARNINGS_AS_ERRORS='-Werror'
+    # Don't treat -Wuninitialized as error b/c it has lots of false positives.
+    WARNINGS_AS_ERRORS="$WARNINGS_AS_ERRORS -Wno-error=uninitialized"
+    # Don't treat -Wdeprecated-declarations as error b/c we don't want our
+    # builds held hostage when a platform-specific API is suddenly deprecated.
+    WARNINGS_AS_ERRORS="$WARNINGS_AS_ERRORS -Wno-error=deprecated-declarations"
     DSO_CFLAGS=''
     DSO_PIC_CFLAGS='-fPIC'
     ASFLAGS="$ASFLAGS -fPIC"
     AC_MSG_CHECKING([for --noexecstack option to as])
     _SAVE_CFLAGS=$CFLAGS
     CFLAGS="$CFLAGS -Wa,--noexecstack"
     AC_TRY_COMPILE(,,AC_MSG_RESULT([yes])
                      [ASFLAGS="$ASFLAGS -Wa,--noexecstack"],
@@ -1432,50 +1411,44 @@ if test "$GNU_CC"; then
     AC_TRY_COMPILE([asm ("pmaddubsw %xmm2,%xmm3");],,AC_MSG_RESULT([yes])
                      [HAVE_TOOLCHAIN_SUPPORT_MSSSE3=1],
                      AC_MSG_RESULT([no]))
     CFLAGS=$_SAVE_CFLAGS
     AC_SUBST(HAVE_TOOLCHAIN_SUPPORT_MSSSE3)
 
     # Turn on GNU-specific warnings:
     # -Wall - turn on a lot of warnings
-    # -pedantic - this is turned on below
-    # -Wpointer-arith - enabled with -pedantic, but good to have even if not
+    # -Wpointer-arith - good to have
     # -Wdeclaration-after-statement - MSVC doesn't like these
     # -Werror=return-type - catches missing returns, zero false positives
     # -Wtype-limits - catches overflow bugs, few false positives
     # -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
     #
     _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -Wpointer-arith -Wdeclaration-after-statement"
     MOZ_C_SUPPORTS_WARNING(-W, error=return-type, ac_c_has_werror_return_type)
     MOZ_C_SUPPORTS_WARNING(-W, type-limits, ac_c_has_wtype_limits)
     MOZ_C_SUPPORTS_WARNING(-W, empty-body, ac_c_has_wempty_body)
     
-    # Turn off the following warnings that -Wall/-pedantic turn on:
+    # Turn off the following warnings that -Wall turns on:
     # -Wno-unused - lots of violations in third-party code
-    # -Wno-overlength-strings - we exceed the minimum maximum length frequently
     #
     _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wno-unused"
-    MOZ_C_SUPPORTS_WARNING(-Wno-, overlength-strings, ac_c_has_wno_overlength_strings)
 
     if test -z "$INTEL_CC" -a -z "$CLANG_CC"; then
        # Don't use -Wcast-align with ICC or clang
        case "$CPU_ARCH" in
            # And don't use it on hppa, ia64, sparc, arm, since it's noisy there
            hppa | ia64 | sparc | arm)
            ;;
            *)
         _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wcast-align"
            ;;
        esac
     fi
 
-    dnl Turn pedantic on but disable the warnings for long long
-    _PEDANTIC=1
-
     _DEFINES_CFLAGS='-include $(DEPTH)/mozilla-config.h -DMOZILLA_CLIENT'
     _USE_CPP_INCLUDE_FLAG=1
 
 elif test "$SOLARIS_SUNPRO_CC"; then
     DSO_CFLAGS=''
     if test "$CPU_ARCH" = "sparc"; then
         # for Sun Studio on Solaris/SPARC
         DSO_PIC_CFLAGS='-xcode=pic32'
@@ -1499,38 +1472,31 @@ else
 fi
 
 if test "$GNU_CXX"; then
     # FIXME: Let us build with strict aliasing. bug 414641.
     CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-strict-aliasing"
 
     # Turn on GNU-specific warnings:
     # -Wall - turn on a lot of warnings
-    # -pedantic - this is turned on below
-    # -Wpointer-arith - enabled with -pedantic, but good to have even if not
+    # -Wpointer-arith - good to have
     # -Woverloaded-virtual - ???
     # -Werror=return-type - catches missing returns, zero false positives
     # -Wtype-limits - catches overflow bugs, few false positives
     # -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
     #
     _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual"
     MOZ_CXX_SUPPORTS_WARNING(-W, error=return-type, ac_cxx_has_werror_return_type)
     MOZ_CXX_SUPPORTS_WARNING(-W, type-limits, ac_cxx_has_wtype_limits)
     MOZ_CXX_SUPPORTS_WARNING(-W, empty-body, ac_cxx_has_wempty_body)
 
-    # Turn off the following warnings that -Wall/-pedantic turn on:
-    # -Wno-ctor-dtor-privacy - ???
-    # -Wno-overlength-strings - we exceed the minimum maximum length frequently 
+    # Turn off the following warnings that -Wall turns on:
     # -Wno-invalid-offsetof - we use offsetof on non-POD types frequently
-    # -Wno-variadic-macros - ???
     #
-    _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-ctor-dtor-privacy"
-    MOZ_CXX_SUPPORTS_WARNING(-Wno-, overlength-strings, ac_cxx_has_wno_overlength_strings)
     MOZ_CXX_SUPPORTS_WARNING(-Wno-, invalid-offsetof, ac_cxx_has_wno_invalid_offsetof)
-    MOZ_CXX_SUPPORTS_WARNING(-Wno-, variadic-macros, ac_cxx_has_wno_variadic_macros)
 
     if test -z "$INTEL_CXX" -a -z "$CLANG_CXX"; then
        # Don't use -Wcast-align with ICC or clang
        case "$CPU_ARCH" in
            # And don't use it on hppa, ia64, sparc, arm, since it's noisy there
            hppa | ia64 | sparc | arm)
            ;;
            *)
@@ -1937,17 +1903,16 @@ case "$target" in
     fi
     AC_DEFINE(NSCAP_DISABLE_DEBUG_PTR_TYPES)
     ;;
 
 *-darwin*)
     MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
     MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -o $@'
     MOZ_OPTIMIZE_FLAGS="-O3"
-    _PEDANTIC=
     # Statically disable jemalloc on 10.5 and 32-bit 10.6.  See bug 702250.
     if test "$HAVE_64BIT_OS"; then
         MOZ_MEMORY=1
     fi
     DLL_SUFFIX=".dylib"
     DSO_LDOPTS=''
     STRIP_FLAGS="$STRIP_FLAGS -x -S"
     # Check whether we're targeting OS X or iOS
@@ -2075,20 +2040,19 @@ ia64*-hpux*)
     # Note: both GNU_CC and INTEL_CC are set when using Intel's C compiler.
     # Similarly for GNU_CXX and INTEL_CXX.
     if test "$INTEL_CC" -o "$INTEL_CXX"; then
         # -Os has been broken on Intel's C/C++ compilers for quite a
         # while; Intel recommends against using it.
         MOZ_OPTIMIZE_FLAGS="-O2"
         MOZ_DEBUG_FLAGS="-g"
     elif test "$GNU_CC" -o "$GNU_CXX"; then
-        GCC_VERSION=`$CC -v 2>&1 | awk '/^gcc version/ { print $3 }'`
         case $GCC_VERSION in
-        4.1.*|4.2.*|4.5.*)
-            # -Os is broken on gcc 4.1.x 4.2.x, 4.5.x we need to tweak it to get good results.
+        4.5.*)
+            # -Os is broken on gcc 4.5.x we need to tweak it to get good results.
             MOZ_OPTIMIZE_SIZE_TWEAK="-finline-limit=50"
         esac
         MOZ_PGO_OPTIMIZE_FLAGS="-O3"
         MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks $MOZ_OPTIMIZE_SIZE_TWEAK"
         MOZ_DEBUG_FLAGS="-g"
     fi
 
     TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"'
@@ -2134,17 +2098,16 @@ ia64*-hpux*)
         RCFLAGS='-O coff --use-temp-file'
         # mingw doesn't require kernel32, user32, and advapi32 explicitly
         LIBS="$LIBS -luuid -lgdi32 -lwinmm -lwsock32 -luserenv -lsecur32 -lnetapi32"
         MOZ_FIX_LINK_PATHS=
         DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib -lxpcom -lxpcom_core -lmozalloc'
         XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/lib -lxpcom -lmozalloc'
         DLL_PREFIX=
         IMPORT_LIB_SUFFIX=dll.a
-        GCC_VERSION=`$CC -v 2>&1 | awk '/^gcc version/ { print $3 }'`
 
         # We use mix of both POSIX and Win32 printf format across the tree, so format
         # warnings are useless on mingw.
         MOZ_C_SUPPORTS_WARNING(-Wno-, format, ac_c_has_wno_format)
         MOZ_CXX_SUPPORTS_WARNING(-Wno-, format, ac_cxx_has_wno_format)
     else
         TARGET_COMPILER_ABI=msvc
         HOST_CC='$(CC)'
@@ -2376,16 +2339,18 @@ ia64*-hpux*)
     LIBXUL_LIBS='-L$(LIBXUL_DIST)/lib $(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
     TARGET_MD_ARCH=os2
     _PLATFORM_DEFAULT_TOOLKIT="cairo-os2"
     RC=rc.exe
     MC=mc.exe
     RCFLAGS='-n'
     MOZ_USER_DIR="Mozilla"
     ZIP="$ZIP -X"
+    STRIP=lxlite
+    STRIP_FLAGS="/yua /ydd /yxd /ynl /anp /b- /cs+ /d /i- /ml1 /mr2 /mf2 /r+ /u+ /x- /zs:0 /zx /zd"
 
     if test "$MOZTOOLS"; then
         MOZ_TOOLS_DIR=`echo $MOZTOOLS | sed -e 's|\\\\|/|g'`
     else
         AC_MSG_ERROR([MOZTOOLS is not set])
     fi
     if test -n "$MOZ_OS2_HIGH_MEMORY"; then
         DSO_LDOPTS="$DSO_LDOPTS -Zhigh-mem"
@@ -5241,18 +5206,22 @@ if test "$NS_PRINTING"; then
 fi
 
 dnl Turn off webrtc for OS's we don't handle yet, but allow 
 dnl --enable-webrtc to override.  Can disable for everything in
 dnl the master list above.
 if test -n "$MOZ_WEBRTC"; then
     case "$target" in
     *-android*|*-linuxandroid*)
-        dnl Make sure doesn't get matched by *-linux*
-        MOZ_WEBRTC=
+        if test -n "$MOZ_B2G"; then
+            MOZ_WEBRTC=1
+        else
+            dnl Make sure doesn't get matched by *-linux*
+            MOZ_WEBRTC=
+        fi
         ;;
     *-linux*|*-mingw*|*-darwin*)
         dnl Leave enabled
         ;;
     *)
         dnl default to disabled for all others
         MOZ_WEBRTC=
         ;;
@@ -5270,28 +5239,30 @@ MOZ_ARG_DISABLE_BOOL(webrtc,
 if test -n "$MOZ_WEBRTC"; then
     AC_DEFINE(MOZ_WEBRTC)
     MOZ_MEDIA=1
     MOZ_RAW=1
     MOZ_VP8=1
     MOZ_VP8_ENCODER=1
     MOZ_VP8_ERROR_CONCEALMENT=1
 
-    dnl OpenSLES is only available in Android 2.3 and later; we'll change this
-    dnl hard dependency to a dynamic load with graceful runtime failure before
-    dnl we make --enable-webrtc on by default in Android (bug 815905)
-    dnl
-    if test "$OS_TARGET" = "Android"; then
-       LDFLAGS="$LDFLAGS -lOpenSLES"
-    fi
-    case "$target" in
-    *-android*|*-linuxandroid*)
-       LDFLAGS="$LDFLAGS -lOpenSLES"
-       ;;
-    esac
+    if test "$MOZ_WIDGET_TOOLKIT" != "gonk"; then
+       dnl OpenSLES is only available in Android 2.3 and later; we'll change this
+       dnl hard dependency to a dynamic load with graceful runtime failure before
+       dnl we make --enable-webrtc on by default in Android (bug 815905)
+       dnl
+       if test "$OS_TARGET" = "Android"; then
+          LDFLAGS="$LDFLAGS -lOpenSLES"
+       fi
+       case "$target" in
+          *-android*|*-linuxandroid*)
+          LDFLAGS="$LDFLAGS -lOpenSLES"
+          ;;
+       esac
+    fi
 
 dnl enable once Signaling lands
     MOZ_WEBRTC_SIGNALING=1
     AC_DEFINE(MOZ_WEBRTC_SIGNALING)
     if test "${OS_TARGET}" = "WINNT"; then
         MOZ_WEBRTC_IN_LIBXUL=1
     fi
 dnl enable once PeerConnection lands
@@ -7720,28 +7691,30 @@ dnl Omnijar packaging is compatible with
 dnl In unpackaged builds, omnijar looks for files as if
 dnl things were flat packaged. After packaging, all files
 dnl are loaded from a single jar. MOZ_CHROME_FILE_FORMAT
 dnl is set to flat since putting files into jars is only
 dnl done during packaging with omnijar.
 if test "$MOZ_CHROME_FILE_FORMAT" = "omni"; then
     MOZ_OMNIJAR=1
     AC_DEFINE(MOZ_OMNIJAR)
-    if test "$OS_ARCH" = "WINNT" -o "$OS_ARCH" = "OS2" -o "$MOZ_WIDGET_TOOLKIT" = "android"; then
-        MOZ_CHROME_FILE_FORMAT=flat
-    else
-        MOZ_CHROME_FILE_FORMAT=symlink
-    fi
 elif test "$MOZ_CHROME_FILE_FORMAT" = "jar"; then
     AC_DEFINE(MOZ_CHROME_FILE_FORMAT_JAR)
 fi
+MOZ_PACKAGER_FORMAT="$MOZ_CHROME_FILE_FORMAT"
+if test "$OS_ARCH" = "WINNT" -o "$OS_ARCH" = "OS2" -o "$MOZ_WIDGET_TOOLKIT" = "android"; then
+    MOZ_CHROME_FILE_FORMAT=flat
+else
+    MOZ_CHROME_FILE_FORMAT=symlink
+fi
 
 OMNIJAR_NAME=omni.ja
 AC_SUBST(OMNIJAR_NAME)
 AC_SUBST(MOZ_OMNIJAR)
+AC_SUBST(MOZ_PACKAGER_FORMAT)
 
 dnl ========================================================
 dnl = Define default location for MOZILLA_FIVE_HOME
 dnl ========================================================
 MOZ_ARG_WITH_STRING(default-mozilla-five-home,
 [  --with-default-mozilla-five-home
                           Set the default value for MOZILLA_FIVE_HOME],
 [ val=`echo $withval`
@@ -7849,43 +7822,16 @@ fi
 AC_SUBST(PROFILE_GEN_CFLAGS)
 AC_SUBST(PROFILE_GEN_LDFLAGS)
 AC_SUBST(PROFILE_USE_CFLAGS)
 AC_SUBST(PROFILE_USE_LDFLAGS)
 
 AC_LANG_CPLUSPLUS
 
 dnl ========================================================
-dnl Test for -pedantic bustage
-dnl ========================================================
-MOZ_ARG_DISABLE_BOOL(pedantic,
-[  --disable-pedantic      Issue all warnings demanded by strict ANSI C ],
-_PEDANTIC= )
-if test "$_PEDANTIC"; then
-    _SAVE_CXXFLAGS=$CXXFLAGS
-    CXXFLAGS="$CXXFLAGS -pedantic ${_WARNINGS_CXXFLAGS} -Wno-long-long"
-    AC_MSG_CHECKING([whether C++ compiler has -pedantic long long bug])
-    AC_TRY_COMPILE([$configure_static_assert_macros],
-                   [CONFIGURE_STATIC_ASSERT(sizeof(long long) == 8)],
-                   result="no", result="yes" )
-    AC_MSG_RESULT([$result])
-    CXXFLAGS="$_SAVE_CXXFLAGS"
-
-    case "$result" in
-    no)
-        _WARNINGS_CFLAGS="-pedantic ${_WARNINGS_CFLAGS} -Wno-long-long"
-        _WARNINGS_CXXFLAGS="-pedantic ${_WARNINGS_CXXFLAGS} -Wno-long-long"
-        ;;
-    yes)
-        AC_MSG_ERROR([Your compiler appears to have a known bug where long long is miscompiled when using -pedantic.  Reconfigure using --disable-pedantic. ])
-        ;;
-    esac
-fi
-
-dnl ========================================================
 dnl Autoconf test for gcc 2.7.2.x (and maybe others?) so that we don't
 dnl provide non-const forms of the operator== for comparing nsCOMPtrs to
 dnl raw pointers in nsCOMPtr.h.  (VC++ has the same bug.)
 dnl ========================================================
 _SAVE_CXXFLAGS=$CXXFLAGS
 CXXFLAGS="$CXXFLAGS ${_WARNINGS_CXXFLAGS}"
 AC_CACHE_CHECK(for correct overload resolution with const and templates,
     ac_nscap_nonconst_opeq_bug,
@@ -9040,31 +8986,45 @@ if test "${OS_TARGET}" = "WINNT"; then
    if test "$HAVE_64BIT_OS"; then
       OS_BITS=64
    else
       OS_BITS=32
    fi
    EXTRA_GYP_DEFINES="-D MSVS_VERSION=${_MSVS_VERSION} -D MSVS_OS_BITS=${OS_BITS}"
 
 elif test "${OS_TARGET}" = "Android"; then
-   EXTRA_GYP_DEFINES="-D gtest_target_type=executable -D android_toolchain=${android_toolchain} -G os=android "
+   if test "${MOZ_WIDGET_TOOLKIT}" != "gonk"; then
+      EXTRA_GYP_DEFINES="-D gtest_target_type=executable -D android_toolchain=${android_toolchain} -G os=android "
+   fi
    if test -n "$ARM_ARCH" && test "$ARM_ARCH" -lt 7; then
-      EXTRA_GYP_DEFINES+=" -D armv7=0 "
+      EXTRA_GYP_DEFINES="${EXTRA_GYP_DEFINES} -D armv7=0 "
    else
-      EXTRA_GYP_DEFINES+=" -D armv7=1 "
+      EXTRA_GYP_DEFINES="${EXTRA_GYP_DEFINES} -D armv7=1 "
    fi
 fi
 
 if test -n "$MOZ_WEBRTC"; then
    AC_MSG_RESULT("generating WebRTC Makefiles...")
 
+   if test "${MOZ_WIDGET_TOOLKIT}" = "gonk"; then
+      EXTRA_GYP_DEFINES="${EXTRA_GYP_DEFINES} -D moz_widget_toolkit_gonk=1"
+   else
+      EXTRA_GYP_DEFINES="${EXTRA_GYP_DEFINES} -D moz_widget_toolkit_gonk=0"
+   fi
+
 dnl Any --include files must also appear in -D FORCED_INCLUDE_FILE= entries
 dnl so that regeneration via dependencies works correctly
    WEBRTC_CONFIG="-D build_with_mozilla=1 --include ${srcdir}/media/webrtc/webrtc_config.gypi -D FORCED_INCLUDE_FILE=${srcdir}/media/webrtc/webrtc_config.gypi"
 
+   if test -n HAVE_CLOCK_MONOTONIC; then
+      WEBRTC_CONFIG="${WEBRTC_CONFIG} -D moz_have_clock_monotonic=1"
+   else
+      WEBRTC_CONFIG="${WEBRTC_CONFIG} -D moz_have_clock_monotonic=0"
+   fi
+
    GYP_WEBRTC_OPTIONS="--format=mozmake ${WEBRTC_CONFIG} -D target_arch=${WEBRTC_TARGET_ARCH} ${EXTRA_GYP_DEFINES} --depth=${srcdir}/media/webrtc/trunk --toplevel-dir=${srcdir} -G OBJDIR=${_objdir}"
 
    $PYTHON ${srcdir}/media/webrtc/trunk/build/gyp_chromium \
      $GYP_WEBRTC_OPTIONS \
      --generator-output=${_objdir}/media/webrtc/trunk \
      ${srcdir}/media/webrtc/trunk/peerconnection.gyp
    if test "$?" != 0; then
       AC_MSG_ERROR([failed to generate WebRTC Makefiles])
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -2257,16 +2257,53 @@ public:
     nsContentUtils::EnterMicroTask();
   }
   ~nsAutoMicroTask()
   {
     nsContentUtils::LeaveMicroTask();
   }
 };
 
+namespace mozilla {
+
+/**
+ * Use AutoJSContext when you need a JS context on the stack but don't have one
+ * passed as a parameter. AutoJSContext will take care of finding the most
+ * appropriate JS context and release it when leaving the stack.
+ */
+class NS_STACK_CLASS AutoJSContext {
+public:
+  AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
+  operator JSContext*();
+
+protected:
+  AutoJSContext(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+
+private:
+  // We need this Init() method because we can't use delegating constructor for
+  // the moment. It is a C++11 feature and we do not require C++11 to be
+  // supported to be able to compile Gecko.
+  void Init(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+
+  JSContext* mCx;
+  nsCxPusher mPusher;
+  MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+/**
+ * SafeAutoJSContext is similar to AutoJSContext but will only return the safe
+ * JS context. That means it will never call ::GetCurrentJSContext().
+ */
+class NS_STACK_CLASS SafeAutoJSContext : public AutoJSContext {
+public:
+  SafeAutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
+};
+
+} // namespace mozilla
+
 #define NS_INTERFACE_MAP_ENTRY_TEAROFF(_interface, _allocator)                \
   if (aIID.Equals(NS_GET_IID(_interface))) {                                  \
     foundInterface = static_cast<_interface *>(_allocator);                   \
     if (!foundInterface) {                                                    \
       *aInstancePtr = nullptr;                                                 \
       return NS_ERROR_OUT_OF_MEMORY;                                          \
     }                                                                         \
   } else
--- a/content/base/src/EventSource.cpp
+++ b/content/base/src/EventSource.cpp
@@ -449,48 +449,24 @@ EventSource::OnStopRequest(nsIRequest *a
 
   if (NS_FAILED(aStatusCode)) {
     DispatchFailConnection();
     return aStatusCode;
   }
 
   nsresult rv;
   nsresult healthOfRequestResult = CheckHealthOfRequestCallback(aRequest);
-  if (NS_SUCCEEDED(healthOfRequestResult)) {
-    // check if we had an incomplete UTF8 char at the end of the stream
-    if (mLastConvertionResult == NS_PARTIAL_MORE_INPUT) {
-      rv = ParseCharacter(REPLACEMENT_CHAR);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
+  if (NS_SUCCEEDED(healthOfRequestResult) &&
+      mLastConvertionResult == NS_PARTIAL_MORE_INPUT) {
+    // we had an incomplete UTF8 char at the end of the stream
+    rv = ParseCharacter(REPLACEMENT_CHAR);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
 
-    // once we reach the end of the stream we must
-    // dispatch the current event
-    switch (mStatus)
-    {
-      case PARSE_STATE_CR_CHAR:
-      case PARSE_STATE_COMMENT:
-      case PARSE_STATE_FIELD_NAME:
-      case PARSE_STATE_FIRST_CHAR_OF_FIELD_VALUE:
-      case PARSE_STATE_FIELD_VALUE:
-      case PARSE_STATE_BEGIN_OF_LINE:
-        rv = SetFieldAndClear();
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        rv = DispatchCurrentMessageEvent();  // there is an empty line (CRCR)
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        break;
-
-      // Just for not getting warnings when compiling
-      case PARSE_STATE_OFF:
-      case PARSE_STATE_BEGIN_OF_STREAM:
-      case PARSE_STATE_BOM_WAS_READ:
-        break;
-    }
-  }
+  ClearFields();
 
   nsCOMPtr<nsIRunnable> event =
     NS_NewRunnableMethod(this, &EventSource::ReestablishConnection);
   NS_ENSURE_STATE(event);
 
   rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1293,16 +1269,18 @@ EventSource::DispatchAllMessageEvents()
 
     messageEvent->SetTrusted(true);
 
     rv = DispatchDOMEvent(nullptr, event, nullptr, nullptr);
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to dispatch the message event!!!");
       return;
     }
+
+    mLastEventID.Assign(message->mLastEventID);
   }
 }
 
 nsresult
 EventSource::ClearFields()
 {
   // mLastEventID and mReconnectionTime must be cached
 
@@ -1343,17 +1321,16 @@ EventSource::SetFieldAndClear()
       if (mLastFieldName.EqualsLiteral("event")) {
         mCurrentMessage.mEventName.Assign(mLastFieldValue);
       }
       break;
 
     case PRUnichar('i'):
       if (mLastFieldName.EqualsLiteral("id")) {
         mCurrentMessage.mLastEventID.Assign(mLastFieldValue);
-        mLastEventID.Assign(mLastFieldValue);
       }
       break;
 
     case PRUnichar('r'):
       if (mLastFieldName.EqualsLiteral("retry")) {
         uint32_t newValue=0;
         uint32_t i = 0;  // we must ensure that there are only digits
         bool assign = true;
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -6790,8 +6790,50 @@ nsContentUtils::InternalIsSupported(nsIS
     return (aVersion.IsEmpty() || aVersion.EqualsLiteral("1.0") ||
             aVersion.EqualsLiteral("1.1")) &&
            nsSVGFeatures::HasFeature(aObject, aFeature);
   }
 
   // Otherwise, we claim to support everything
   return true;
 }
+
+AutoJSContext::AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
+  : mCx(nullptr)
+{
+  Init(false MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT);
+}
+
+AutoJSContext::AutoJSContext(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
+  : mCx(nullptr)
+{
+  Init(aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT);
+}
+
+void
+AutoJSContext::Init(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
+{
+  MOZ_ASSERT(!mCx, "mCx should not be initialized!");
+
+  MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+
+  if (!aSafe) {
+    mCx = nsContentUtils::GetCurrentJSContext();
+  }
+
+  if (!mCx) {
+    mCx = nsContentUtils::GetSafeJSContext();
+    bool result = mPusher.Push(mCx);
+    if (!result || !mCx) {
+      MOZ_CRASH();
+    }
+  }
+}
+
+AutoJSContext::operator JSContext*()
+{
+  return mCx;
+}
+
+SafeAutoJSContext::SafeAutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
+  : AutoJSContext(true MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
+{
+}
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -2352,17 +2352,19 @@ nsINode::WrapObject(JSContext *aCx, JSOb
       !hasHadScriptHandlingObject &&
       !nsContentUtils::IsCallerChrome()) {
     Throw<true>(aCx, NS_ERROR_UNEXPECTED);
     *aTriedToWrap = true;
     return nullptr;
   }
 
   JSObject* obj = WrapNode(aCx, aScope, aTriedToWrap);
-  if (obj && ChromeOnlyAccess()) {
+  if (obj && ChromeOnlyAccess() &&
+      !nsContentUtils::IsSystemPrincipal(NodePrincipal()))
+  {
     // Create a new wrapper and cache it.
     JSAutoCompartment ac(aCx, obj);
     JSObject* wrapper = xpc::WrapperFactory::WrapSOWObject(aCx, obj);
     if (!wrapper) {
       ClearWrapper();
       return nullptr;
     }
     dom::SetSystemOnlyWrapper(obj, this, *wrapper);
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -492,18 +492,16 @@ MOCHITEST_FILES_B = \
 		eventsource.resource \
 		eventsource.resource^headers^ \
 		eventsource_redirect.resource \
 		eventsource_redirect.resource^headers^ \
 		eventsource_redirect_to.resource \
 		eventsource_redirect_to.resource^headers^ \
 		badContentType.eventsource \
 		badContentType.eventsource^headers^ \
-		badEventFieldName.eventsource \
-		badEventFieldName.eventsource^headers^ \
 		badHTTPResponseCode.eventsource \
 		badHTTPResponseCode.eventsource^headers^ \
 		badMessageEvent.eventsource \
 		badMessageEvent.eventsource^headers^ \
 		file_restrictedEventSource.sjs \
 		forRemoval.resource \
 		forRemoval.resource^headers^ \
 		accesscontrol.resource \
@@ -622,16 +620,18 @@ MOCHITEST_FILES_B = \
 		test_textnode_normalize_in_selection.html \
 		test_xhr_send_readystate.html \
 		test_bug813919.html \
 		test_bug814576.html \
 		test_xhr_withCredentials.html \
 		test_bothCSPheaders.html \
 		file_bothCSPheaders.html \
 		file_bothCSPheaders.html^headers^ \
+		badMessageEvent2.eventsource \
+		badMessageEvent2.eventsource^headers^ \
 		$(NULL)
 
 # OOP tests don't work on Windows (bug 763081) or native-fennec
 # (see Bug 774939)
 ifneq ($(OS_ARCH),WINNT)
 ifndef MOZ_ANDROID_OMTC
 MOCHITEST_FILES_B += \
 		test_messagemanager_assertpermission.html \
--- a/content/base/test/accesscontrol.resource
+++ b/content/base/test/accesscontrol.resource
@@ -1,5 +1,7 @@
 :this file must be enconded in utf8
 :and its Content-Type must be equal to text/event-stream
 
 event: message
-data: 1
\ No newline at end of file
+data: 1
+
+
--- a/content/base/test/badContentType.eventsource
+++ b/content/base/test/badContentType.eventsource
@@ -1,3 +1,5 @@
 retry:500
 event: message
 data: 1
+
+
deleted file mode 100644
--- a/content/base/test/badEventFieldName.eventsource
+++ /dev/null
@@ -1,4 +0,0 @@
-retry:500
-:space isn't a valid NCName char, am I right?
-event: message event
-data: 1
deleted file mode 100644
--- a/content/base/test/badEventFieldName.eventsource^headers^
+++ /dev/null
@@ -1,1 +0,0 @@
-Content-Type: text/event-stream
--- a/content/base/test/badHTTPResponseCode.eventsource
+++ b/content/base/test/badHTTPResponseCode.eventsource
@@ -1,3 +1,5 @@
 retry:500
 event: message
 data: 1
+
+
--- a/content/base/test/badMessageEvent.eventsource
+++ b/content/base/test/badMessageEvent.eventsource
@@ -1,2 +1,4 @@
 retry:500
 event: message
+
+
new file mode 100644
--- /dev/null
+++ b/content/base/test/badMessageEvent2.eventsource
@@ -0,0 +1,5 @@
+retry:500
+data: ok
+
+id: invalid-id
+data: not-ok
new file mode 100644
--- /dev/null
+++ b/content/base/test/badMessageEvent2.eventsource^headers^
@@ -0,0 +1,1 @@
+Content-Type: text/event-stream
--- a/content/base/test/delayedServerEvents.sjs
+++ b/content/base/test/delayedServerEvents.sjs
@@ -1,15 +1,15 @@
 // this will take strings_to_send.length*500 ms = 5 sec
 
 var timer = null;
 var strings_to_send = ["data\r\n\nda", "ta", ":", "de", "layed1\n\n",
                        "",
                        "",
-                       "data:delayed2", "", ""];
+                       "data:delayed2\n\n", "", ""];
 var resp = null;
 
 function sendNextString()
 {
   if (strings_to_send.length == 0) {
     timer.cancel();
     resp.finish();
     timer = null;
--- a/content/base/test/eventsource.resource
+++ b/content/base/test/eventsource.resource
@@ -13,8 +13,10 @@ unknow: unknow
 event: click
 retry:500
 
 event: blur
 retry:500
 
 event:keypress
 retry:500
+
+
--- a/content/base/test/eventsource_redirect_to.resource
+++ b/content/base/test/eventsource_redirect_to.resource
@@ -1,3 +1,4 @@
 retry:500
 data: 1
 
+
--- a/content/base/test/forRemoval.resource
+++ b/content/base/test/forRemoval.resource
@@ -16,8 +16,9 @@ data: 3
 retry:500
 event: message
 data: 4
 
 retry:500
 event: message
 data: 5
 
+
--- a/content/base/test/invalid_accesscontrol.resource
+++ b/content/base/test/invalid_accesscontrol.resource
@@ -1,5 +1,7 @@
 :this file must be enconded in utf8
 :and its Content-Type must be equal to text/event-stream
 
 event: message
-data: 1
\ No newline at end of file
+data: 1
+
+
--- a/content/base/test/somedatas.resource
+++ b/content/base/test/somedatas.resource
@@ -8,10 +8,9 @@ data:12345678912345678912345678912345678
 data:  123456789123456789123456789123456789123456789123456789123456789123456789
 :some utf-8 characteres
 data:çãá"'@`~Ý Ḿyyyy
 
 :test if the character ":"(which is used for comments) isn't misunderstood
 data:  :xxabcdefghij
 data:çãá"'@`~Ý Ḿyyyy : zz
 
-:a message dispatched because of eof
-data:1
+
--- a/content/base/test/test_bug338583.html
+++ b/content/base/test/test_bug338583.html
@@ -202,18 +202,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 // in order to test (3)
 //   a) XSite domain error test
 //   b) protocol file:// test
 //   c) protocol javascript: test
 //   d) wrong Content-Type test
 //   e) bad http response code test
 //   f) message eventsource without a data test
-//   g) eventsource with invalid NCName char in the event field test
-//   h) DNS error
+//   g) DNS error
+//   h) EventSource which last message doesn't end with an empty line. See bug 710546
 
   function doTest3(test_id) {
     gEventSourceObj3_a = new EventSource("http://example.org/tests/content/base/test/eventsource.resource");
 
     gEventSourceObj3_a.onmessage = fn_onmessage;
     gEventSourceObj3_a.hits = [];
     gEventSourceObj3_a.hits['fn_onmessage'] = 0;
 
@@ -305,40 +305,54 @@ https://bugzilla.mozilla.org/show_bug.cg
     }, parseInt(1500*stress_factor));
   }
 
   function fnInvalidNCName() {
     fnInvalidNCName.hits++;
   }
 
   function doTest3_g(test_id) {
-    gEventSourceObj3_g = new EventSource("badEventFieldName.eventsource");
+    gEventSourceObj3_g = new EventSource("http://hdfskjghsbg.jtiyoejowe.dafsgbhjab.com");
 
-    fnInvalidNCName.hits = 0;
-    gEventSourceObj3_g.addEventListener('message event', fnInvalidNCName, true);
+    gEventSourceObj3_g.onmessage = fn_onmessage;
+    gEventSourceObj3_g.hits = [];
+    gEventSourceObj3_g.hits['fn_onmessage'] = 0;
 
     setTimeout(function() {
-      ok(fnInvalidNCName.hits != 0, "Test 3.g failed");
+      ok(gEventSourceObj3_g.hits['fn_onmessage'] == 0, "Test 3.g failed");
       gEventSourceObj3_g.close();
       setTestHasFinished(test_id);
     }, parseInt(1500*stress_factor));
   }
 
+  function fnMessageListenerTest3h(e) {
+    fnMessageListenerTest3h.msg_ok = (fnMessageListenerTest3h.msg_ok && e.data == "ok");
+    fnMessageListenerTest3h.id_ok = (fnMessageListenerTest3h.msg_ok && e.lastEventId == "");
+  }
+
   function doTest3_h(test_id) {
-    gEventSourceObj3_h = new EventSource("http://hdfskjghsbg.jtiyoejowe.dafsgbhjab.com");
+    gEventSourceObj3_h = new EventSource("badMessageEvent2.eventsource");
+
+    gEventSourceObj3_h.addEventListener('message event', fnMessageListenerTest3h, true);
+    fnMessageListenerTest3h.msg_ok = true;
+    fnMessageListenerTest3h.id_ok = true;
 
     gEventSourceObj3_h.onmessage = fn_onmessage;
     gEventSourceObj3_h.hits = [];
     gEventSourceObj3_h.hits['fn_onmessage'] = 0;
 
     setTimeout(function() {
-      ok(gEventSourceObj3_h.hits['fn_onmessage'] == 0, "Test 3.h failed");
+      ok(gEventSourceObj3_h.hits['fn_onmessage'] > 1, "Test 3.h.1 failed");
+      if (gEventSourceObj3_h.hits['fn_onmessage'] > 1) {
+        ok(fnMessageListenerTest3h.msg_ok, "Test 3.h.2 failed");
+        ok(fnMessageListenerTest3h.id_ok, "Test 3.h.3 failed");
+      }
       gEventSourceObj3_h.close();
       setTestHasFinished(test_id);
-    }, parseInt(1500*stress_factor));
+    }, parseInt(3000*stress_factor));
   }
 
 // in order to test (4)
 //   a) close the object when it is in use, which is being processed and that is expected
 //      to dispatch more eventlisteners
 //   b) remove an eventlistener in use
 
   function fn_onmessage4_a(e)
@@ -539,18 +553,16 @@ https://bugzilla.mozilla.org/show_bug.cg
     gEventSourceObj6 = new EventSource("somedatas.resource");
     var fn_somedata = function(e) {
       if (fn_somedata.expected == 0) {
         ok(e.data == "123456789\n123456789123456789\n123456789123456789123456789123456789\n 123456789123456789123456789123456789123456789123456789123456789123456789\nçãá\"\'@`~Ý Ḿyyyy",
           "Test 6.a failed");
       } else if (fn_somedata.expected == 1) {
         ok(e.data == " :xxabcdefghij\nçãá\"\'@`~Ý Ḿyyyy : zz",
           "Test 6.b failed");
-      } else if (fn_somedata.expected == 2) {
-        ok(e.data == "1", "Test 6.c failed");
         gEventSourceObj6.close();
       } else {
         ok(false, "Test 6 failed (unexpected message event)");
       }
       fn_somedata.expected++;
     }
     fn_somedata.expected = 0;
     gEventSourceObj6.onmessage = fn_somedata;
new file mode 100644
--- /dev/null
+++ b/content/defs.mk
@@ -0,0 +1,5 @@
+ifeq ($(OS_TARGET),WINNT)
+ifneq (,$(filter nightly,$(MOZ_UPDATE_CHANNEL)))
+NO_PROFILE_GUIDED_OPTIMIZE := 1 # Don't PGO
+endif
+endif
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -744,16 +744,17 @@ nsEventListenerManager::CompileEventHand
 
   nsresult result = NS_OK;
 
   nsIJSEventListener *listener = aListenerStruct->GetJSListener();
   NS_ASSERTION(!listener->GetHandler().HasEventHandler(),
                "What is there to compile?");
 
   nsIScriptContext *context = listener->GetEventContext();
+  JSContext *cx = context->GetNativeContext();
   nsScriptObjectHolder<JSObject> handler(context);
 
   nsCOMPtr<nsPIDOMWindow> win; // Will end up non-null if mTarget is a window
 
   if (aListenerStruct->mHandlerIsString) {
     // OK, we didn't find an existing compiled event handler.  Flag us
     // as not a string so we don't keep trying to compile strings
     // which can't be compiled
@@ -812,44 +813,46 @@ nsEventListenerManager::CompileEventHand
       nsIURI *uri = doc->GetDocumentURI();
       if (uri) {
         uri->GetSpec(url);
         lineNo = 1;
       }
     }
 
     nsCxPusher pusher;
-    if (aNeedsCxPush && !pusher.Push(context->GetNativeContext())) {
+    if (aNeedsCxPush && !pusher.Push(cx)) {
       return NS_ERROR_FAILURE;
     }
 
     uint32_t argCount;
     const char **argNames;
     // If no content, then just use kNameSpaceID_None for the
     // namespace ID.  In practice, it doesn't matter since SVG is
     // the only thing with weird arg names and SVG doesn't map event
     // listeners to the window.
     nsContentUtils::GetEventArgNames(content ?
                                        content->GetNameSpaceID() :
                                        kNameSpaceID_None,
                                      aListenerStruct->mTypeAtom,
                                      &argCount, &argNames);
 
-    result = context->CompileEventHandler(aListenerStruct->mTypeAtom,
-                                          argCount, argNames,
-                                          *body,
-                                          url.get(), lineNo,
-                                          SCRIPTVERSION_DEFAULT, // for now?
-                                          /* aIsXBL = */ false,
-                                          handler);
-    if (result == NS_ERROR_ILLEGAL_VALUE) {
-      NS_WARNING("Probably a syntax error in the event handler!");
-      return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA;
-    }
+    JSAutoRequest ar(cx);
+    JSAutoCompartment ac(cx, context->GetNativeGlobal());
+    JS::CompileOptions options(cx);
+    options.setFileAndLine(url.get(), lineNo)
+           .setVersion(SCRIPTVERSION_DEFAULT);
+
+    js::RootedObject rootedNull(cx, nullptr); // See bug 781070.
+    JSObject *handlerFun = nullptr;
+    result = nsJSUtils::CompileFunction(cx, rootedNull, options,
+                                        nsAtomCString(aListenerStruct->mTypeAtom),
+                                        argCount, argNames, *body, &handlerFun);
     NS_ENSURE_SUCCESS(result, result);
+    handler.set(handlerFun);
+    NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE);
   }
 
   if (handler) {
     // Bind it
     nsScriptObjectHolder<JSObject> boundHandler(context);
     context->BindCompiledEventHandler(mTarget, listener->GetEventScope(),
                                       handler.get(), boundHandler);
     if (listener->EventName() == nsGkAtoms::onerror && win) {
new file mode 100644
--- /dev/null
+++ b/content/html/content/crashtests/828472.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+<input type='date' value='2013-01-01'>
+</body>
+</html>
--- a/content/html/content/crashtests/crashtests.list
+++ b/content/html/content/crashtests/crashtests.list
@@ -39,10 +39,11 @@ load 741250.xhtml
 load 795221-1.html
 load 795221-2.html
 load 795221-3.html
 load 795221-4.html
 load 795221-5.xml
 load 798802-1.html
 load 811226.html
 load 819745.html
+pref(dom.experimental_forms,true) load 828472.html
 load 828180.html
 load 832011.html
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -2023,24 +2023,39 @@ nsGenericHTMLElement::GetURIListAttr(nsI
   return NS_OK;
 }
 
 void
 nsGenericHTMLElement::GetEnumAttr(nsIAtom* aAttr,
                                   const char* aDefault,
                                   nsAString& aResult) const
 {
+  GetEnumAttr(aAttr, aDefault, aDefault, aResult);
+}
+
+void
+nsGenericHTMLElement::GetEnumAttr(nsIAtom* aAttr,
+                                  const char* aDefaultMissing,
+                                  const char* aDefaultInvalid,
+                                  nsAString& aResult) const
+{
   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aAttr);
 
   aResult.Truncate();
 
-  if (attrVal && attrVal->Type() == nsAttrValue::eEnum) {
-    attrVal->GetEnumString(aResult, true);
-  } else if (aDefault) {
-    AppendASCIItoUTF16(nsDependentCString(aDefault), aResult);
+  if (!attrVal) {
+    if (aDefaultMissing) {
+      AppendASCIItoUTF16(nsDependentCString(aDefaultMissing), aResult);
+    }
+  } else {
+    if (attrVal->Type() == nsAttrValue::eEnum) {
+      attrVal->GetEnumString(aResult, true);
+    } else if (aDefaultInvalid) {
+      AppendASCIItoUTF16(nsDependentCString(aDefaultInvalid), aResult);
+    }
   }
 }
 
 nsHTMLMenuElement*
 nsGenericHTMLElement::GetContextMenu() const
 {
   nsAutoString value;
   GetHTMLAttr(nsGkAtoms::contextmenu, value);
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -916,16 +916,32 @@ protected:
    * @param aDefault  the default value if the attribute is missing or invalid.
    * @param aResult   string corresponding to the value [out].
    */
   NS_HIDDEN_(void) GetEnumAttr(nsIAtom* aAttr,
                                const char* aDefault,
                                nsAString& aResult) const;
 
   /**
+   * Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES.
+   * Gets the enum value string of an attribute and using the default missing
+   * value if the attribute is missing or the default invalid value if the
+   * string is an invalid enum value.
+   *
+   * @param aType            the name of the attribute.
+   * @param aDefaultMissing  the default value if the attribute is missing.
+   * @param aDefaultInvalid  the default value if the attribute is invalid.
+   * @param aResult          string corresponding to the value [out].
+   */
+  NS_HIDDEN_(void) GetEnumAttr(nsIAtom* aAttr,
+                               const char* aDefaultMissing,
+                               const char* aDefaultInvalid,
+                               nsAString& aResult) const;
+
+  /**
    * Locates the nsIEditor associated with this node.  In general this is
    * equivalent to GetEditorInternal(), but for designmode or contenteditable,
    * this may need to get an editor that's not actually on this element's
    * associated TextControlFrame.  This is used by the spellchecking routines
    * to get the editor affected by changing the spellcheck attribute on this
    * node.
    */
   virtual already_AddRefed<nsIEditor> GetAssociatedEditor();
@@ -1361,16 +1377,35 @@ protected:
   }                                                                       \
   NS_IMETHODIMP                                                           \
   _class::Set##_method(const nsAString& aValue)                           \
   {                                                                       \
     return SetAttrHelper(nsGkAtoms::_atom, aValue);                       \
   }
 
 /**
+ * A macro to implement the getter and setter for a given content
+ * property that needs to set an enumerated string that has different
+ * default values for missing and invalid values. The method uses a
+ * specific GetEnumAttr and the generic SetAttrHelper methods.
+ */
+#define NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES(_class, _method, _atom, _defaultMissing, _defaultInvalid) \
+  NS_IMETHODIMP                                                                                   \
+  _class::Get##_method(nsAString& aValue)                                                         \
+  {                                                                                               \
+    GetEnumAttr(nsGkAtoms::_atom, _defaultMissing, _defaultInvalid, aValue);                      \
+    return NS_OK;                                                                                 \
+  }                                                                                               \
+  NS_IMETHODIMP                                                                                   \
+  _class::Set##_method(const nsAString& aValue)                                                   \
+  {                                                                                               \
+    return SetAttrHelper(nsGkAtoms::_atom, aValue);                                               \
+  }
+
+/**
  * QueryInterface() implementation helper macros
  */
 
 #define NS_HTML_CONTENT_INTERFACE_TABLE_AMBIGUOUS_BEGIN(_class, _base)        \
   NS_NODE_OFFSET_AND_INTERFACE_TABLE_BEGIN(_class)                            \
     NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMNode, _base)             \
     NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMElement, _base)          \
     NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMHTMLElement, _base)
--- a/content/html/content/src/nsHTMLAudioElement.cpp
+++ b/content/html/content/src/nsHTMLAudioElement.cpp
@@ -171,24 +171,21 @@ nsHTMLAudioElement::MozWriteAudio(const 
 
   float* frames = JS_GetFloat32ArrayData(tsrc);
   // Convert the samples back to integers as we are using fixed point audio in
   // the AudioStream.
   // This could be optimized to avoid allocation and memcpy when
   // AudioDataValue is 'float', but it's not worth it for this deprecated API.
   nsAutoArrayPtr<AudioDataValue> audioData(new AudioDataValue[writeLen * mChannels]);
   ConvertAudioSamples(frames, audioData.get(), writeLen * mChannels);
-  if (!mAudioStream->IsStarted()) {
-    mAudioStream->Start();
-  }
   nsresult rv = mAudioStream->Write(audioData.get(), writeLen);
-
   if (NS_FAILED(rv)) {
     return rv;
   }
+  mAudioStream->Start();
 
   // Return the actual amount written.
   *aRetVal = writeLen * mChannels;
   return rv;
 }
 
 NS_IMETHODIMP
 nsHTMLAudioElement::MozCurrentSampleOffset(uint64_t *aRetVal)
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -31,17 +31,16 @@
 #include "nsFormSubmissionConstants.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "nsIFormControlFrame.h"
 #include "nsITextControlFrame.h"
 #include "nsIFrame.h"
 #include "nsEventStates.h"
 #include "nsIServiceManager.h"
-#include "nsIScriptSecurityManager.h"
 #include "nsError.h"
 #include "nsIEditor.h"
 #include "nsGUIEvent.h"
 #include "nsIIOService.h"
 #include "nsDocument.h"
 #include "nsAttrValueOrString.h"
 
 #include "nsPresState.h"
@@ -912,20 +911,20 @@ NS_IMPL_STRING_ATTR(nsHTMLInputElement, 
 NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, Autocomplete, autocomplete,
                                 kInputDefaultAutocomplete->tag)
 NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Autofocus, autofocus)
 //NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Checked, checked)
 NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Disabled, disabled)
 NS_IMPL_STRING_ATTR(nsHTMLInputElement, Max, max)
 NS_IMPL_STRING_ATTR(nsHTMLInputElement, Min, min)
 NS_IMPL_ACTION_ATTR(nsHTMLInputElement, FormAction, formaction)
-NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormEnctype, formenctype,
-                                kFormDefaultEnctype->tag)
-NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, FormMethod, formmethod,
-                                kFormDefaultMethod->tag)
+NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES(nsHTMLInputElement, FormEnctype, formenctype,
+                                                 "", kFormDefaultEnctype->tag)
+NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES(nsHTMLInputElement, FormMethod, formmethod,
+                                                 "", kFormDefaultMethod->tag)
 NS_IMPL_BOOL_ATTR(nsHTMLInputElement, FormNoValidate, formnovalidate)
 NS_IMPL_STRING_ATTR(nsHTMLInputElement, FormTarget, formtarget)
 NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLInputElement, Inputmode, inputmode,
                                 kInputDefaultInputmode->tag)
 NS_IMPL_BOOL_ATTR(nsHTMLInputElement, Multiple, multiple)
 NS_IMPL_NON_NEGATIVE_INT_ATTR(nsHTMLInputElement, MaxLength, maxlength)
 NS_IMPL_STRING_ATTR(nsHTMLInputElement, Name, name)
 NS_IMPL_BOOL_ATTR(nsHTMLInputElement, ReadOnly, readonly)
@@ -1079,20 +1078,18 @@ nsHTMLInputElement::ConvertStringToNumbe
         if (NS_FAILED(ec)) {
           return false;
         }
 
         return true;
       }
     case NS_FORM_INPUT_DATE:
       {
-        JSContext* ctx = nsContentUtils::GetContextFromDocument(OwnerDoc());
-        if (!ctx) {
-          return false;
-        }
+        SafeAutoJSContext ctx;
+        JSAutoRequest ar(ctx);
 
         uint32_t year, month, day;
         if (!GetValueAsDate(aValue, &year, &month, &day)) {
           return false;
         }
 
         JSObject* date = JS_NewDateObjectMsec(ctx, 0);
         if (!date) {
@@ -1239,20 +1236,18 @@ nsHTMLInputElement::ConvertNumberToStrin
   aResultString.Truncate();
 
   switch (mType) {
     case NS_FORM_INPUT_NUMBER:
       aResultString.AppendFloat(aValue);
       return true;
     case NS_FORM_INPUT_DATE:
       {
-        JSContext* ctx = nsContentUtils::GetContextFromDocument(OwnerDoc());
-        if (!ctx) {
-          return false;
-        }
+        SafeAutoJSContext ctx;
+        JSAutoRequest ar(ctx);
 
         // The specs require |aValue| to be truncated.
         aValue = floor(aValue);
 
         JSObject* date = JS_NewDateObjectMsec(ctx, aValue);
         if (!date) {
           JS_ClearPendingException(ctx);
           return false;
@@ -3188,16 +3183,21 @@ nsHTMLInputElement::ParseAttribute(int32
         newType = aResult.GetEnumValue();
         if ((newType == NS_FORM_INPUT_NUMBER ||
              newType == NS_FORM_INPUT_TIME ||
              newType == NS_FORM_INPUT_DATE) && 
             !Preferences::GetBool("dom.experimental_forms", false)) {
           newType = kInputDefaultType->value;
           aResult.SetTo(newType, &aValue);
         }
+        if (newType == NS_FORM_INPUT_FILE &&
+            Preferences::GetBool("dom.disable_input_file", false)) {
+          newType = kInputDefaultType->value;
+          aResult.SetTo(newType, &aValue);
+        }
       } else {
         newType = kInputDefaultType->value;
       }
 
       if (newType != mType) {
         // Make sure to do the check for newType being NS_FORM_INPUT_FILE and
         // the corresponding SetValueInternal() call _before_ we set mType.
         // That way the logic in SetValueInternal() will work right (that logic
--- a/content/html/content/test/forms/Makefile.in
+++ b/content/html/content/test/forms/Makefile.in
@@ -46,12 +46,13 @@ MOCHITEST_FILES = \
 		test_min_attribute.html \
 		test_step_attribute.html \
 		test_stepup_stepdown.html \
 		test_valueasnumber_attribute.html \
 		test_experimental_forms_pref.html \
 		test_input_number_value.html \
 		test_input_sanitization.html \
 		test_valueasdate_attribute.html \
+		test_input_file_b2g_disabled.html \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/content/html/content/test/forms/test_input_attributes_reflection.html
+++ b/content/html/content/test/forms/test_input_attributes_reflection.html
@@ -71,26 +71,26 @@ reflectBoolean({
 
 // .formEnctype
 reflectLimitedEnumerated({
   element: document.createElement("input"),
   attribute: "formEnctype",
   validValues: [ "application/x-www-form-urlencoded", "multipart/form-data",
                  "text/plain" ],
   invalidValues: [ "", "foo", "tulip", "multipart/foo" ],
-  defaultValue: "application/x-www-form-urlencoded"
+  defaultValue: { invalid: "application/x-www-form-urlencoded", missing: "" }
 });
 
 // .formMethod
 reflectLimitedEnumerated({
   element: document.createElement("input"),
   attribute: "formMethod",
   validValues: [ "get", "post" ],
   invalidValues: [ "", "foo", "tulip" ],
-  defaultValue: "get"
+  defaultValue: { invalid: "get", missing: "" }
 });
 
 // .formNoValidate
 reflectBoolean({
   element: document.createElement("input"),
   attribute: "formNoValidate",
 });
 
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/forms/test_input_file_b2g_disabled.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=801635
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 801635</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug 801635 **/
+  var oldPrefValue = null;
+  try {
+    oldPrefValue = SpecialPowers.getBoolPref('dom.disable_input_file');
+  } catch(e) {
+  }
+
+  var input = document.createElement('input');
+
+  SpecialPowers.setBoolPref('dom.disable_input_file', true); 
+  input.type='file';
+  is(input.type, 'text', "<input type='file'> should be disabled");
+  input.type ='text';
+
+  SpecialPowers.setBoolPref('dom.disable_input_file', false); 
+  input.type='file';
+  is(input.type, 'file', "<input type='file'> should not be disabled");
+
+  SpecialPowers.setBoolPref('dom.disable_input_file', oldPrefValue); 
+
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=801635">Disable &lt;input type='file'&gt; on B2G</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/content/html/content/test/reflect.js
+++ b/content/html/content/test/reflect.js
@@ -238,46 +238,54 @@ function reflectUnsignedInt(aParameters)
     is(element[attr], 0, "." + attr + " should be equals to 0");
   }
 }
 
 /**
  * Checks that a given attribute is correctly reflected as limited to known
  * values enumerated attribute.
  *
- * @param aParameters    Object    object containing the parameters, which are:
- *  - element            Element   node to test on
- *  - attribute          String    name of the attribute
+ * @param aParameters     Object   object containing the parameters, which are:
+ *  - element             Element  node to test on
+ *  - attribute           String   name of the attribute
  *     OR
- *    attribute          Object    object containing two attributes, 'content' and 'idl'
- *  - validValues        Array     valid values we support
- *  - invalidValues      Array     invalid values
- *  - defaultValue       String    [optional] default value when no valid value is set
- *  - unsupportedValues  Array     [optional] valid values we do not support
+ *    attribute           Object   object containing two attributes, 'content' and 'idl'
+ *  - validValues         Array    valid values we support
+ *  - invalidValues       Array    invalid values
+ *  - defaultValue        String   [optional] default value when no valid value is set
+ *     OR
+ *    defaultValue        Object   [optional] object containing two attributes, 'invalid' and 'missing'
+ *  - unsupportedValues   Array    [optional] valid values we do not support
  */
 function reflectLimitedEnumerated(aParameters)
 {
   var element = aParameters.element;
   var contentAttr = typeof aParameters.attribute === "string"
                       ? aParameters.attribute : aParameters.attribute.content;
   var idlAttr = typeof aParameters.attribute === "string"
                   ? aParameters.attribute : aParameters.attribute.idl;
   var validValues = aParameters.validValues;
   var invalidValues = aParameters.invalidValues;
   var defaultValue = aParameters.defaultValue !== undefined
                        ? aParameters.defaultValue : "";
+  var defaultValueInvalid = aParameters.defaultValue === undefined
+                               ? "" : typeof aParameters.defaultValue === "string"
+                                   ? aParameters.defaultValue : aParameters.defaultValue.invalid
+  var defaultValueMissing = aParameters.defaultValue === undefined
+                                ? "" : typeof aParameters.defaultValue === "string"
+                                    ? aParameters.defaultValue : aParameters.defaultValue.missing
   var unsupportedValues = aParameters.unsupportedValues !== undefined
                             ? aParameters.unsupportedValues : [];
 
   ok(idlAttr in element, idlAttr + " should be an IDL attribute of this element");
   is(typeof element[idlAttr], "string", idlAttr + " IDL attribute should be a string");
 
   // Explicitly check the default value.
   element.removeAttribute(contentAttr);
-  is(element[idlAttr], defaultValue,
+  is(element[idlAttr], defaultValueMissing,
      "When no attribute is set, the value should be the default value.");
 
   // Check valid values.
   validValues.forEach(function (v) {
     element.setAttribute(contentAttr, v);
     is(element[idlAttr], v,
        v + " should be accepted as a valid value for " + idlAttr);
     is(element.getAttribute(contentAttr), v,
@@ -304,24 +312,24 @@ function reflectLimitedEnumerated(aParam
     is(element.getAttribute(contentAttr), v.toUpperCase(),
        "Content attribute should not be lower-cased.");
     element.removeAttribute(contentAttr);
   });
 
   // Check invalid values.
   invalidValues.forEach(function (v) {
     element.setAttribute(contentAttr, v);
-    is(element[idlAttr], defaultValue,
+    is(element[idlAttr], defaultValueInvalid,
        "When the content attribute is set to an invalid value, the default value should be returned.");
     is(element.getAttribute(contentAttr), v,
        "Content attribute should not have been changed.");
     element.removeAttribute(contentAttr);
 
     element[idlAttr] = v;
-    is(element[idlAttr], defaultValue,
+    is(element[idlAttr], defaultValueInvalid,
        "When the value is set to an invalid value, the default value should be returned.");
     is(element.getAttribute(contentAttr), v,
        "Content attribute should not have been changed.");
     element.removeAttribute(contentAttr);
   });
 
   // Check valid values we currently do not support.
   // Basically, it's like the checks for the valid values but with some todo's.
new file mode 100644
--- /dev/null
+++ b/content/mathml/defs.mk
@@ -0,0 +1,3 @@
+ifeq ($(OS_TARGET),WINNT)
+NO_PROFILE_GUIDED_OPTIMIZE := 1 # Don't PGO
+endif
--- a/content/media/AudioSegment.cpp
+++ b/content/media/AudioSegment.cpp
@@ -107,11 +107,12 @@ AudioSegment::WriteTo(AudioStream* aOutp
                                  aOutput->GetChannels(),
                                  buf.Elements());
     } else {
       // Assumes that a bit pattern of zeroes == 0.0f
       memset(buf.Elements(), 0, buf.Length()*sizeof(AudioDataValue));
     }
     aOutput->Write(buf.Elements(), int32_t(c.mDuration));
   }
+  aOutput->Start();
 }
 
 }
--- a/content/media/AudioStream.cpp
+++ b/content/media/AudioStream.cpp
@@ -54,18 +54,17 @@ class NativeAudioStream : public AudioSt
 
   nsresult Init(int32_t aNumChannels, int32_t aRate,
                 const dom::AudioChannelType aAudioChannelType);
   void Shutdown();
   nsresult Write(const AudioDataValue* aBuf, uint32_t aFrames);
   uint32_t Available();
   void SetVolume(double aVolume);
   void Drain();
-  nsresult Start();
-  bool IsStarted();
+  void Start();
   void Pause();
   void Resume();
   int64_t GetPosition();
   int64_t GetPositionInFrames();
   int64_t GetPositionInFramesInternal();
   bool IsPaused();
   int32_t GetMinWriteSize();
 
@@ -460,27 +459,20 @@ void NativeAudioStream::Drain()
 
   int r = sa_stream_drain(static_cast<sa_stream_t*>(mAudioHandle));
   if (r != SA_SUCCESS && r != SA_ERROR_INVALID) {
     PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("NativeAudioStream: sa_stream_drain error"));
     mInError = true;
   }
 }
 
-nsresult NativeAudioStream::Start()
+void NativeAudioStream::Start()
 {
   // Since sydneyaudio is a push API, the playback is started when enough frames
   // have been written. Hence, Start() is a noop.
-  return NS_OK;
-}
-
-bool NativeAudioStream::IsStarted()
-{
-  // See the comment for the |Start()| method.
-  return true;
 }
 
 void NativeAudioStream::Pause()
 {
   if (mInError)
     return;
   mPaused = true;
   sa_stream_pause(static_cast<sa_stream_t*>(mAudioHandle));
@@ -615,18 +607,17 @@ class BufferedAudioStream : public Audio
 
   nsresult Init(int32_t aNumChannels, int32_t aRate,
                 const dom::AudioChannelType aAudioChannelType);
   void Shutdown();
   nsresult Write(const AudioDataValue* aBuf, uint32_t aFrames);
   uint32_t Available();
   void SetVolume(double aVolume);
   void Drain();
-  nsresult Start();
-  bool IsStarted();
+  void Start();
   void Pause();
   void Resume();
   int64_t GetPosition();
   int64_t GetPositionInFrames();
   int64_t GetPositionInFramesInternal();
   bool IsPaused();
   int32_t GetMinWriteSize();
   // This method acquires the monitor and forward the call to the base
@@ -652,16 +643,18 @@ private:
 
   long GetTimeStretched(void* aBuffer, long aFrames);
 
 
   // Shared implementation of underflow adjusted position calculation.
   // Caller must own the monitor.
   int64_t GetPositionInFramesUnlocked();
 
+  void StartUnlocked();
+
   // The monitor is held to protect all access to member variables.  Write()
   // waits while mBuffer is full; DataCallback() notifies as it consumes
   // data from mBuffer.  Drain() waits while mState is DRAINING;
   // StateCallback() notifies when mState is DRAINED.
   Monitor mMonitor;
 
   // Sum of silent frames written when DataCallback requests more frames
   // than are available in mBuffer.
@@ -816,19 +809,21 @@ BufferedAudioStream::Write(const AudioDa
 
     mBuffer.AppendElements(src, available);
     src += available;
     bytesToCopy -= available;
 
     if (bytesToCopy > 0) {
       // If we are not playing, but our buffer is full, start playing to make
       // room for soon-to-be-decoded data.
-      if (!IsStarted()) {
-        MonitorAutoUnlock mon(mMonitor);
-        Start();
+      if (mState != STARTED) {
+        StartUnlocked();
+        if (mState != STARTED) {
+          return NS_ERROR_FAILURE;
+        }
       }
       mon.Wait();
     }
   }
 
   mWritten += aFrames;
 
   return NS_OK;
@@ -856,42 +851,49 @@ BufferedAudioStream::SetVolume(double aV
   mVolume = aVolume;
 }
 
 void
 BufferedAudioStream::Drain()
 {
   MonitorAutoLock mon(mMonitor);
   if (mState != STARTED) {
+    NS_ASSERTION(mBuffer.Available() == 0, "Draining with unplayed audio");
     return;
   }
   mState = DRAINING;
   while (mState == DRAINING) {
     mon.Wait();
   }
 }
 
-nsresult
+void
 BufferedAudioStream::Start()
 {
-  if (!mCubebStream) {
-    return NS_ERROR_FAILURE;
+  MonitorAutoLock mon(mMonitor);
+  StartUnlocked();
+}
+
+void
+BufferedAudioStream::StartUnlocked()
+{
+  mMonitor.AssertCurrentThreadOwns();
+  if (!mCubebStream || mState != INITIALIZED) {
+    return;
   }
   if (mState != STARTED) {
-    int r = cubeb_stream_start(mCubebStream);
-    mState = r == CUBEB_OK ? STARTED : ERRORED;
-    return mState == STARTED ? NS_OK : NS_ERROR_FAILURE;
+    int r;
+    {
+      MonitorAutoUnlock mon(mMonitor);
+      r = cubeb_stream_start(mCubebStream);
+    }
+    if (mState != ERRORED) {
+      mState = r == CUBEB_OK ? STARTED : ERRORED;
+    }
   }
-  return NS_OK;
-}
-
-bool
-BufferedAudioStream::IsStarted()
-{
-  return mState == STARTED ? true : false;
 }
 
 void
 BufferedAudioStream::Pause()
 {
   MonitorAutoLock mon(mMonitor);
   if (!mCubebStream || mState != STARTED) {
     return;
--- a/content/media/AudioStream.h
+++ b/content/media/AudioStream.h
@@ -128,20 +128,17 @@ public:
   // Set the current volume of the audio playback. This is a value from
   // 0 (meaning muted) to 1 (meaning full volume).  Thread-safe.
   virtual void SetVolume(double aVolume) = 0;
 
   // Block until buffered audio data has been consumed.
   virtual void Drain() = 0;
 
   // Start the stream.
-  virtual nsresult Start() = 0;
-
-  // Check if the stream is started.
-  virtual bool IsStarted() = 0;
+  virtual void Start() = 0;
 
   // Return the number of frames written so far in the stream. This allow the
   // caller to check if it is safe to start the stream, if needed.
   virtual int64_t GetWritten();
 
   // Pause audio playback.
   virtual void Pause() = 0;
 
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -956,18 +956,17 @@ bool MediaDecoderStateMachine::IsPlaying
 }
 
 // If we have already written enough frames to the AudioStream, start the
 // playback.
 static void
 StartAudioStreamPlaybackIfNeeded(AudioStream* aStream)
 {
   // We want to have enough data in the buffer to start the stream.
-  if (!aStream->IsStarted() &&
-      static_cast<double>(aStream->GetWritten()) / aStream->GetRate() >=
+  if (static_cast<double>(aStream->GetWritten()) / aStream->GetRate() >=
       static_cast<double>(AUDIOSTREAM_MIN_WRITE_BEFORE_START_USECS) / USECS_PER_S) {
     aStream->Start();
   }
 }
 
 static void WriteSilence(AudioStream* aStream, uint32_t aFrames)
 {
   uint32_t numSamples = aFrames * aStream->GetChannels();
@@ -1123,19 +1122,17 @@ void MediaDecoderStateMachine::AudioLoop
   {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
     if (mReader->AudioQueue().AtEndOfStream() &&
         mState != DECODER_STATE_SHUTDOWN &&
         !mStopAudioThread)
     {
       // If the media was too short to trigger the start of the audio stream,
       // start it now.
-      if (!mAudioStream->IsStarted()) {
-        mAudioStream->Start();
-      }
+      mAudioStream->Start();
       // Last frame pushed to audio hardware, wait for the audio to finish,
       // before the audio thread terminates.
       bool seeking = false;
       {
         int64_t unplayedFrames = audioDuration % minWriteFrames;
         if (minWriteFrames > 1 && unplayedFrames > 0) {
           // Sound is written by libsydneyaudio to the hardware in blocks of
           // frames of size minWriteFrames. So if the number of frames we've
--- a/content/media/VideoFrameContainer.cpp
+++ b/content/media/VideoFrameContainer.cpp
@@ -56,16 +56,17 @@ void VideoFrameContainer::SetCurrentFram
   nsRefPtr<Image> kungFuDeathGrip;
   kungFuDeathGrip = mImageContainer->LockCurrentImage();
   mImageContainer->UnlockCurrentImage();
 
   mImageContainer->SetCurrentImage(aImage);
   gfxIntSize newFrameSize = mImageContainer->GetCurrentSize();
   if (oldFrameSize != newFrameSize) {
     mImageSizeChanged = true;
+    mNeedInvalidation = true;
   }
 
   mPaintTarget = aTargetTime;
 }
 
 void VideoFrameContainer::ClearCurrentFrame()
 {
   MutexAutoLock lock(mMutex);
@@ -99,17 +100,18 @@ void VideoFrameContainer::Invalidate()
   NS_ASSERTION(NS_IsMainThread(), "Must call on main thread");
 
   if (!mNeedInvalidation) {
     return;
   }
 
   if (mImageContainer &&
       mImageContainer->IsAsync() &&
-      mImageContainer->HasCurrentImage()) {
+      mImageContainer->HasCurrentImage() &&
+      !mIntrinsicSizeChanged) {
     mNeedInvalidation = false;
   }
 
   if (!mElement) {
     // Element has been destroyed
     return;
   }
 
--- a/content/media/webaudio/AudioContext.cpp
+++ b/content/media/webaudio/AudioContext.cpp
@@ -39,17 +39,17 @@ AudioContext::AudioContext(nsIDOMWindow*
 AudioContext::~AudioContext()
 {
 }
 
 JSObject*
 AudioContext::WrapObject(JSContext* aCx, JSObject* aScope,
                          bool* aTriedToWrap)
 {
-  return mozAudioContextBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+  return AudioContextBinding::Wrap(aCx, aScope, this, aTriedToWrap);
 }
 
 /* static */ already_AddRefed<AudioContext>
 AudioContext::Constructor(nsISupports* aGlobal, ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal);
   if (!window) {
     aRv.Throw(NS_ERROR_FAILURE);
--- a/content/media/webaudio/test/test_AudioBuffer.html
+++ b/content/media/webaudio/test/test_AudioBuffer.html
@@ -7,17 +7,17 @@
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   SpecialPowers.setBoolPref("media.webaudio.enabled", true);
-  var ac = new mozAudioContext();
+  var ac = new AudioContext();
   var buffer = ac.createBuffer(2, 2048, 44100);
   SpecialPowers.gc(); // Make sure that our channels are accessible after GC
   ok(buffer, "Buffer was allocated successfully");
   is(buffer.sampleRate, 44100, "Correct sample rate");
   is(buffer.length, 2048, "Correct length");
   ok(Math.abs(buffer.duration - 2048 / 44100) < 0.0001, "Correct duration");
   is(buffer.numberOfChannels, 2, "Correct number of channels");
   for (var i = 0; i < buffer.numberOfChannels; ++i) {
--- a/content/media/webaudio/test/test_AudioContext.html
+++ b/content/media/webaudio/test/test_AudioContext.html
@@ -6,27 +6,27 @@
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
-  ok(!window.mozAudioContext, "mozAudioContext should be hidden behind a pref");
+  ok(!window.AudioContext, "AudioContext should be hidden behind a pref");
   var accessThrows = false;
   try {
-    new mozAudioContext();
+    new AudioContext();
   } catch (e) {
     accessThrows = true;
   }
-  ok(accessThrows, "mozAudioContext should be hidden behind a pref");
+  ok(accessThrows, "AudioContext should be hidden behind a pref");
   SpecialPowers.setBoolPref("media.webaudio.enabled", true);
-  var ac = new mozAudioContext();
-  ok(ac, "Create a mozAudioContext object");
+  var ac = new AudioContext();
+  ok(ac, "Create a AudioContext object");
   is(ac.sampleRate, 44100, "Correct sample rate");
   SpecialPowers.clearUserPref("media.webaudio.enabled");
   SimpleTest.finish();
 });
 
 </script>
 </pre>
 </body>
--- a/content/media/webaudio/test/test_AudioListener.html
+++ b/content/media/webaudio/test/test_AudioListener.html
@@ -7,17 +7,17 @@
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   SpecialPowers.setBoolPref("media.webaudio.enabled", true);
-  var context = new mozAudioContext();
+  var context = new AudioContext();
   ok("listener" in context, "AudioContext.listener should exist");
   ok(Math.abs(context.listener.dopplerFactor - 1.0) < 1e-4, "Correct default doppler factor");
   ok(Math.abs(context.listener.speedOfSound - 343.3) < 1e-4, "Correct default speed of sound value");
   context.listener.dopplerFactor = 0.5;
   ok(Math.abs(context.listener.dopplerFactor - 0.5) < 1e-4, "The doppler factor value can be changed");
   context.listener.speedOfSound = 400;
   ok(Math.abs(context.listener.speedOfSound - 400) < 1e-4, "The speed of sound can be changed");
   // The values set by the following cannot be read from script, but the
--- a/content/media/webaudio/test/test_badConnect.html
+++ b/content/media/webaudio/test/test_badConnect.html
@@ -9,18 +9,18 @@
 <pre id="test">
 <script src="webaudio.js" type="text/javascript"></script>
 <script class="testbody" type="text/javascript">
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   SpecialPowers.setBoolPref("media.webaudio.enabled", true);
 
-  var context1 = new mozAudioContext();
-  var context2 = new mozAudioContext();
+  var context1 = new AudioContext();
+  var context2 = new AudioContext();
 
   var destination1 = context1.destination;
   var destination2 = context2.destination;
 
   isnot(destination1, destination2, "Destination nodes should not be the same");
   isnot(destination1.context, destination2.context, "Destination nodes should not have the same context");
 
   var source1 = context1.createBufferSource();
--- a/content/media/webaudio/test/test_biquadFilterNode.html
+++ b/content/media/webaudio/test/test_biquadFilterNode.html
@@ -13,17 +13,17 @@
 function near(a, b, msg) {
   ok(Math.abs(a - b) < 1e-3, msg);
 }
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   SpecialPowers.setBoolPref("media.webaudio.enabled", true);
 
-  var context = new mozAudioContext();
+  var context = new AudioContext();
   var buffer = context.createBuffer(1, 2048, 44100);
   for (var i = 0; i < 2048; ++i) {
     buffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * i / 44100);
   }
 
   var destination = context.destination;
 
   var source = context.createBufferSource();
--- a/content/media/webaudio/test/test_bug808374.html
+++ b/content/media/webaudio/test/test_bug808374.html
@@ -5,16 +5,16 @@
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 SpecialPowers.setBoolPref("media.webaudio.enabled", true);
-mozAudioContext().createBuffer(0, 0, 0);
+AudioContext().createBuffer(0, 0, 0);
 ok(true, "The test should not crash during CC");
 SpecialPowers.clearUserPref("media.webaudio.enabled");
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/webaudio/test/test_bug827541.html
+++ b/content/media/webaudio/test/test_bug827541.html
@@ -8,18 +8,18 @@
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
   SpecialPowers.setBoolPref("media.webaudio.enabled", true);
 
   var iframe = document.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
   document.body.appendChild(iframe);
   var frameWin = iframe.contentWindow;
-  frameWin.mozAudioContext();
+  frameWin.AudioContext();
   document.body.removeChild(iframe);
-  frameWin.mozAudioContext();
+  frameWin.AudioContext();
 
   ok(true, "This test should not leak");
   SpecialPowers.clearUserPref("media.webaudio.enabled");
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/webaudio/test/test_delayNode.html
+++ b/content/media/webaudio/test/test_delayNode.html
@@ -9,17 +9,17 @@
 <pre id="test">
 <script src="webaudio.js" type="text/javascript"></script>
 <script class="testbody" type="text/javascript">
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   SpecialPowers.setBoolPref("media.webaudio.enabled", true);
 
-  var context = new mozAudioContext();
+  var context = new AudioContext();
   var buffer = context.createBuffer(1, 2048, 44100);
   for (var i = 0; i < 2048; ++i) {
     buffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * i / 44100);
   }
 
   var destination = context.destination;
 
   var source = context.createBufferSource();
--- a/content/media/webaudio/test/test_dynamicsCompressorNode.html
+++ b/content/media/webaudio/test/test_dynamicsCompressorNode.html
@@ -12,17 +12,17 @@
 function near(a, b, msg) {
   ok(Math.abs(a - b) < 1e-4, msg);
 }
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   SpecialPowers.setBoolPref("media.webaudio.enabled", true);
 
-  var context = new mozAudioContext();
+  var context = new AudioContext();
   var buffer = context.createBuffer(1, 2048, 44100);
   for (var i = 0; i < 2048; ++i) {
     buffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * i / 44100);
   }
 
   var destination = context.destination;
 
   var source = context.createBufferSource();
--- a/content/media/webaudio/test/test_gainNode.html
+++ b/content/media/webaudio/test/test_gainNode.html
@@ -8,17 +8,17 @@
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   SpecialPowers.setBoolPref("media.webaudio.enabled", true);
 
-  var context = new mozAudioContext();
+  var context = new AudioContext();
   var buffer = context.createBuffer(1, 2048, 44100);
   for (var i = 0; i < 2048; ++i) {
     buffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * i / 44100);
   }
 
   var destination = context.destination;
 
   var source = context.createBufferSource();
--- a/content/media/webaudio/test/test_pannerNode.html
+++ b/content/media/webaudio/test/test_pannerNode.html
@@ -12,17 +12,17 @@
 function near(a, b, msg) {
   ok(Math.abs(a - b) < 1e-4, msg);
 }
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   SpecialPowers.setBoolPref("media.webaudio.enabled", true);
 
-  var context = new mozAudioContext();
+  var context = new AudioContext();
   var buffer = context.createBuffer(1, 2048, 44100);
   for (var i = 0; i < 2048; ++i) {
     buffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * i / 44100);
   }
 
   var destination = context.destination;
 
   var source = context.createBufferSource();
--- a/content/media/webaudio/test/test_singleSourceDest.html
+++ b/content/media/webaudio/test/test_singleSourceDest.html
@@ -8,17 +8,17 @@
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 SimpleTest.waitForExplicitFinish();
 addLoadEvent(function() {
   SpecialPowers.setBoolPref("media.webaudio.enabled", true);
 
-  var context = new mozAudioContext();
+  var context = new AudioContext();
   var buffer = context.createBuffer(1, 2048, 44100);
   for (var i = 0; i < 2048; ++i) {
     buffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * i / 44100);
   }
 
   var destination = context.destination;
   is(destination.context, context, "Destination node has proper context");
   is(destination.context, context, "Destination node has proper context");
--- a/content/media/wmf/WMFDecoder.cpp
+++ b/content/media/wmf/WMFDecoder.cpp
@@ -95,21 +95,21 @@ bool IsWindows7OrLater()
     return false;
   }
   // Note: Win Vista = 6.0
   //       Win 7     = 6.1
   //       Win 8     = 6.2
   return versionInfo.dwMajorVersion > 6 ||
         (versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1);
 }
-
+
 /* static */
 bool
 WMFDecoder::IsEnabled()
 {
-  // We only use WMF on Windows 7 and up, until we can properly test Vista
-  // and how it responds with and without the Platform Update installed.
-  return IsWindows7OrLater() &&
+  // We only use WMF on Windows 7 and up, until we can properly test Vista
+  // and how it responds with and without the Platform Update installed.
+  return IsWindows7OrLater() &&
          Preferences::GetBool("media.windows-media-foundation.enabled");
 }
 
 } // namespace mozilla
 
--- a/content/media/wmf/WMFReader.cpp
+++ b/content/media/wmf/WMFReader.cpp
@@ -29,17 +29,16 @@ extern PRLogModuleInfo* gMediaDecoderLog
 //#define LOG_SAMPLE_DECODE 1
 
 WMFReader::WMFReader(MediaDecoder* aDecoder)
   : MediaDecoderReader(aDecoder),
     mSourceReader(nullptr),
     mAudioChannels(0),
     mAudioBytesPerSample(0),
     mAudioRate(0),
-    mVideoWidth(0),
     mVideoHeight(0),
     mVideoStride(0),
     mHasAudio(false),
     mHasVideo(false),
     mCanSeek(false)
 {
   NS_ASSERTION(NS_IsMainThread(), "Must be on main thread.");
   MOZ_COUNT_CTOR(WMFReader);
@@ -229,16 +228,123 @@ GetDefaultStride(IMFMediaType *aType, ui
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   hr = wmf::MFGetStrideForBitmapInfoHeader(subtype.Data1, width, (LONG*)(aOutStride));
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   return hr;
 }
 
+static int32_t
+MFOffsetToInt32(const MFOffset& aOffset)
+{
+  return int32_t(aOffset.value + (aOffset.fract / 65536.0f));
+}
+
+// Gets the sub-region of the video frame that should be displayed.
+// See: http://msdn.microsoft.com/en-us/library/windows/desktop/bb530115(v=vs.85).aspx
+static HRESULT
+GetPictureRegion(IMFMediaType* aMediaType, nsIntRect& aOutPictureRegion)
+{
+  // Determine if "pan and scan" is enabled for this media. If it is, we
+  // only display a region of the video frame, not the entire frame.
+  BOOL panScan = MFGetAttributeUINT32(aMediaType, MF_MT_PAN_SCAN_ENABLED, FALSE);
+
+  // If pan and scan mode is enabled. Try to get the display region.
+  HRESULT hr = E_FAIL;
+  MFVideoArea videoArea;
+  memset(&videoArea, 0, sizeof(MFVideoArea));
+  if (panScan) {
+    hr = aMediaType->GetBlob(MF_MT_PAN_SCAN_APERTURE,
+                             (UINT8*)&videoArea,
+                             sizeof(MFVideoArea),
+                             NULL);
+  }
+
+  // If we're not in pan-and-scan mode, or the pan-and-scan region is not set,
+  // check for a minimimum display aperture.
+  if (!panScan || hr == MF_E_ATTRIBUTENOTFOUND) {
+    hr = aMediaType->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE,
+                             (UINT8*)&videoArea,
+                             sizeof(MFVideoArea),
+                             NULL);
+  }
+
+  if (hr == MF_E_ATTRIBUTENOTFOUND) {
+    // Minimum display aperture is not set, for "backward compatibility with
+    // some components", check for a geometric aperture.
+    hr = aMediaType->GetBlob(MF_MT_GEOMETRIC_APERTURE,
+                             (UINT8*)&videoArea,
+                             sizeof(MFVideoArea),
+                             NULL);
+  }
+
+  if (SUCCEEDED(hr)) {
+    // The media specified a picture region, return it.
+    aOutPictureRegion = nsIntRect(MFOffsetToInt32(videoArea.OffsetX),
+                                  MFOffsetToInt32(videoArea.OffsetY),
+                                  videoArea.Area.cx,
+                                  videoArea.Area.cy);
+    return S_OK;
+  }
+
+  // No picture region defined, fall back to using the entire video area.
+  UINT32 width = 0, height = 0;
+  hr = MFGetAttributeSize(aMediaType, MF_MT_FRAME_SIZE, &width, &height);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+  aOutPictureRegion = nsIntRect(0, 0, width, height);
+  return S_OK;
+}
+
+HRESULT
+WMFReader::ConfigureVideoFrameGeometry(IMFMediaType* aMediaType)
+{
+  NS_ENSURE_TRUE(aMediaType != nullptr, E_POINTER);
+
+  nsIntRect pictureRegion;
+  HRESULT hr = GetPictureRegion(aMediaType, pictureRegion);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+
+  UINT32 width = 0, height = 0;
+  hr = MFGetAttributeSize(aMediaType, MF_MT_FRAME_SIZE, &width, &height);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+
+  uint32_t aspectNum = 0, aspectDenom = 0;
+  hr = MFGetAttributeRatio(aMediaType,
+                           MF_MT_PIXEL_ASPECT_RATIO,
+                           &aspectNum,
+                           &aspectDenom);
+  NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
+
+  // Calculate and validate the picture region and frame dimensions after
+  // scaling by the pixel aspect ratio.
+  nsIntSize frameSize = nsIntSize(width, height);
+  nsIntSize displaySize = nsIntSize(pictureRegion.width, pictureRegion.height);
+  ScaleDisplayByAspectRatio(displaySize, float(aspectNum) / float(aspectDenom));
+  if (!VideoInfo::ValidateVideoRegion(frameSize, pictureRegion, displaySize)) {
+    // Video track's frame sizes will overflow. Ignore the video track.
+    return E_FAIL;
+  }
+
+  // Success! Save state.
+  mInfo.mDisplay = displaySize;
+  GetDefaultStride(aMediaType, &mVideoStride);
+  mVideoHeight = height;
+  mPictureRegion = pictureRegion;
+
+  LOG("WMFReader frame geometry frame=(%u,%u) stride=%u picture=(%d, %d, %d, %d) display=(%d,%d) PAR=%d:%d",
+      width, height,
+      mVideoStride,
+      mPictureRegion.x, mPictureRegion.y, mPictureRegion.width, mPictureRegion.height,
+      displaySize.width, displaySize.height,
+      aspectNum, aspectDenom);
+
+  return S_OK;
+}
+
 void
 WMFReader::ConfigureVideoDecoder()
 {
   NS_ASSERTION(mSourceReader, "Must have a SourceReader before configuring decoders!");
 
   // Determine if we have video.
   if (!mSourceReader ||
       !SourceReaderHasStream(mSourceReader, MF_SOURCE_READER_FIRST_VIDEO_STREAM)) {
@@ -261,44 +367,20 @@ WMFReader::ConfigureVideoDecoder()
   RefPtr<IMFMediaType> mediaType;
   hr = mSourceReader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM,
                                           byRef(mediaType));
   if (FAILED(hr)) {
     NS_WARNING("Failed to get configured video media type");
     return;
   }
 
-  if (FAILED(MFGetAttributeSize(mediaType, MF_MT_FRAME_SIZE, &mVideoWidth, &mVideoHeight))) {
-    NS_WARNING("WMF video decoder failed to get frame dimensions!");
-    return;
-  }
-
-  LOG("Video frame %u x %u", mVideoWidth, mVideoHeight);
-  uint32_t aspectNum = 0, aspectDenom = 0;
-  if (FAILED(MFGetAttributeRatio(mediaType,
-                                 MF_MT_PIXEL_ASPECT_RATIO,
-                                 &aspectNum,
-                                 &aspectDenom))) {
-    NS_WARNING("WMF video decoder failed to get pixel aspect ratio!");
+  if (FAILED(ConfigureVideoFrameGeometry(mediaType))) {
+    NS_WARNING("Failed configured video frame dimensions");
     return;
   }
-  LOG("Video aspect ratio %u x %u", aspectNum, aspectDenom);
-
-  GetDefaultStride(mediaType, &mVideoStride);
-
-  // Calculate and validate the frame size.
-  nsIntSize frameSize = nsIntSize(mVideoWidth, mVideoHeight);
-  nsIntRect pictureRegion = nsIntRect(0, 0, mVideoWidth, mVideoHeight);
-  nsIntSize displaySize = frameSize;
-  ScaleDisplayByAspectRatio(displaySize, float(aspectNum)/float(aspectDenom));
-  if (!VideoInfo::ValidateVideoRegion(frameSize, pictureRegion, displaySize)) {
-    // Video track's frame sizes will overflow. Ignore the video track.
-    return;
-  }
-  mInfo.mDisplay = displaySize;
 
   LOG("Successfully configured video stream");
 
   mHasVideo = mInfo.mHasVideo = true;
 }
 
 void
 WMFReader::ConfigureAudioDecoder()
@@ -401,17 +483,20 @@ WMFReader::DecodeAudioData()
                                  0, // control flags
                                  nullptr, // read stream index
                                  &flags,
                                  &timestampHns,
                                  byRef(sample));
 
   if (FAILED(hr) ||
       (flags & MF_SOURCE_READERF_ERROR) ||
-      (flags & MF_SOURCE_READERF_ENDOFSTREAM)) {
+      (flags & MF_SOURCE_READERF_ENDOFSTREAM) ||
+      (flags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED)) {
+    LOG("WMFReader::DecodeAudioData() ReadSample failed with hr=0x%x flags=0x%x",
+        hr, flags);
     // End of stream.
     mAudioQueue.Finish();
     return false;
   }
 
   RefPtr<IMFMediaBuffer> buffer;
   hr = sample->ConvertToContiguousBuffer(byRef(buffer));
   NS_ENSURE_TRUE(SUCCEEDED(hr), false);
@@ -486,16 +571,29 @@ WMFReader::DecodeVideoFrame(bool &aKeyfr
       // End of stream.
       mVideoQueue.Finish();
       return false;
     }
     LOG("WMFReader; Null sample after video decode. Maybe insufficient data...");
     return true;
   }
 
+  if ((flags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED)) {
+    LOG("WMFReader: Video media type changed!");
+    RefPtr<IMFMediaType> mediaType;
+    hr = mSourceReader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM,
+                                            byRef(mediaType));
+    if (FAILED(hr) ||
+        FAILED(ConfigureVideoFrameGeometry(mediaType))) {
+      NS_WARNING("Failed to reconfigure video media type");
+      mVideoQueue.Finish();
+      return false;
+    }
+  }
+
   int64_t timestamp = HNsToUsecs(timestampHns);
   if (timestamp < aTimeThreshold) {
     return true;
   }
   int64_t offset = mDecoder->GetResource()->Tell();
   int64_t duration = GetSampleDuration(sample);
 
   RefPtr<IMFMediaBuffer> buffer;
@@ -565,34 +663,34 @@ WMFReader::DecodeVideoFrame(bool &aKeyfr
   VideoData *v = VideoData::Create(mInfo,
                                    mDecoder->GetImageContainer(),
                                    offset,
                                    timestamp,
                                    timestamp + duration,
                                    b,
                                    false,
                                    -1,
-                                   nsIntRect(0, 0, mVideoWidth, mVideoHeight));
+                                   mPictureRegion);
   if (twoDBuffer) {
     twoDBuffer->Unlock2D();
   } else {
     buffer->Unlock();
   }
 
   if (!v) {
     NS_WARNING("Failed to create VideoData");
     return false;
   }
   parsed++;
   decoded++;
   mVideoQueue.Push(v);
 
   #ifdef LOG_SAMPLE_DECODE
-  LOG("Decoded video sample timestamp=%lld duration=%lld stride=%d width=%u height=%u flags=%u",
-      timestamp, duration, stride, mVideoWidth, mVideoHeight, flags);
+  LOG("Decoded video sample timestamp=%lld duration=%lld stride=%d height=%u flags=%u",
+      timestamp, duration, stride, mVideoHeight, flags);
   #endif
 
   if ((flags & MF_SOURCE_READERF_ENDOFSTREAM)) {
     // End of stream.
     mVideoQueue.Finish();
     LOG("End of video stream");
     return false;
   }
--- a/content/media/wmf/WMFReader.h
+++ b/content/media/wmf/WMFReader.h
@@ -44,25 +44,29 @@ public:
 
   void OnDecodeThreadStart() MOZ_OVERRIDE;
   void OnDecodeThreadFinish() MOZ_OVERRIDE;
 
 private:
 
   void ConfigureAudioDecoder();
   void ConfigureVideoDecoder();
+  HRESULT ConfigureVideoFrameGeometry(IMFMediaType* aMediaType);
 
   RefPtr<IMFSourceReader> mSourceReader;
   RefPtr<WMFByteStream> mByteStream;
 
+  // Region inside the video frame that makes up the picture. Pixels outside
+  // of this region should not be rendered.
+  nsIntRect mPictureRegion;
+
   uint32_t mAudioChannels;
   uint32_t mAudioBytesPerSample;
   uint32_t mAudioRate;
 
-  uint32_t mVideoWidth;
   uint32_t mVideoHeight;
   uint32_t mVideoStride;
 
   bool mHasAudio;
   bool mHasVideo;
   bool mCanSeek;
 };
 
new file mode 100644
--- /dev/null
+++ b/content/smil/defs.mk
@@ -0,0 +1,3 @@
+ifeq ($(OS_TARGET),WINNT)
+NO_PROFILE_GUIDED_OPTIMIZE := 1 # Don't PGO
+endif
new file mode 100644
--- /dev/null
+++ b/content/svg/defs.mk
@@ -0,0 +1,3 @@
+ifeq ($(OS_TARGET),WINNT)
+NO_PROFILE_GUIDED_OPTIMIZE := 1 # Don't PGO
+endif
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp
+++ b/content/xbl/src/nsXBLPrototypeHandler.cpp
@@ -39,16 +39,17 @@
 #include "nsIXPConnect.h"
 #include "nsIDOMScriptObjectFactory.h"
 #include "nsDOMCID.h"
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
 #include "nsXBLEventHandler.h"
 #include "nsXBLSerialize.h"
 #include "nsEventDispatcher.h"
+#include "nsJSUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/EventHandlerBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
                      NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
@@ -344,24 +345,33 @@ nsXBLPrototypeHandler::EnsureEventHandle
 
   nsAutoCString bindingURI;
   mPrototypeBinding->DocURI()->GetSpec(bindingURI);
 
   uint32_t argCount;
   const char **argNames;
   nsContentUtils::GetEventArgNames(kNameSpaceID_XBL, aName, &argCount,
                                    &argNames);
-  nsresult rv = aBoundContext->CompileEventHandler(aName, argCount, argNames,
-                                                   handlerText,
-                                                   bindingURI.get(), 
-                                                   mLineNumber,
-                                                   JSVERSION_LATEST,
-                                                   /* aIsXBL = */ true,
-                                                   aHandler);
+
+  JSContext* cx = aBoundContext->GetNativeContext();
+  JSAutoRequest ar(cx);
+  JSAutoCompartment ac(cx, aGlobal->GetGlobalJSObject());
+  JS::CompileOptions options(cx);
+  options.setFileAndLine(bindingURI.get(), mLineNumber)
+         .setVersion(JSVERSION_LATEST)
+         .setUserBit(true); // Flag us as XBL
+
+  js::RootedObject rootedNull(cx, nullptr); // See bug 781070.
+  JSObject* handlerFun = nullptr;
+  nsresult rv = nsJSUtils::CompileFunction(cx, rootedNull, options,
+                                           nsAtomCString(aName), argCount,
+                                           argNames, handlerText, &handlerFun);
   NS_ENSURE_SUCCESS(rv, rv);
+  aHandler.set(handlerFun);
+  NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE);
 
   if (pWindow) {
     pWindow->CacheXBLPrototypeHandler(this, aHandler);
   }
 
   return NS_OK;
 }
 
new file mode 100644
--- /dev/null
+++ b/content/xslt/defs.mk
@@ -0,0 +1,3 @@
+ifeq ($(OS_TARGET),WINNT)
+NO_PROFILE_GUIDED_OPTIMIZE := 1 # Don't PGO
+endif
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -217,23 +217,16 @@ using namespace mozilla::dom;
 static int32_t gNumberOfDocumentsLoading = 0;
 
 // Global count of existing docshells.
 static int32_t gDocShellCount = 0;
 
 // Global count of docshells with the private attribute set
 static uint32_t gNumberOfPrivateDocShells = 0;
 
-// Global count of private docshells which will always remain open
-#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
-static uint32_t gNumberOfAlwaysOpenPrivateDocShells = 0; // the private hidden window
-#else
-static const uint32_t gNumberOfAlwaysOpenPrivateDocShells = 0;
-#endif
-
 // Global reference to the URI fixup service.
 nsIURIFixup *nsDocShell::sURIFixup = 0;
 
 // True means we validate window targets to prevent frameset
 // spoofing. Initialize this to a non-bolean value so we know to check
 // the pref on the creation of the first docshell.
 static uint32_t gValidateOrigin = 0xffffffff;
 
@@ -688,52 +681,34 @@ ConvertLoadTypeToNavigationType(uint32_t
   }
 
   return result;
 }
 
 static nsISHEntry* GetRootSHEntry(nsISHEntry *entry);
 
 static void
-AdjustAlwaysOpenPrivateDocShellCount()
-{
-#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
-    nsCOMPtr<nsIAppShellService> appShell
-      (do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
-    bool hasHiddenPrivateWindow = false;
-    if (appShell) {
-      appShell->GetHasHiddenPrivateWindow(&hasHiddenPrivateWindow);
-    }
-    gNumberOfAlwaysOpenPrivateDocShells = hasHiddenPrivateWindow ? 1 : 0;
-#endif
-}
-
-static void
 IncreasePrivateDocShellCount()
 {
-    AdjustAlwaysOpenPrivateDocShellCount();
-
     gNumberOfPrivateDocShells++;
-    if (gNumberOfPrivateDocShells > gNumberOfAlwaysOpenPrivateDocShells + 1 ||
+    if (gNumberOfPrivateDocShells > 1 ||
         XRE_GetProcessType() != GeckoProcessType_Content) {
         return;
     }
 
     mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
     cc->SendPrivateDocShellsExist(true);
 }
 
 static void
 DecreasePrivateDocShellCount()
 {
-    AdjustAlwaysOpenPrivateDocShellCount();
-
     MOZ_ASSERT(gNumberOfPrivateDocShells > 0);
     gNumberOfPrivateDocShells--;
-    if (gNumberOfPrivateDocShells == gNumberOfAlwaysOpenPrivateDocShells)
+    if (!gNumberOfPrivateDocShells)
     {
         if (XRE_GetProcessType() == GeckoProcessType_Content) {
             mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
             cc->SendPrivateDocShellsExist(false);
             return;
         }
 
         nsCOMPtr<nsIObserverService> obsvc = mozilla::services::GetObserverService();
@@ -790,16 +765,17 @@ nsDocShell::nsDocShell():
     mURIResultedInDocument(false),
     mIsBeingDestroyed(false),
     mIsExecutingOnLoadHandler(false),
     mIsPrintingOrPP(false),
     mSavingOldViewer(false),
 #ifdef DEBUG
     mInEnsureScriptEnv(false),
 #endif
+    mAffectPrivateSessionLifetime(true),
     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!");
@@ -2064,20 +2040,22 @@ nsDocShell::SetUsePrivateBrowsing(bool a
 }
 
 NS_IMETHODIMP
 nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing)
 {
     bool changed = aUsePrivateBrowsing != mInPrivateBrowsing;
     if (changed) {
         mInPrivateBrowsing = aUsePrivateBrowsing;
-        if (aUsePrivateBrowsing) {
-            IncreasePrivateDocShellCount();
-        } else {
-            DecreasePrivateDocShellCount();
+        if (mAffectPrivateSessionLifetime) {
+            if (aUsePrivateBrowsing) {
+                IncreasePrivateDocShellCount();
+            } else {
+                DecreasePrivateDocShellCount();
+            }
         }
     }
 
     int32_t count = mChildList.Count();
     for (int32_t i = 0; i < count; ++i) {
         nsCOMPtr<nsILoadContext> shell = do_QueryInterface(ChildAt(i));
         if (shell) {
             shell->SetPrivateBrowsing(aUsePrivateBrowsing);
@@ -2095,16 +2073,46 @@ nsDocShell::SetPrivateBrowsing(bool aUse
                 obs->PrivateModeChanged(aUsePrivateBrowsing);
             }
         }
     }
     return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDocShell::SetAffectPrivateSessionLifetime(bool aAffectLifetime)
+{
+    bool change = aAffectLifetime != mAffectPrivateSessionLifetime;
+    if (change && mInPrivateBrowsing) {
+        if (aAffectLifetime) {
+            IncreasePrivateDocShellCount();
+        } else {
+            DecreasePrivateDocShellCount();
+        }
+    }
+    mAffectPrivateSessionLifetime = aAffectLifetime;
+
+    int32_t count = mChildList.Count();
+    for (int32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIDocShell> shell = do_QueryInterface(ChildAt(i));
+        if (shell) {
+            shell->SetAffectPrivateSessionLifetime(aAffectLifetime);
+        }
+    }
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::GetAffectPrivateSessionLifetime(bool* aAffectLifetime)
+{
+    *aAffectLifetime = mAffectPrivateSessionLifetime;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDocShell::AddWeakPrivacyTransitionObserver(nsIPrivacyTransitionObserver* aObserver)
 {
     nsWeakPtr weakObs = do_GetWeakReference(aObserver);
     if (!weakObs) {
         return NS_ERROR_NOT_AVAILABLE;
     }
     return mPrivacyObservers.AppendElement(weakObs) ? NS_OK : NS_ERROR_FAILURE;
 }
@@ -2828,16 +2836,18 @@ nsDocShell::SetDocLoaderParent(nsDocLoad
         if (NS_SUCCEEDED(parentAsDocShell->GetIsActive(&value)))
         {
             SetIsActive(value);
         }
         if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))) {
             value = false;
         }
         SetAllowDNSPrefetch(value);
+        value = parentAsDocShell->GetAffectPrivateSessionLifetime();
+        SetAffectPrivateSessionLifetime(value);
     }
 
     nsCOMPtr<nsILoadContext> parentAsLoadContext(do_QueryInterface(parent));
     if (parentAsLoadContext &&
         NS_SUCCEEDED(parentAsLoadContext->GetUsePrivateBrowsing(&value)))
     {
         SetPrivateBrowsing(value);
 #ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
@@ -4972,17 +4982,19 @@ nsDocShell::Destroy()
     mSecurityUI = nullptr;
 
     // Cancel any timers that were set for this docshell; this is needed
     // to break the cycle between us and the timers.
     CancelRefreshURITimers();
 
     if (mInPrivateBrowsing) {
         mInPrivateBrowsing = false;
-        DecreasePrivateDocShellCount();
+        if (mAffectPrivateSessionLifetime) {
+            DecreasePrivateDocShellCount();
+        }
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetUnscaledDevicePixelsPerCSSPixel(double *aScale)
 {
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -837,16 +837,17 @@ protected:
     // should be passed a SHEntry to save itself into.
     bool                       mSavingOldViewer;
     
     // @see nsIDocShellHistory::createdDynamically
     bool                       mDynamicallyCreated;
 #ifdef DEBUG
     bool                       mInEnsureScriptEnv;
 #endif
+    bool                       mAffectPrivateSessionLifetime;
     uint64_t                   mHistoryID;
 
     static nsIURIFixup *sURIFixup;
 
     nsRefPtr<nsDOMNavigationTiming> mTiming;
 
     // Are we a regular frame, a browser frame, or an app frame?
     FrameType mFrameType;
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -721,14 +721,16 @@ interface nsIDocShell : nsISupports
    * "allowfullscreen" attribute to the child process. Setting
    * fullscreenAllowed on docshells which aren't content boundaries throws an
    * exception.
    */
   [infallible] readonly attribute boolean fullscreenAllowed;
   
   void setFullscreenAllowed(in boolean allowed);
 
+  [noscript, infallible] attribute boolean affectPrivateSessionLifetime;
+
   /**
    * Indicates whether the UI may enable the character encoding menu. The UI
    * must disable the menu when this property is false.
    */
   [infallible] readonly attribute boolean mayEnableCharacterEncodingMenu;
 };
new file mode 100644
--- /dev/null
+++ b/docshell/defs.mk
@@ -0,0 +1,5 @@
+ifeq ($(OS_TARGET),WINNT)
+ifneq (,$(filter nightly,$(MOZ_UPDATE_CHANNEL)))
+NO_PROFILE_GUIDED_OPTIMIZE := 1 # Don't PGO
+endif
+endif
--- a/docshell/test/chrome/Makefile.in
+++ b/docshell/test/chrome/Makefile.in
@@ -89,16 +89,17 @@ MOCHITEST_CHROME_FILES =	\
 		test_bug690056.xul \
 		bug690056_window.xul \
 		test_bug311007.xul \
 		bug311007_window.xul \
 		test_principalInherit.xul \
 		test_mozFrameType.xul \
 		mozFrameType_window.xul \
 		test_bug789773.xul \
+		test_private_hidden_window.html \
     docshell_helpers.js \
     generic.html \
     $(NULL)
 
 ifneq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 MOCHITEST_CHROME_FILES += \
 		test_bug454235.xul \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/docshell/test/chrome/test_private_hidden_window.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=829383
+-->
+<head>
+  <title>Test for Bug 829383</title>
+  <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=829383">Mozilla Bug 829383</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <iframe name="target"></iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+const Ci = Components.interfaces;
+var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
+                       .getInterface(Ci.nsIWebNavigation)
+                       .QueryInterface(Ci.nsIDocShellTreeItem)
+                       .rootTreeItem
+                       .QueryInterface(Ci.nsIInterfaceRequestor)
+                       .getInterface(Ci.nsIDOMWindow);
+
+// We need to wait for the hidden window to load, but can't access
+// an event target for a regular event listener.
+var hidden = mainWindow.Services.appShell.hiddenPrivateDOMWindow;
+var tmp = setTimeout(function poll() {
+  if (hidden.location.href != "resource://gre-resources/hiddenWindow.html" ||
+      !hidden.document.body) {
+    setTimeout(poll, 100);
+    return;
+  }
+
+  var iframe = hidden.document.createElement('iframe');
+  iframe.src = 'generic.html';
+  hidden.document.body.appendChild(iframe);
+
+  var win = mainWindow.OpenBrowserWindow({private: true});
+  win.addEventListener("load", function onLoad() {
+    win.removeEventListener("load", onLoad, false);
+    win.close();
+    win = null;
+  }, false);
+}, 100);
+
+function observer(aSubject, aTopic, aData) {
+  is(aTopic, "last-pb-context-exited", "Unexpected observer topic");
+  mainWindow.Services.obs.removeObserver(observer, "last-pb-context-exited");
+  SimpleTest.finish();
+}
+mainWindow.Services.obs.addObserver(observer, "last-pb-context-exited", false);
+
+</script>
+</pre>
+</body>
+</html>
+
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -759,19 +759,17 @@ this.DOMApplicationRegistry = {
     }
 
     let msg = aMessage.data || {};
     let mm = aMessage.target;
     msg.mm = mm;
 
     switch (aMessage.name) {
       case "Webapps:Install":
-        // always ask for UI to install
         this.doInstall(msg, mm);
-        //Services.obs.notifyObservers(mm, "webapps-ask-install", JSON.stringify(msg));
         break;
       case "Webapps:GetSelf":
         this.getSelf(msg, mm);
         break;
       case "Webapps:Uninstall":
         this.uninstall(msg, mm);
         break;
       case "Webapps:Launch":
@@ -982,16 +980,17 @@ this.DOMApplicationRegistry = {
         debug("startDownload: No update manifest found at " + file.path + " " + aManifestURL);
         return;
       }
 
       let manifest = new ManifestHelper(aJSON, app.installOrigin);
       this.downloadPackage(manifest, {
           manifestURL: aManifestURL,
           origin: app.origin,
+          installOrigin: app.installOrigin,
           downloadSize: app.downloadSize
         }, isUpdate, function(aId, aManifest) {
           // Success! Keep the zip in of TmpD, we'll move it out when
           // applyDownload() will be called.
           let tmpDir = FileUtils.getDir("TmpD", ["webapps", aId], true, true);
 
           // Save the manifest in TmpD also
           let manFile = tmpDir.clone();
@@ -1506,32 +1505,39 @@ this.DOMApplicationRegistry = {
          throw Cr.NS_ERROR_NO_INTERFACE;
        }
      }
   },
 
   // Downloads the manifest and run checks, then eventually triggers the
   // installation UI.
   doInstall: function doInstall(aData, aMm) {
+    let app = aData.app;
+
     let sendError = function sendError(aError) {
       aData.error = aError;
       aMm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
       Cu.reportError("Error installing app from: " + app.installOrigin +
                      ": " + aError);
     }.bind(this);
 
+    // Disallow reinstalls from the same origin for now.
+    // See https://bugzilla.mozilla.org/show_bug.cgi?id=821288
+    if (this._appId(app.origin) !== null) {
+      sendError("REINSTALL_FORBIDDEN");
+      return;
+    }
+
     // Hosted apps can't be trusted or certified, so just check that the
     // manifest doesn't ask for those.
     function checkAppStatus(aManifest) {
       let manifestStatus = aManifest.type || "web";
       return manifestStatus === "web";
     }
 
-    let app = aData.app;
-
     let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
                 .createInstance(Ci.nsIXMLHttpRequest);
     xhr.open("GET", app.manifestURL, true);
     xhr.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
     xhr.channel.notificationCallbacks = this.createLoadContext(aData.appId,
                                                                aData.isBrowser);
     xhr.responseType = "json";
 
@@ -1577,24 +1583,32 @@ this.DOMApplicationRegistry = {
     xhr.addEventListener("error", (function() {
       sendError("NETWORK_ERROR");
     }).bind(this), false);
 
     xhr.send(null);
   },
 
   doInstallPackage: function doInstallPackage(aData, aMm) {
+    let app = aData.app;
+
     let sendError = function sendError(aError) {
       aData.error = aError;
       aMm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
       Cu.reportError("Error installing packaged app from: " +
                      app.installOrigin + ": " + aError);
     }.bind(this);
 
-    let app = aData.app;
+    // Disallow reinstalls from the same manifest URL for now.
+    // See https://bugzilla.mozilla.org/show_bug.cgi?id=821288
+    if (this.getAppLocalIdByManifestURL(app.manifestURL) !==
+        Ci.nsIScriptSecurityManager.NO_APP_ID) {
+      sendError("REINSTALL_FORBIDDEN");
+      return;
+    }
 
     let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
                 .createInstance(Ci.nsIXMLHttpRequest);
     xhr.open("GET", app.manifestURL, true);
     xhr.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
     xhr.channel.notificationCallbacks = this.createLoadContext(aData.appId,
                                                                aData.isBrowser);
     xhr.responseType = "json";
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2190,20 +2190,20 @@ nsDOMWindowUtils::StopFrameTimeRecording
 
     *paintTimes = (float*)nsMemory::Alloc(*frameCount * sizeof(float*));
     if (!*paintTimes)
       return NS_ERROR_OUT_OF_MEMORY;
 
     /* copy over the frame intervals and paint times into the arrays we just allocated */
     for (uint32_t i = 0; i < *frameCount; i++) {
       (*frameIntervals)[i] = tmpFrameIntervals[i];
-#ifndef ANDROID
+#ifndef MOZ_WIDGET_GONK
       (*paintTimes)[i] = tmpPaintTimes[i];
 #else
-      // Waiting for bug 785597 to work on android.
+      // Waiting for bug 830475 to work on B2G.
       (*paintTimes)[i] = 0;
 #endif
     }
   }
 
   return NS_OK;
 }
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -647,19 +647,22 @@ nsOuterWindowProxy::getOwnPropertyDescri
 
   return js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, desc, flags);
 }
 
 bool
 nsOuterWindowProxy::defineProperty(JSContext* cx, JSObject* proxy,
                                    jsid id, JSPropertyDescriptor* desc)
 {
-  if (nsCOMPtr<nsIDOMWindow> frame = GetSubframeWindow(cx, proxy, id)) {
-    // Don't define anything; we're done here, since the spec requires
-    // that we treat our indexed properties as readonly.
+  int32_t index = GetArrayIndexFromId(cx, id);
+  if (IsArrayIndex(index)) {
+    // Spec says to Reject whether this is a supported index or not,
+    // since we have no indexed setter or indexed creator.  That means
+    // throwing in strict mode (FIXME: Bug 828137), doing nothing in
+    // non-strict mode.
     return true;
   }
 
   return js::Wrapper::defineProperty(cx, proxy, id, desc);
 }
 
 bool
 nsOuterWindowProxy::getOwnPropertyNames(JSContext *cx, JSObject *proxy,
@@ -677,22 +680,29 @@ nsOuterWindowProxy::getOwnPropertyNames(
   return js::AppendUnique(cx, props, innerProps);
 }
 
 bool
 nsOuterWindowProxy::delete_(JSContext *cx, JSObject *proxy, jsid id,
                             bool *bp)
 {
   if (nsCOMPtr<nsIDOMWindow> frame = GetSubframeWindow(cx, proxy, id)) {
-    // Reject (which means throw if and only if strict) the set.
+    // Reject (which means throw if strict, else return false) the delete.
     // Except we don't even know whether we're strict.  See bug 803157.
     *bp = false;
     return true;
   }
 
+  int32_t index = GetArrayIndexFromId(cx, id);
+  if (IsArrayIndex(index)) {
+    // Indexed, but not supported.  Spec says return true.
+    *bp = true;
+    return true;
+  }
+
   return js::Wrapper::delete_(cx, proxy, id, bp);
 }
 
 bool
 nsOuterWindowProxy::enumerate(JSContext *cx, JSObject *proxy,
                               JS::AutoIdVector &props)
 {
   // Just our indexed stuff followed by our "normal" own property names.
@@ -750,17 +760,18 @@ nsOuterWindowProxy::get(JSContext *cx, J
 
   return js::Wrapper::get(cx, wrapper, receiver, id, vp);
 }
 
 bool
 nsOuterWindowProxy::set(JSContext *cx, JSObject *proxy, JSObject *receiver,
                         jsid id, bool strict, JS::Value *vp)
 {
-  if (nsCOMPtr<nsIDOMWindow> frame = GetSubframeWindow(cx, proxy, id)) {
+  int32_t index = GetArrayIndexFromId(cx, id);
+  if (IsArrayIndex(index)) {
     // Reject (which means throw if and only if strict) the set.
     if (strict) {
       // XXXbz This needs to throw, but see bug 828137.
     }
     return true;
   }
 
   return js::Wrapper::set(cx, proxy, receiver, id, strict, vp);
--- a/dom/base/nsIScriptContext.h
+++ b/dom/base/nsIScriptContext.h
@@ -40,18 +40,18 @@ public:
 
   virtual nsIScriptObjectPrincipal* GetObjectPrincipal() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
                               NS_ISCRIPTCONTEXTPRINCIPAL_IID)
 
 #define NS_ISCRIPTCONTEXT_IID \
-{ 0xd5358302, 0xcd6b, 0x4830, \
-    { 0x8c, 0x81, 0xfb, 0xc4, 0x31, 0x71, 0x1c, 0x11 } }
+{ 0xa2210341, 0x3123, 0x4477, \
+    { 0xb5, 0xa9, 0x91, 0x95, 0xbd, 0x77, 0xb1, 0xe6 } }
 
 /* This MUST match JSVERSION_DEFAULT.  This version stuff if we don't
    know what language we have is a little silly... */
 #define SCRIPTVERSION_DEFAULT JSVERSION_DEFAULT
 
 /**
  * It is used by the application to initialize a runtime and run scripts.
  * A script runtime would implement this interface.
@@ -117,53 +117,16 @@ public:
    *
    * @return NS_OK if the script was valid and got executed
    *
    */
   virtual nsresult ExecuteScript(JSScript* aScriptObject,
                                  JSObject* aScopeObject) = 0;
 
   /**
-   * Compile the event handler named by atom aName, with function body aBody
-   * into a function object returned if ok via aHandler.  Does NOT bind the
-   * function to anything - BindCompiledEventHandler() should be used for that
-   * purpose.  Note that this event handler is always considered 'shared' and
-   * hence is compiled without principals.  Never call the returned object
-   * directly - it must be bound (and thereby cloned, and therefore have the 
-   * correct principals) before use!
-   *
-   * If the compilation sets a pending exception on the native context, it is
-   * this method's responsibility to report said exception immediately, without
-   * relying on callers to do so.
-   *
-   *
-   * @param aName an nsIAtom pointer naming the function; it must be lowercase
-   *        and ASCII, and should not be longer than 63 chars.  This bound on
-   *        length is enforced only by assertions, so caveat caller!
-   * @param aEventName the name that the event object should be bound to
-   * @param aBody the event handler function's body
-   * @param aURL the URL or filename for error messages
-   * @param aLineNo the starting line number of the script for error messages
-   * @param aVersion the script language version to use when executing
-   * @param aHandler the out parameter in which a void pointer to the compiled
-   *        function object is stored on success
-   *
-   * @return NS_OK if the function body was valid and got compiled
-   */
-  virtual nsresult CompileEventHandler(nsIAtom* aName,
-                                       uint32_t aArgCount,
-                                       const char** aArgNames,
-                                       const nsAString& aBody,
-                                       const char* aURL,
-                                       uint32_t aLineNo,
-                                       uint32_t aVersion,
-                                       bool aIsXBL,
-                                       nsScriptObjectHolder<JSObject>& aHandler) = 0;
-
-  /**
    * Call the function object with given args and return its boolean result,
    * or true if the result isn't boolean.
    *
    * @param aTarget the event target
    * @param aScript an object telling the scope in which to call the compiled
    *        event handler function.
    * @param aHandler function object (function and static scope) to invoke.
    * @param argv array of arguments.  Note each element is assumed to
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -181,61 +181,75 @@ JSRuntime *nsJSRuntime::sRuntime;
 
 static const char kJSRuntimeServiceContractID[] =
   "@mozilla.org/js/xpc/RuntimeService;1";
 
 static PRTime sFirstCollectionTime;
 
 static bool sIsInitialized;
 static bool sDidShutdown;
-
+static bool sShuttingDown;
 static int32_t sContextCount;
 
 static PRTime sMaxScriptRunTime;
 static PRTime sMaxChromeScriptRunTime;
 
 static nsIScriptSecurityManager *sSecurityManager;
 
-// nsMemoryPressureObserver observes the memory-pressure notifications
+// nsJSEnvironmentObserver observes the memory-pressure notifications
 // and forces a garbage collection and cycle collection when it happens, if
 // the appropriate pref is set.
 
 static bool sGCOnMemoryPressure;
 
 static PRTime
 GetCollectionTimeDelta()
 {
   PRTime now = PR_Now();
   if (sFirstCollectionTime) {
     return now - sFirstCollectionTime;
   }
   sFirstCollectionTime = now;
   return 0;
 }
 
-class nsMemoryPressureObserver MOZ_FINAL : public nsIObserver
+static void
+KillTimers()
+{
+  nsJSContext::KillGCTimer();
+  nsJSContext::KillShrinkGCBuffersTimer();
+  nsJSContext::KillCCTimer();
+  nsJSContext::KillFullGCTimer();
+  nsJSContext::KillInterSliceGCTimer();
+}
+
+class nsJSEnvironmentObserver MOZ_FINAL : public nsIObserver
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 };
 
-NS_IMPL_ISUPPORTS1(nsMemoryPressureObserver, nsIObserver)
+NS_IMPL_ISUPPORTS1(nsJSEnvironmentObserver, nsIObserver)
 
 NS_IMETHODIMP
-nsMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
-                                  const PRUnichar* aData)
+nsJSEnvironmentObserver::Observe(nsISupports* aSubject, const char* aTopic,
+                                 const PRUnichar* aData)
 {
-  if (sGCOnMemoryPressure) {
+  if (sGCOnMemoryPressure && !nsCRT::strcmp(aTopic, "memory-pressure")) {
     nsJSContext::GarbageCollectNow(js::gcreason::MEM_PRESSURE,
                                    nsJSContext::NonIncrementalGC,
                                    nsJSContext::NonCompartmentGC,
                                    nsJSContext::ShrinkingGC);
     nsJSContext::CycleCollectNow();
+  } else if (!nsCRT::strcmp(aTopic, "quit-application")) {
+    sShuttingDown = true;
+    KillTimers();
   }
+
   return NS_OK;
 }
 
 class nsRootedJSValueArray {
 public:
   explicit nsRootedJSValueArray(JSContext *cx) : avr(cx, vals.Length(), vals.Elements()) {}
 
   bool SetCapacity(JSContext *cx, size_t capacity) {
@@ -1258,18 +1272,18 @@ nsJSContext::EvaluateString(const nsAStr
   nsresult rv = sSecurityManager->CanExecuteScripts(mContext, nsJSPrincipals::get(p), &ok);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(ok, NS_OK);
 
   nsJSContext::TerminationFuncHolder holder(this);
 
   // Scope the JSAutoCompartment so that it gets destroyed before we pop the
   // cx and potentially call JS_RestoreFrameChain.
+  XPCAutoRequest ar(mContext);
   {
-    XPCAutoRequest ar(mContext);
     JSAutoCompartment ac(mContext, &aScopeObject);
 
     ++mExecuteDepth;
 
     js::RootedObject rootedScope(mContext, &aScopeObject);
     ok = JS::Evaluate(mContext, rootedScope, aOptions,
                       PromiseFlatString(aScript).get(),
                       aScript.Length(), aRetValue);
@@ -1288,16 +1302,19 @@ nsJSContext::EvaluateString(const nsAStr
 
     ReportPendingException();
   }
 
   // ScriptEvaluated needs to come after we pop the stack
   pusher.Pop();
   ScriptEvaluated(true);
 
+  // Wrap the return value into whatever compartment mContext was in.
+  if (!JS_WrapValue(mContext, aRetValue))
+    return NS_ERROR_OUT_OF_MEMORY;
   return NS_OK;
 }
 
 nsIScriptObjectPrincipal*
 nsJSContext::GetObjectPrincipal()
 {
   nsCOMPtr<nsIScriptObjectPrincipal> prin = do_QueryInterface(GetGlobalObject());
   return prin;
@@ -1384,16 +1401,17 @@ nsJSContext::ExecuteScript(JSScript* aSc
   nsCOMPtr<nsIJSContextStack> stack =
            do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
   if (NS_FAILED(rv) || NS_FAILED(stack->Push(mContext))) {
     return NS_ERROR_FAILURE;
   }
 
   nsJSContext::TerminationFuncHolder holder(this);
   XPCAutoRequest ar(mContext);
+  JSAutoCompartment ac(mContext, aScopeObject);
   ++mExecuteDepth;
 
   // The result of evaluation, used only if there were no errors. This need
   // not be a GC root currently, provided we run the GC only from the
   // operation callback or from ScriptEvaluated.
   jsval val;
   if (!JS_ExecuteScript(mContext, aScopeObject, aScriptObject, &val)) {
     ReportPendingException();
@@ -1459,72 +1477,16 @@ nsJSContext::JSObjectFromInterface(nsISu
 
   *aRet = xpc_UnmarkGrayObject(JSVAL_TO_OBJECT(v));
 
   return NS_OK;
 }
 
 
 nsresult
-nsJSContext::CompileEventHandler(nsIAtom *aName,
-                                 uint32_t aArgCount,
-                                 const char** aArgNames,
-                                 const nsAString& aBody,
-                                 const char *aURL, uint32_t aLineNo,
-                                 uint32_t aVersion,
-                                 bool aIsXBL,
-                                 nsScriptObjectHolder<JSObject>& aHandler)
-{
-  NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
-
-  NS_PRECONDITION(AtomIsEventHandlerName(aName), "Bad event name");
-  NS_PRECONDITION(!::JS_IsExceptionPending(mContext),
-                  "Why are we being called with a pending exception?");
-
-  if (!sSecurityManager) {
-    NS_ERROR("Huh, we need a script security manager to compile "
-             "an event handler!");
-
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  // Don't compile if aVersion is unknown.  Since the caller is responsible for
-  // parsing the version strings, we just check it isn't JSVERSION_UNKNOWN.
-  if ((JSVersion)aVersion == JSVERSION_UNKNOWN) {
-    return NS_ERROR_ILLEGAL_VALUE;
-  }
-
-#ifdef DEBUG
-  JSContext* top = nsContentUtils::GetCurrentJSContext();
-  NS_ASSERTION(mContext == top, "Context not properly pushed!");
-#endif
-
-  // Event handlers are always shared, and must be bound before use.
-  // Therefore we don't bother compiling with principals.
-  XPCAutoRequest ar(mContext);
-
-  JS::CompileOptions options(mContext);
-  options.setVersion(JSVersion(aVersion))
-         .setFileAndLine(aURL, aLineNo)
-         .setUserBit(aIsXBL);
-  js::RootedObject empty(mContext, NULL);
-  JSFunction* fun = JS::CompileFunction(mContext, empty, options, nsAtomCString(aName).get(),
-                                        aArgCount, aArgNames,
-                                        PromiseFlatString(aBody).get(), aBody.Length());
-
-  if (!fun) {
-    ReportPendingException();
-    return NS_ERROR_ILLEGAL_VALUE;
-  }
-
-  JSObject *handler = ::JS_GetFunctionObject(fun);
-  return aHandler.set(handler);
-}
-
-nsresult
 nsJSContext::CallEventHandler(nsISupports* aTarget, JSObject* aScope,
                               JSObject* aHandler, nsIArray* aargv,
                               nsIVariant** arv)
 {
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
 
   if (!mScriptsEnabled) {
     return NS_OK;
@@ -3059,17 +3021,17 @@ nsJSContext::LoadEnd()
   sLoadingInProgress = false;
   PokeGC(js::gcreason::LOAD_END);
 }
 
 // static
 void
 nsJSContext::PokeGC(js::gcreason::Reason aReason, int aDelay)
 {
-  if (sGCTimer) {
+  if (sGCTimer || sShuttingDown) {
     // There's already a timer for GC'ing, just return
     return;
   }
 
   CallCreateInstance("@mozilla.org/timer;1", &sGCTimer);
 
   if (!sGCTimer) {
     // Failed to create timer (probably because we're in XPCOM shutdown)
@@ -3088,17 +3050,17 @@ nsJSContext::PokeGC(js::gcreason::Reason
 
   first = false;
 }
 
 // static
 void
 nsJSContext::PokeShrinkGCBuffers()
 {
-  if (sShrinkGCBuffersTimer) {
+  if (sShrinkGCBuffersTimer || sShuttingDown) {
     return;
   }
 
   CallCreateInstance("@mozilla.org/timer;1", &sShrinkGCBuffersTimer);
 
   if (!sShrinkGCBuffersTimer) {
     // Failed to create timer (probably because we're in XPCOM shutdown)
     return;
@@ -3108,17 +3070,17 @@ nsJSContext::PokeShrinkGCBuffers()
                                               NS_SHRINK_GC_BUFFERS_DELAY,
                                               nsITimer::TYPE_ONE_SHOT);
 }
 
 // static
 void
 nsJSContext::MaybePokeCC()
 {
-  if (sCCTimer || sDidShutdown) {
+  if (sCCTimer || sShuttingDown) {
     return;
   }
 
   if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
     sCCTimerFireCount = 0;
     CallCreateInstance("@mozilla.org/timer;1", &sCCTimer);
     if (!sCCTimer) {
       return;
@@ -3251,35 +3213,37 @@ DOMGCSliceCallback(JSRuntime *aRt, js::G
     nsJSContext::KillShrinkGCBuffersTimer();
   } else if (aProgress == js::GC_CYCLE_END) {
     sCCLockedOut = false;
   }
 
   // The GC has more work to do, so schedule another GC slice.
   if (aProgress == js::GC_SLICE_END) {
     nsJSContext::KillInterSliceGCTimer();
-    CallCreateInstance("@mozilla.org/timer;1", &sInterSliceGCTimer);
-    sInterSliceGCTimer->InitWithFuncCallback(InterSliceGCTimerFired,
-                                             NULL,
-                                             NS_INTERSLICE_GC_DELAY,
-                                             nsITimer::TYPE_ONE_SHOT);
+    if (!sShuttingDown) {
+      CallCreateInstance("@mozilla.org/timer;1", &sInterSliceGCTimer);
+      sInterSliceGCTimer->InitWithFuncCallback(InterSliceGCTimerFired,
+                                               NULL,
+                                               NS_INTERSLICE_GC_DELAY,
+                                               nsITimer::TYPE_ONE_SHOT);
+    }
   }
 
   if (aProgress == js::GC_CYCLE_END) {
     // May need to kill the inter-slice GC timer
     nsJSContext::KillInterSliceGCTimer();
 
     sCCollectedWaitingForGC = 0;
     sCleanupsSinceLastGC = 0;
     sNeedsFullCC = true;
     nsJSContext::MaybePokeCC();
 
     if (aDesc.isCompartment) {
       ++sCompartmentGCCount;
-      if (!sFullGCTimer) {
+      if (!sFullGCTimer && !sShuttingDown) {
         CallCreateInstance("@mozilla.org/timer;1", &sFullGCTimer);
         js::gcreason::Reason reason = js::gcreason::FULL_GC_TIMER;
         sFullGCTimer->InitWithFuncCallback(FullGCTimerFired,
                                            reinterpret_cast<void *>(reason),
                                            NS_FULL_GC_DELAY,
                                            nsITimer::TYPE_ONE_SHOT);
       }
     } else {
@@ -3395,16 +3359,17 @@ nsJSRuntime::Startup()
   sPostGCEventsToConsole = false;
   sDisableExplicitCompartmentGC = false;
   sNeedsFullCC = false;
   gNameSpaceManager = nullptr;
   sRuntimeService = nullptr;
   sRuntime = nullptr;
   sIsInitialized = false;
   sDidShutdown = false;
+  sShuttingDown = false;
   sContextCount = 0;
   sSecurityManager = nullptr;
 }
 
 static int
 MaxScriptRunTimePrefChangedCallback(const char *aPrefName, void *aClosure)
 {
   // Default limit on script run time to 10 seconds. 0 means let
@@ -3711,19 +3676,19 @@ nsJSRuntime::Init()
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (!obs)
     return NS_ERROR_FAILURE;
 
   Preferences::AddBoolVarCache(&sGCOnMemoryPressure,
                                "javascript.options.gc_on_memory_pressure",
                                true);
 
-  nsIObserver* memPressureObserver = new nsMemoryPressureObserver();
-  NS_ENSURE_TRUE(memPressureObserver, NS_ERROR_OUT_OF_MEMORY);
-  obs->AddObserver(memPressureObserver, "memory-pressure", false);
+  nsIObserver* observer = new nsJSEnvironmentObserver();
+  obs->AddObserver(observer, "memory-pressure", false);
+  obs->AddObserver(observer, "quit-application", false);
 
   sIsInitialized = true;
 
   return NS_OK;
 }
 
 //static
 nsScriptNameSpaceManager*
@@ -3742,32 +3707,29 @@ nsJSRuntime::GetNameSpaceManager()
 
   return gNameSpaceManager;
 }
 
 /* static */
 void
 nsJSRuntime::Shutdown()
 {
-  nsJSContext::KillGCTimer();
-  nsJSContext::KillShrinkGCBuffersTimer();
-  nsJSContext::KillCCTimer();
-  nsJSContext::KillFullGCTimer();
-  nsJSContext::KillInterSliceGCTimer();
+  KillTimers();
 
   NS_IF_RELEASE(gNameSpaceManager);
 
   if (!sContextCount) {
     // We're being shutdown, and there are no more contexts
     // alive, release the JS runtime service and the security manager.
 
     NS_IF_RELEASE(sRuntimeService);
     NS_IF_RELEASE(sSecurityManager);
   }
 
+  sShuttingDown = true;
   sDidShutdown = true;
 }
 
 // Script object mananagement - note duplicate implementation
 // in nsJSContext above...
 nsresult
 nsJSRuntime::HoldScriptObject(void* aScriptObject)
 {
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -56,24 +56,16 @@ public:
                                  const char *aURL,
                                  uint32_t aLineNo,
                                  uint32_t aVersion,
                                  nsScriptObjectHolder<JSScript>& aScriptObject,
                                  bool aSaveSource = false);
   virtual nsresult ExecuteScript(JSScript* aScriptObject,
                                  JSObject* aScopeObject);
 
-  virtual nsresult CompileEventHandler(nsIAtom *aName,
-                                       uint32_t aArgCount,
-                                       const char** aArgNames,
-                                       const nsAString& aBody,
-                                       const char *aURL, uint32_t aLineNo,
-                                       uint32_t aVersion,
-                                       bool aIsXBL,
-                                       nsScriptObjectHolder<JSObject>& aHandler);
   virtual nsresult CallEventHandler(nsISupports* aTarget, JSObject* aScope,
                                     JSObject* aHandler,
                                     nsIArray *argv, nsIVariant **rv);
   virtual nsresult BindCompiledEventHandler(nsISupports *aTarget,
                                             JSObject *aScope,
                                             JSObject* aHandler,
                                             nsScriptObjectHolder<JSObject>& aBoundHandler);
 
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -156,29 +156,34 @@ nsJSUtils::CompileFunction(JSContext* aC
                            uint32_t aArgCount,
                            const char** aArgArray,
                            const nsAString& aBody,
                            JSObject** aFunctionObject)
 {
   MOZ_ASSERT(js::GetEnterCompartmentDepth(aCx) > 0);
   MOZ_ASSERT_IF(aTarget, js::IsObjectInContextCompartment(aTarget, aCx));
   MOZ_ASSERT_IF(aOptions.versionSet, aOptions.version != JSVERSION_UNKNOWN);
+  mozilla::DebugOnly<nsIScriptContext*> ctx = GetScriptContextFromJSContext(aCx);
+  MOZ_ASSERT_IF(ctx, ctx->IsContextInitialized());
 
   // Since aTarget and aCx are same-compartment, there should be no distinction
   // between the object principal and the cx principal.
   // However, aTarget may be null in the wacky aShared case. So use the cx.
   JSPrincipals* p = JS_GetCompartmentPrincipals(js::GetContextCompartment(aCx));
   aOptions.setPrincipals(p);
 
   // Do the junk Gecko is supposed to do before calling into JSAPI.
   xpc_UnmarkGrayObject(aTarget);
 
   // Compile.
   JSFunction* fun = JS::CompileFunction(aCx, aTarget, aOptions,
                                         PromiseFlatCString(aName).get(),
                                         aArgCount, aArgArray,
                                         PromiseFlatString(aBody).get(),
                                         aBody.Length());
-  NS_ENSURE_TRUE(fun, NS_ERROR_FAILURE);
+  if (!fun) {
+    ReportPendingException(aCx);
+    return NS_ERROR_FAILURE;
+  }
 
   *aFunctionObject = JS_GetFunctionObject(fun);
   return NS_OK;
 }
--- a/dom/base/test/test_window_indexing.html
+++ b/dom/base/test/test_window_indexing.html
@@ -1,8 +1,9 @@
+
 <!DOCTYPE HTML>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=823228
 -->
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 823228</title>
@@ -21,23 +22,23 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript">
 
   /** Test for Bug 823228 **/
   is(window, window.frames, "These better be equal");
   ok("0" in window, "We have a subframe");
   ok("1" in window, "We have two subframes");
   ok(!("2" in window), "But we don't have three subframes");
   window[2] = "myString";
-  ok("2" in window, "Should be able to set expando");
+  ok(!("2" in window), "Should not be able to set indexed expando");
   Object.getPrototypeOf(window)[3] = "Hey there";
   ok("3" in window, "Should be walking up the proto chain");
 
   is(window[0].name, "x", "First frame is x");
   is(window[1].name, "y", "Second frame is y");
-  is(window[2], "myString", "We should still have our expando");
+  is(window[2], undefined, "We should still not have our expando");
   is(window[3], "Hey there", "We should still have our prop on the proto chain");
 
   var x = $("x");
   var y = $("y");
 
   is(x.contentWindow, window[0], "First frame should have correct window");
   is(y.contentWindow, window[1], "Second frame should have correct window");
 
@@ -52,65 +53,62 @@ https://bugzilla.mozilla.org/show_bug.cg
   x.parentNode.appendChild(y);
   Object.defineProperty(window, "1", { value: "FAIL2", configurable: true,
 				       writable: true })
   y.parentNode.removeChild(y);
   ok(!("1" in window), "We no longer have two subframes, again");
   is(window[1], undefined, "We should not have a value here either");
 
   // More set() hook test
-  window[1] = "PASS";
-  is(window[1], "PASS", "Should be able to set expando on window[1] now");
+  window[1] = "FAIL3";
+  ok(!("1" in window), "We shouldn't allow indexed expandos");
+  is(window[1], undefined, "We should not have a value for an indexed expando");
   var desc = Object.getOwnPropertyDescriptor(window, "1");
-  ok(desc.configurable, "Expando should be configurable");
-  ok(desc.enumerable, "Expando should be configurable");
-  ok(desc.writable, "Expando should be writable");
-  is(desc.value, "PASS", "Expando should have correct value");
+  is(desc, undefined, "We really really shouldn't have indexed expandos");
 
-  // Sneaky shadowing (get() hook)
   x.parentNode.appendChild(y);
-  is(window[1], y.contentWindow, "Second frame should now shadow expando");
+  is(window[1], y.contentWindow, "Second frame should now be visible");
   desc = Object.getOwnPropertyDescriptor(window, "1");
   ok(desc.configurable, "Subframe should be configurable");
   ok(desc.enumerable, "Subframe should be configurable");
   ok(!desc.writable, "Subframe should not be writable");
   is(desc.value, y.contentWindow, "Subframe should have correct value");
 
-  // And unshadowing
   y.parentNode.removeChild(y);
-  is(window[1], "PASS", "And now we should be able to see the expando again");
+  is(window[1], undefined, "And now we should be back to no [1] property");
 
   // And more defineProperty()
-  Object.defineProperty(window, "1", { value: "PASS2", configurable: true,
+  Object.defineProperty(window, "1", { value: "FAIL2", configurable: true,
 				       writable: true })
-  is(window[1], "PASS2", "Defining past end of list should work");
+  ok(!("1" in window), "Defining indexed properties really just shouldn't work");
+  is(window[1], undefined, "Defining past end of list should not work");
 
   // Enumeration tests
   x.parentNode.appendChild(y);
 
   var names = Object.getOwnPropertyNames(window);
   is(names[0], "0", "Must start with 0");
   is(names[1], "1", "Must continue with 1");
-  isnot(names.indexOf("2"), -1, "And then 2, defined earlier, should be in there");
+  is(names.indexOf("2"), -1, "And 2, an attempted expando, should not be in there");
   is(names.indexOf("3"), -1, "But no 3; that's on the proto");
 
   names = [];
   for (var name in window) {
     names.push(name);
   }
   is(names[0], "0", "Enumeration must start with 0");
   is(names[1], "1", "Enumeration must continue with 1");
-  isnot(names.indexOf("2"), -1, "Enumeration: and then 2, defined earlier");
+  is(names.indexOf("2"), -1, "Enumeration: but no expando 2");
   isnot(names.indexOf("3"), -1, "Enumeration: and then 3, defined on the proto");
   is(names.indexOf("4"), -1, "But no 4 around");
 
   // Delete tests
-  delete window[1];
+  is(delete window[1], false, "Deleting supported index should return false");
   is(window[1], y.contentWindow, "Shouldn't be able to delete a supported index");
   y.parentNode.removeChild(y);
-  is(window[1], "PASS2",
-     "And shouldn't have deleted the thing we were shadowing either");
-  delete window[1];
   is(window[1], undefined,
-     "But should be able to delete unshadowed things");
+     "And now we should have no property here");
+  is(delete window[1], true, "Deleting unsupported index should return true");
+  is(window[1], undefined,
+     "And we shouldn't have things magically appear due to delete");
   </script>
 </body>
 </html>
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -86,18 +86,17 @@
 #
 # A descriptor can also have 'skipGen': True specified if it should be skipped
 # when deciding what header includes to generate and should never have an
 # implementation generated for it.  This is only needed in special cases like
 # worker descriptors for objects that will never actually appear in workers.
 
 DOMInterfaces = {
 
-'mozAudioContext': {
-    'nativeType': 'AudioContext',
+'AudioContext': {
     'implicitJSContext': [ 'createBuffer' ],
     'nativeOwnership': 'refcounted',
     'resultNotAddRefed': [ 'destination', 'listener' ],
 },
 
 'AudioListener' : {
     'nativeOwnership': 'refcounted'
 },
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -11,16 +11,17 @@
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothScoManager.h"
 #include "BluetoothService.h"
 #include "BluetoothUtils.h"
 #include "BluetoothUuid.h"
 
 #include "MobileConnection.h"
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
+#include "mozilla/Hal.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "nsContentUtils.h"
 #include "nsIAudioManager.h"
 #include "nsIObserverService.h"
 #include "nsISettingsService.h"
 #include "nsIRadioInterfaceLayer.h"
 #include "nsRadioInterfaceLayer.h"
@@ -123,16 +124,17 @@ class mozilla::dom::bluetooth::Call {
 
     uint16_t mState;
     bool mDirection; // true: incoming call; false: outgoing call
     nsString mNumber;
     int mType;
 };
 
 class mozilla::dom::bluetooth::BluetoothHfpManagerObserver : public nsIObserver
+                                                           , public BatteryObserver
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   BluetoothHfpManagerObserver()
   {
   }
@@ -156,37 +158,53 @@ public:
       return false;
     }
 
     if (NS_FAILED(obs->AddObserver(this, MOBILE_CONNECTION_VOICE_CHANGED, false))) {
       NS_WARNING("Failed to add mobile connection voice change observer!");
       return false;
     }
 
+    hal::RegisterBatteryObserver(this);
+
     return true;
   }
 
   bool Shutdown()
   {
     nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
     if (!obs ||
         NS_FAILED(obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) ||
         NS_FAILED(obs->RemoveObserver(this, MOZSETTINGS_CHANGED_ID)) ||
         NS_FAILED(obs->RemoveObserver(this, MOBILE_CONNECTION_ICCINFO_CHANGED)) ||
         NS_FAILED(obs->RemoveObserver(this, MOBILE_CONNECTION_VOICE_CHANGED))) {
       NS_WARNING("Can't unregister observers, or already unregistered!");
       return false;
     }
+
+    hal::UnregisterBatteryObserver(this);
+
     return true;
   }
 
   ~BluetoothHfpManagerObserver()
   {
     Shutdown();
   }
+
+  void Notify(const hal::BatteryInformation& aBatteryInfo)
+  {
+    // Range of battery level: [0, 1], double
+    // Range of CIND::BATTCHG: [0, 5], int
+    int level = ceil(aBatteryInfo.level() * 5.0);
+    if (level != sCINDItems[CINDType::BATTCHG].value) {
+      sCINDItems[CINDType::BATTCHG].value = level;
+      gBluetoothHfpManager->SendCommand("+CIEV: ", CINDType::BATTCHG);
+    }
+  }
 };
 
 class BluetoothHfpManager::GetVolumeTask : public nsISettingsServiceCallback
 {
 public:
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD
@@ -595,36 +613,49 @@ BluetoothHfpManager::HandleVoiceConnecti
   }
   signal = ceil(value.toNumber() / 20.0);
 
   if (signal != sCINDItems[CINDType::SIGNAL].value) {
     sCINDItems[CINDType::SIGNAL].value = signal;
     SendCommand("+CIEV: ", CINDType::SIGNAL);
   }
 
+  /**
+   * Possible return values for mode are:
+   * - null (unknown): set mNetworkSelectionMode to 0 (auto)
+   * - automatic: set mNetworkSelectionMode to 0 (auto)
+   * - manual: set mNetworkSelectionMode to 1 (manual)
+   */
+  nsString mode;
+  connection->GetNetworkSelectionMode(mode);
+  if (mode.EqualsLiteral("manual")) {
+    mNetworkSelectionMode = 1;
+  } else {
+    mNetworkSelectionMode = 0;
+  }
+
+  nsIDOMMozMobileNetworkInfo* network;
+  voiceInfo->GetNetwork(&network);
+  NS_ENSURE_TRUE(network, NS_ERROR_FAILURE);
+  network->GetLongName(mOperatorName);
+
   return NS_OK;
 }
 
 nsresult
 BluetoothHfpManager::HandleIccInfoChanged()
 {
   nsCOMPtr<nsIMobileConnectionProvider> connection =
     do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
   NS_ENSURE_TRUE(connection, NS_ERROR_FAILURE);
 
   nsIDOMMozMobileICCInfo* iccInfo;
   connection->GetIccInfo(&iccInfo);
   NS_ENSURE_TRUE(iccInfo, NS_ERROR_FAILURE);
-
-  nsString msisdn;
-  iccInfo->GetMsisdn(msisdn);
-
-  if (!msisdn.Equals(mMsisdn)) {
-    mMsisdn = msisdn;
-  }
+  iccInfo->GetMsisdn(mMsisdn);
 
   return NS_OK;
 }
 
 nsresult
 BluetoothHfpManager::HandleShutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -684,18 +715,45 @@ BluetoothHfpManager::ReceiveSocketData(U
       NS_WARNING("Could't get the value of command [AT+CMEE=]");
       goto respond_with_ok;
     }
 
     // AT+CMEE = 0: +CME ERROR shall not be used
     // AT+CMEE = 1: use numeric <err>
     // AT+CMEE = 2: use verbose <err>
     mCMEE = !atCommandValues[0].EqualsLiteral("0");
+  } else if (msg.Find("AT+COPS=") != -1) {
+    ParseAtCommand(msg, 8, atCommandValues);
+
+    if (atCommandValues.Length() != 2) {
+      NS_WARNING("Could't get the value of command [AT+COPS=]");
+      goto respond_with_ok;
+    }
+
+    // Handsfree only support AT+COPS=3,0
+    if (!atCommandValues[0].EqualsLiteral("3") ||
+        !atCommandValues[1].EqualsLiteral("0")) {
+      if (mCMEE) {
+        SendCommand("+CME ERROR: ", BluetoothCmeError::OPERATION_NOT_SUPPORTED);
+      } else {
+        SendLine("ERROR");
+      }
+      return;
+    }
+  } else if (msg.Find("AT+COPS?") != -1) {
+    nsAutoCString message("+COPS: ");
+    message.AppendInt(mNetworkSelectionMode);
+    message += ",0,\"";
+    message += NS_ConvertUTF16toUTF8(mOperatorName);
+    message += "\"";
+    SendLine(message.get());
+    return;
   } else if (msg.Find("AT+VTS=") != -1) {
     ParseAtCommand(msg, 7, atCommandValues);
+
     if (atCommandValues.Length() != 1) {
       NS_WARNING("Couldn't get the value of command [AT+VTS=]");
       goto respond_with_ok;
     }
 
     if (IsValidDtmf(atCommandValues[0].get()[0])) {
       nsAutoCString message("VTS=");
       message += atCommandValues[0].get()[0];
--- a/dom/bluetooth/BluetoothHfpManager.h
+++ b/dom/bluetooth/BluetoothHfpManager.h
@@ -94,19 +94,21 @@ private:
 
   int mCurrentVgs;
   int mCurrentVgm;
   uint32_t mCurrentCallIndex;
   bool mCCWA;
   bool mCLIP;
   bool mCMEE;
   bool mCMER;
+  int mNetworkSelectionMode;
   bool mReceiveVgsFlag;
   nsString mDevicePath;
   nsString mMsisdn;
+  nsString mOperatorName;
   enum mozilla::ipc::SocketConnectionStatus mSocketStatus;
 
   nsTArray<Call> mCurrentCallArray;
   nsAutoPtr<BluetoothRilListener> mListener;
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
 };
 
 END_BLUETOOTH_NAMESPACE
--- a/dom/camera/CameraControlImpl.cpp
+++ b/dom/camera/CameraControlImpl.cpp
@@ -328,33 +328,33 @@ CameraControlImpl::AutoFocus(nsICameraAu
     cancel = true;
   }
 
   nsCOMPtr<nsIRunnable> autoFocusTask = new AutoFocusTask(this, cancel, onSuccess, onError);
   return mCameraThread->Dispatch(autoFocusTask, NS_DISPATCH_NORMAL);
 }
 
 nsresult
-CameraControlImpl::TakePicture(CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, CameraPosition aPosition, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError)
+CameraControlImpl::TakePicture(CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, CameraPosition aPosition, uint64_t aDateTime, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError)
 {
   MOZ_ASSERT(NS_IsMainThread());
   bool cancel = false;
 
   nsCOMPtr<nsICameraTakePictureCallback> cb = mTakePictureOnSuccessCb.get();
   if (cb) {
     /**
      * We already have a callback, so someone has already
      * called takePicture() -- cancel it.
      */
     mTakePictureOnSuccessCb = nullptr;
     mTakePictureOnErrorCb = nullptr;
     cancel = true;
   }
 
-  nsCOMPtr<nsIRunnable> takePictureTask = new TakePictureTask(this, cancel, aSize, aRotation, aFileFormat, aPosition, onSuccess, onError);
+  nsCOMPtr<nsIRunnable> takePictureTask = new TakePictureTask(this, cancel, aSize, aRotation, aFileFormat, aPosition, aDateTime, onSuccess, onError);
   return mCameraThread->Dispatch(takePictureTask, NS_DISPATCH_NORMAL);
 }
 
 nsresult
 CameraControlImpl::StartRecording(CameraStartRecordingOptions* aOptions, nsIFile* aFolder, const nsAString& aFilename, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError)
 {
   nsCOMPtr<nsIFile> clone;
   aFolder->Clone(getter_AddRefs(clone));
--- a/dom/camera/CameraControlImpl.h
+++ b/dom/camera/CameraControlImpl.h
@@ -47,17 +47,17 @@ class CameraControlImpl : public ICamera
 
 public:
   CameraControlImpl(uint32_t aCameraId, nsIThread* aCameraThread, uint64_t aWindowId);
 
   nsresult GetPreviewStream(dom::CameraSize aSize, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError);
   nsresult StartPreview(DOMCameraPreview* aDOMPreview);
   void StopPreview();
   nsresult AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError);
-  nsresult TakePicture(dom::CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, dom::CameraPosition aPosition, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError);
+  nsresult TakePicture(dom::CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, dom::CameraPosition aPosition, uint64_t aDateTime, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError);
   nsresult StartRecording(dom::CameraStartRecordingOptions* aOptions, nsIFile* aFolder, const nsAString& aFilename, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError);
   nsresult StopRecording();
   nsresult GetPreviewStreamVideoMode(dom::CameraRecorderOptions* aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError);
   nsresult ReleaseHardware(nsICameraReleaseCallback* onSuccess, nsICameraErrorCallback* onError);
 
   nsresult Set(uint32_t aKey, const nsAString& aValue);
   nsresult Get(uint32_t aKey, nsAString& aValue);
   nsresult Set(uint32_t aKey, double aValue);
@@ -356,23 +356,24 @@ protected:
   nsMainThreadPtrHandle<nsICameraTakePictureCallback> mOnSuccessCb;
   uint64_t mWindowId;
 };
 
 // Capture a still image with the camera.
 class TakePictureTask : public nsRunnable
 {
 public:
-  TakePictureTask(CameraControlImpl* aCameraControl, bool aCancel, dom::CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, dom::CameraPosition aPosition, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError)
+  TakePictureTask(CameraControlImpl* aCameraControl, bool aCancel, dom::CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, dom::CameraPosition aPosition, uint64_t aDateTime, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError)
     : mCameraControl(aCameraControl)
     , mCancel(aCancel)
     , mSize(aSize)
     , mRotation(aRotation)
     , mFileFormat(aFileFormat)
     , mPosition(aPosition)
+    , mDateTime(aDateTime)
     , mOnSuccessCb(new nsMainThreadPtrHolder<nsICameraTakePictureCallback>(onSuccess))
     , mOnErrorCb(new nsMainThreadPtrHolder<nsICameraErrorCallback>(onError))
   {
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
   virtual ~TakePictureTask()
   {
@@ -394,16 +395,17 @@ public:
   }
 
   nsRefPtr<CameraControlImpl> mCameraControl;
   bool mCancel;
   dom::CameraSize mSize;
   int32_t mRotation;
   nsString mFileFormat;
   dom::CameraPosition mPosition;
+  uint64_t mDateTime;
   nsMainThreadPtrHandle<nsICameraTakePictureCallback> mOnSuccessCb;
   nsMainThreadPtrHandle<nsICameraErrorCallback> mOnErrorCb;
 };
 
 // Return the result of starting recording.  Runs on the main thread.
 class StartRecordingResult : public nsRunnable
 {
 public:
--- a/dom/camera/DOMCameraControl.cpp
+++ b/dom/camera/DOMCameraControl.cpp
@@ -352,17 +352,17 @@ nsDOMCameraControl::TakePicture(const JS
    */
   pos.latitude = NAN;
   pos.longitude = NAN;
   pos.altitude = NAN;
   pos.timestamp = NAN;
   rv = pos.Init(cx, &options.position);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return mCameraControl->TakePicture(size, options.rotation, options.fileFormat, pos, onSuccess, onError);
+  return mCameraControl->TakePicture(size, options.rotation, options.fileFormat, pos, options.dateTime, onSuccess, onError);
 }
 
 /* [implicit_jscontext] void GetPreviewStreamVideoMode (in jsval aOptions, in nsICameraPreviewStreamCallback onSuccess, [optional] in nsICameraErrorCallback onError); */
 NS_IMETHODIMP
 nsDOMCameraControl::GetPreviewStreamVideoMode(const JS::Value& aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError, JSContext* cx)
 {
   NS_ENSURE_TRUE(onSuccess, NS_ERROR_INVALID_ARG);
 
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -9,16 +9,17 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
+#include <time.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <libgen.h>
 #include "base/basictypes.h"
 #include "libcameraservice/CameraHardwareInterface.h"
 #include "camera/CameraParameters.h"
@@ -792,16 +793,43 @@ nsGonkCameraControl::TakePictureImpl(Tak
     DOM_CAMERA_LOGI("setting picture altitude to %lf\n", aTakePicture->mPosition.altitude);
     SetParameter(CameraParameters::KEY_GPS_ALTITUDE, nsPrintfCString("%lf", aTakePicture->mPosition.altitude).get());
   }
   if (!isnan(aTakePicture->mPosition.timestamp)) {
     DOM_CAMERA_LOGI("setting picture timestamp to %lf\n", aTakePicture->mPosition.timestamp);
     SetParameter(CameraParameters::KEY_GPS_TIMESTAMP, nsPrintfCString("%lf", aTakePicture->mPosition.timestamp).get());
   }
 
+  // Add the non-GPS timestamp.  The EXIF date/time field is formatted as
+  // "YYYY:MM:DD HH:MM:SS", without room for a time-zone; as such, the time
+  // is meant to be stored as a local time.  Since we are given seconds from
+  // Epoch GMT, we use localtime_r() to handle the conversion.
+  time_t time = aTakePicture->mDateTime;
+  if (time != aTakePicture->mDateTime) {
+    DOM_CAMERA_LOGE("picture date/time '%llu' is too far in the future\n", aTakePicture->mDateTime);
+  } else {
+    struct tm t;
+    if (localtime_r(&time, &t)) {
+      char dateTime[20];
+      if (strftime(dateTime, sizeof(dateTime), "%Y:%m:%d %T", &t)) {
+        DOM_CAMERA_LOGI("setting picture date/time to %s\n", dateTime);
+        // Not every platform defines a CameraParameters::KEY_EXIF_DATETIME;
+        // for those who don't, we use the raw string key, and if the platform
+        // doesn't support it, it will be ignored.
+        //
+        // See bug 832494.
+        SetParameter("exif-datetime", dateTime);
+      } else {
+        DOM_CAMERA_LOGE("picture date/time couldn't be converted to string\n");
+      }
+    } else {
+      DOM_CAMERA_LOGE("picture date/time couldn't be converted to local time: (%d) %s\n", errno, strerror(errno));
+    }
+  }
+
   mDeferConfigUpdate = false;
   PushParameters();
 
   if (GonkCameraHardware::TakePicture(mHwHandle) != OK) {
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
--- a/dom/camera/ICameraControl.h
+++ b/dom/camera/ICameraControl.h
@@ -21,17 +21,17 @@ class ICameraControl
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ICameraControl)
 
   virtual nsresult GetPreviewStream(dom::CameraSize aSize, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
   virtual nsresult StartPreview(DOMCameraPreview* aDOMPreview) = 0;
   virtual void StopPreview() = 0;
   virtual nsresult AutoFocus(nsICameraAutoFocusCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
-  virtual nsresult TakePicture(dom::CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, dom::CameraPosition aPosition, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
+  virtual nsresult TakePicture(dom::CameraSize aSize, int32_t aRotation, const nsAString& aFileFormat, dom::CameraPosition aPosition, uint64_t aDateTime, nsICameraTakePictureCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
   virtual nsresult StartRecording(dom::CameraStartRecordingOptions* aOptions, nsIFile* aFolder, const nsAString& aFilename, nsICameraStartRecordingCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
   virtual nsresult StopRecording() = 0;
   virtual nsresult GetPreviewStreamVideoMode(dom::CameraRecorderOptions* aOptions, nsICameraPreviewStreamCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
   virtual nsresult ReleaseHardware(nsICameraReleaseCallback* onSuccess, nsICameraErrorCallback* onError) = 0;
 
   virtual nsresult Set(uint32_t aKey, const nsAString& aValue) = 0;
   virtual nsresult Get(uint32_t aKey, nsAString& aValue) = 0;
   virtual nsresult Set(uint32_t aKey, double aValue) = 0;
--- a/dom/camera/nsIDOMCameraManager.idl
+++ b/dom/camera/nsIDOMCameraManager.idl
@@ -145,30 +145,34 @@ dictionary CameraPictureOptions
 
         can be null in the case where position information isn't
         available/desired.
 
         'altitude' is in metres; 'timestamp' is UTC, in seconds from
         January 1, 1970.
     */
     jsval     position;
+
+    /* the number of seconds from January 1, 1970 UTC.  This can be
+       different from the positional timestamp (above). */
+    long long dateTime;
 };
 
 /* These properties affect the video recording preview, e.g.
       {
          profile: "1080p",
          rotation: 0
       }
 
    'profile' is one of the profiles returned by
    nsICameraCapabilities.recorderProfiles'; if this profile is missing,
    an arbitrary profile will be chosen.
 
    'rotation' is the degrees clockwise to rotate the preview; if
-   this options is not supported, it will be ignored; if this option
+   this option is not supported, it will be ignored; if this option
    is missing, the default is 0.
 */
 dictionary CameraRecorderOptions
 {
     DOMString profile;
     long      rotation;
 };
 
new file mode 100644
--- /dev/null
+++ b/dom/defs.mk
@@ -0,0 +1,5 @@
+ifeq ($(OS_TARGET),WINNT)
+ifneq (,$(filter nightly,$(MOZ_UPDATE_CHANNEL)))
+NO_PROFILE_GUIDED_OPTIMIZE := 1 # Don't PGO
+endif
+endif
--- a/dom/file/FileService.cpp
+++ b/dom/file/FileService.cpp
@@ -38,28 +38,20 @@ FileService::~FileService()
 }
 
 nsresult
 FileService::Init()
 {
   mFileStorageInfos.Init();
 
   nsresult rv;
-
   mStreamTransportTarget =
     do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIStreamTransportService> sts =
-    do_QueryInterface(mStreamTransportTarget);
-
-  rv = sts->RaiseThreadLimit();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
+  return rv;
 }
 
 nsresult
 FileService::Cleanup()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   nsIThread* thread = NS_GetCurrentThread();
--- a/dom/media/tests/mochitest/Makefile.in
+++ b/dom/media/tests/mochitest/Makefile.in
@@ -10,24 +10,24 @@ relativesrcdir = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_FILES = \
   test_getUserMedia_exceptions.html \
   test_getUserMedia_basicAudio.html \
   test_getUserMedia_basicVideo.html \
   test_getUserMedia_basicVideoAudio.html \
+  test_peerConnection_basicAudio.html \
+  test_peerConnection_basicAudioVideo.html \
+  test_peerConnection_basicAudioVideoCombined.html \
+  test_peerConnection_basicVideo.html \
   head.js \
   mediaStreamPlayback.js \
   pc.js \
   $(NULL)
 
 # The following tests are leaking and cannot be run by default yet
 ifdef MOZ_WEBRTC_LEAKING_TESTS
 MOCHITEST_FILES += \
-  test_peerConnection_basicAudio.html \
-  test_peerConnection_basicAudioVideo.html \
-  test_peerConnection_basicAudioVideoCombined.html \
-  test_peerConnection_basicVideo.html \
   $(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/dom/media/tests/mochitest/test_peerConnection_basicAudio.html
+++ b/dom/media/tests/mochitest/test_peerConnection_basicAudio.html
@@ -88,17 +88,17 @@ https://bugzilla.mozilla.org/show_bug.cg
           ok(PeerConnection.findStream(pcRemote.remoteStreams, test_data.pcRemote.audio[0]) !== -1,
              "Remote audio stream for remote peer is accessible");
 
           info("For now simply disconnect. We will add checks for media in a follow-up bug");
           disconnect();
         });
       }, unexpectedCallbackAndFinish);
     }, unexpectedCallbackAndFinish);
-  });
+  }, true);
 
   function disconnect() {
     pcLocal.close();
     pcRemote.close();
 
     info("We can't run any checks and clean-up code due to a crash (see bug 820072)");
 
     SimpleTest.finish();
--- a/dom/media/tests/mochitest/test_peerConnection_basicAudioVideo.html
+++ b/dom/media/tests/mochitest/test_peerConnection_basicAudioVideo.html
@@ -135,17 +135,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
               info("For now simply disconnect. We will add checks for media in a follow-up bug");
               disconnect();
             });
           }, unexpectedCallbackAndFinish);
         }, unexpectedCallbackAndFinish);
       }, unexpectedCallbackAndFinish);
     }, unexpectedCallbackAndFinish);
-  });
+  }, true);
 
   function disconnect() {
     pcLocal.close();
     pcRemote.close();
 
     info("We can't run any checks and clean-up code due to a crash (see bug 820072)");
 
     SimpleTest.finish();
--- a/dom/media/tests/mochitest/test_peerConnection_basicAudioVideoCombined.html
+++ b/dom/media/tests/mochitest/test_peerConnection_basicAudioVideoCombined.html
@@ -123,17 +123,17 @@ https://bugzilla.mozilla.org/show_bug.cg
           ok(PeerConnection.findStream(pcRemote.remoteStreams, test_data.pcRemote.video[0]) !== -1,
              "Remote video stream for remote peer is accessible");
 
           info("For now simply disconnect. We will add checks for media in a follow-up bug");
           disconnect();
         });
       }, unexpectedCallbackAndFinish);
     }, unexpectedCallbackAndFinish);
-  });
+  }, true);
 
   function disconnect() {
     pcLocal.close();
     pcRemote.close();
 
     info("We can't run any checks and clean-up code due to a crash (see bug 820072)");
 
     SimpleTest.finish();
--- a/dom/media/tests/mochitest/test_peerConnection_basicVideo.html
+++ b/dom/media/tests/mochitest/test_peerConnection_basicVideo.html
@@ -88,17 +88,17 @@ https://bugzilla.mozilla.org/show_bug.cg
           ok(PeerConnection.findStream(pcRemote.remoteStreams, test_data.pcRemote.video[0]) !== -1,
              "Remote video stream for remote peer is accessible");
 
           info("For now simply disconnect. We will add checks for media in a follow-up bug");
           disconnect();
         });
       }, unexpectedCallbackAndFinish);
     }, unexpectedCallbackAndFinish);
-  });
+  }, true);
 
   function disconnect() {
     pcLocal.close();
     pcRemote.close();
 
     info("We can't run any checks and clean-up code due to a crash (see bug 820072)");
 
     SimpleTest.finish();
--- a/dom/network/src/NetworkStatsDB.jsm
+++ b/dom/network/src/NetworkStatsDB.jsm
@@ -66,45 +66,52 @@ NetworkStatsDB.prototype = {
         objectStore.createIndex("txTotalBytes", "txTotalBytes", { unique: false });
         if (DEBUG) {
           debug("Created object stores and indexes");
         }
       }
     }
   },
 
+  convertDate: function convertDate(aDate) {
+    // Convert to UTC according to timezone and
+    // filter timestamp to get SAMPLE_RATE precission
+    let timestamp = aDate.getTime() - aDate.getTimezoneOffset() * 60 * 1000;
+    timestamp = Math.floor(timestamp / SAMPLE_RATE) * SAMPLE_RATE;
+    return timestamp;
+  },
+
   saveStats: function saveStats(stats, aResultCb) {
-    // Filter timestamp to get SAMPLE_RATE precission
-    let offset = new Date().getTimezoneOffset() * 60 * 1000;
-    let timestamp = Math.floor((stats.date.getTime() - offset) / SAMPLE_RATE) * SAMPLE_RATE + offset;
+    let timestamp = this.convertDate(stats.date);
 
     stats = {connectionType: stats.connectionType,
              timestamp:      timestamp,
              rxBytes:        0,
              txBytes:        0,
              rxTotalBytes:   stats.rxBytes,
              txTotalBytes:   stats.txBytes};
 
     this.dbNewTxn("readwrite", function(txn, store) {
       if (DEBUG) {
-        debug("Going to store " + JSON.stringify(stats));
+        debug("Filtered time: " + new Date(timestamp));
+        debug("New stats: " + JSON.stringify(stats));
       }
 
       let request = store.index("connectionType").openCursor(stats.connectionType, "prev");
       request.onsuccess = function onsuccess(event) {
         let cursor = event.target.result;
         if (!cursor) {
           // Empty, so save first element.
           this._saveStats(txn, store, stats);
           return;
         }
 
         // There are old samples
         if (DEBUG) {
-          debug(JSON.stringify(cursor.value));
+          debug("Last value " + JSON.stringify(cursor.value));
         }
 
         // Remove stats previous to now - VALUE_MAX_LENGTH
         this._removeOldStats(txn, store, stats.connectionType, stats.timestamp);
 
         // Process stats before save
         this._processSamplesDiff(txn, store, cursor, stats);
       }.bind(this);
@@ -115,16 +122,23 @@ NetworkStatsDB.prototype = {
    * This function check that stats are saved in the database following the sample rate.
    * In this way is easier to find elements when stats are requested.
    */
   _processSamplesDiff: function _processSamplesDiff(txn, store, lastSampleCursor, newSample) {
     let lastSample = lastSampleCursor.value;
 
     // Get difference between last and new sample.
     let diff = (newSample.timestamp - lastSample.timestamp) / SAMPLE_RATE;
+    if (diff % 1) {
+      // diff is decimal, so some error happened because samples are stored as a multiple
+      // of SAMPLE_RATE
+      txn.abort();
+      throw new Error("Error processing samples");
+    }
+
     if (DEBUG) {
       debug("New: " + newSample.timestamp + " - Last: " + lastSample.timestamp + " - diff: " + diff);
     }
 
     let rxDiff = newSample.rxTotalBytes - lastSample.rxTotalBytes;
     let txDiff = newSample.txTotalBytes - lastSample.txTotalBytes;
     if (rxDiff < 0 || txDiff < 0) {
       rxDiff = newSample.rxTotalBytes;
@@ -134,17 +148,18 @@ NetworkStatsDB.prototype = {
     newSample.txBytes = txDiff;
 
     if (diff == 1) {
       // New element.
       this._saveStats(txn, store, newSample);
       return;
     }
     if (diff > 1) {
-      // Some samples lost. Device off during one or more samplerate periods
+      // Some samples lost. Device off during one or more samplerate periods.
+      // Time or timezone changed
       // Add lost samples with 0 bytes and the actual one.
       if (diff > VALUES_MAX_LENGTH) {
         diff = VALUES_MAX_LENGTH;
       }
 
       let data = [];
       for (let i = diff - 2; i >= 0; i--) {
         let time = newSample.timestamp - SAMPLE_RATE * (i + 1);
@@ -158,30 +173,34 @@ NetworkStatsDB.prototype = {
       }
 
       data.push(newSample);
       this._saveStats(txn, store, data);
       return;
     }
     if (diff == 0) {
       // New element received before samplerate period.
-      // It means that device has been restarted (or clock change).
+      // It means that device has been restarted (or clock / timezone change).
       // Update element.
 
       lastSample.rxBytes += rxDiff;
       lastSample.txBytes += txDiff;
       lastSample.rxTotalBytes = newSample.rxTotalBytes;
       lastSample.txTotalBytes = newSample.txTotalBytes;
+      if (DEBUG) {
+        debug("Update: " + JSON.stringify(lastSample));
+      }
       let req = lastSampleCursor.update(lastSample);
     }
     if (diff < 0) {
-      // Only possible if clock changed.
+      // Clock or timezone changed back.
       if (DEBUG) {
-        debug("This stat record older than last one");
+        debug("This stat record is older than last one");
       }
+      this._insertSample(txn, store, newSample, lastSample.timestamp);
     }
   },
 
   _saveStats: function _saveStats(txn, store, networkStats) {
     if (DEBUG) {
       debug("_saveStats: " + JSON.stringify(networkStats));
     }
 
@@ -190,16 +209,35 @@ NetworkStatsDB.prototype = {
       for (let i = 0; i <= len; i++) {
         store.put(networkStats[i]);
       }
     } else {
       store.put(networkStats);
     }
   },
 
+  _insertSample: function _insertSample(txn, store, sample, endTimestamp) {
+    let lowFilter = [sample.connectionType, sample.timestamp];
+    let upFilter = [sample.connectionType, endTimestamp];
+    let range = this.dbGlobal.IDBKeyRange.bound(lowFilter, upFilter, false, false);
+
+    let request = store.openCursor(range).onsuccess = function(event) {
+      var cursor = event.target.result;
+      if (cursor) {
+        sample.rxBytes += cursor.value.rxBytes;
+        sample.txBytes += cursor.value.txBytes;
+        cursor.delete();
+        cursor.continue();
+        return;
+      }
+
+      this._saveStats(txn, store, sample);
+    }.bind(this);
+  },
+
   _removeOldStats: function _removeOldStats(txn, store, connType, date) {
     // Callback function to remove old items when new ones are added.
     let filterDate = date - (SAMPLE_RATE * VALUES_MAX_LENGTH - 1);
     let lowFilter = [connType, 0];
     let upFilter = [connType, filterDate];
     let range = this.dbGlobal.IDBKeyRange.bound(lowFilter, upFilter, false, false);
     store.openCursor(range).onsuccess = function(event) {
       var cursor = event.target.result;
@@ -215,22 +253,23 @@ NetworkStatsDB.prototype = {
       if (DEBUG) {
         debug("Going to clear all!");
       }
       store.clear();
     }, aResultCb);
   },
 
   find: function find(aResultCb, aOptions) {
-    // Filter end and start date to adapt them to SAMPLE_RATE precision.
-    let offset = new Date().getTimezoneOffset() * 60 * 1000;
-    let start = Math.floor((aOptions.start - offset) / SAMPLE_RATE) * SAMPLE_RATE + offset;
-    let end = Math.floor((aOptions.end - offset) / SAMPLE_RATE) * SAMPLE_RATE + offset;
+    let start = this.convertDate(aOptions.start);
+    let end = this.convertDate(aOptions.end);
+
     if (DEBUG) {
       debug("Find: connectionType:" + aOptions.connectionType + " start: " + start + " end: " + end);
+      debug("Start time: " + new Date(start));
+      debug("End time: " + new Date(end));
     }
 
     this.dbNewTxn("readonly", function(txn, store) {
       let lowFilter = [aOptions.connectionType, start];
       let upFilter = [aOptions.connectionType, end];
       let range = this.dbGlobal.IDBKeyRange.bound(lowFilter, upFilter, false, false);
 
       let data = [];
@@ -257,19 +296,19 @@ NetworkStatsDB.prototype = {
         txn.result.start = new Date(aOptions.start);
         txn.result.end = new Date(aOptions.end);
         txn.result.data = data;
       }.bind(this);
     }.bind(this), aResultCb);
   },
 
   findAll: function findAll(aResultCb, aOptions) {
-let offset = new Date().getTimezoneOffset() * 60 * 1000;
-    let start = Math.floor((aOptions.start - offset) / SAMPLE_RATE) * SAMPLE_RATE + offset;
-    let end = Math.floor((aOptions.end - offset) / SAMPLE_RATE) * SAMPLE_RATE + offset;
+    let start = this.convertDate(aOptions.start);
+    let end = this.convertDate(aOptions.end);
+
     if (DEBUG) {
       debug("FindAll: start: " + start + " end: " + end + "\n");
     }
 
     let self = this;
     this.dbNewTxn("readonly", function(txn, store) {
       let lowFilter = start;
       let upFilter = end;
--- a/dom/network/src/NetworkStatsManager.js
+++ b/dom/network/src/NetworkStatsManager.js
@@ -117,19 +117,16 @@ NetworkStatsManager.prototype = {
   getNetworkStats: function getNetworkStats(aOptions) {
     this.checkPrivileges();
 
     if (!aOptions.start || !aOptions.end ||
       aOptions.start > aOptions.end) {
       throw Components.results.NS_ERROR_INVALID_ARG;
     }
 
-    aOptions.start = aOptions.start.getTime();
-    aOptions.end = aOptions.end.getTime();
-
     let request = this.createRequest();
     cpmm.sendAsyncMessage("NetworkStats:Get",
                           {data: aOptions, id: this.getRequestId(request)});
     return request;
   },
 
   clearAllData: function clearAllData() {
     this.checkPrivileges();
--- a/dom/sms/interfaces/nsIRilSmsDatabaseService.idl
+++ b/dom/sms/interfaces/nsIRilSmsDatabaseService.idl
@@ -1,13 +1,33 @@
 /* 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 "nsISmsDatabaseService.idl"
 
-[scriptable, uuid(71d7dd4e-5489-4e58-a489-171200378c3c)]
+interface nsIDOMMozSmsMessage;
+
+[scriptable, function, uuid(04a08668-c020-469e-a1ad-8626c951ab2b)]
+interface nsIRilSmsDatabaseCallback : nsISupports
+{
+  void notify(in nsresult aRv, in nsIDOMMozSmsMessage aSms);
+};
+
+[scriptable, uuid(8e2acd73-0332-4d16-82cc-ff5bac59d245)]
 interface nsIRilSmsDatabaseService : nsISmsDatabaseService
 {
-  long saveReceivedMessage(in DOMString aSender, in DOMString aBody, in DOMString aMessageClass, in unsigned long long aDate);
-  long saveSendingMessage(in DOMString aReceiver, in DOMString aBody, in unsigned long long aDate);
-  void setMessageDelivery(in long aMessageId, in DOMString aDelivery, in DOMString aDeliveryStatus);
+  long saveReceivedMessage(in DOMString aSender,
+                           in DOMString aBody,
+                           in DOMString aMessageClass,
+                           in unsigned long long aDate,
+                [optional] in nsIRilSmsDatabaseCallback aCallback);
+  long saveSendingMessage(in DOMString aReceiver,
+                          in DOMString aBody,
+                          in DOMString aDeliveryStatus,
+                          in unsigned long long aDate,
+               [optional] in nsIRilSmsDatabaseCallback aCallback);
+  void setMessageDelivery(in long aMessageId,
+                          in DOMString aDelivery,
+                          in DOMString aDeliveryStatus,
+               [optional] in nsIRilSmsDatabaseCallback aCallback);
 };
--- a/dom/sms/src/ril/SmsDatabaseService.js
+++ b/dom/sms/src/ril/SmsDatabaseService.js
@@ -174,44 +174,44 @@ SmsDatabaseService.prototype = {
             self.createSchema(db);
             break;
           case 1:
             if (DEBUG) debug("Upgrade to version 2. Including `read` index");
             let objectStore = event.target.transaction.objectStore(STORE_NAME);
             self.upgradeSchema(objectStore);
             break;
           case 2:
-            if (DEBUG) debug("Upgrade to version 3. Fix existing entries.")
+            if (DEBUG) debug("Upgrade to version 3. Fix existing entries.");
             objectStore = event.target.transaction.objectStore(STORE_NAME);
             self.upgradeSchema2(objectStore);
             break;
           case 3:
-            if (DEBUG) debug("Upgrade to version 4. Add quick threads view.")
+            if (DEBUG) debug("Upgrade to version 4. Add quick threads view.");
             self.upgradeSchema3(db, event.target.transaction);
             break;
           case 4:
-            if (DEBUG) debug("Upgrade to version 5. Populate quick threads view.")
+            if (DEBUG) debug("Upgrade to version 5. Populate quick threads view.");
             self.upgradeSchema4(event.target.transaction);
             break;
           case 5:
-            if (DEBUG) debug("Upgrade to version 6. Use PhonenumberJS.")
+            if (DEBUG) debug("Upgrade to version 6. Use PhonenumberJS.");
             self.upgradeSchema5(event.target.transaction);
             break;
           case 6:
-            if (DEBUG) debug("Upgrade to version 7. Use multiple entry indexes.")
+            if (DEBUG) debug("Upgrade to version 7. Use multiple entry indexes.");
             self.upgradeSchema6(event.target.transaction);
             break;
           default:
             event.target.transaction.abort();
             callback("Old database version: " + event.oldVersion, null);
             break;
         }
         currentVersion++;
       }
-    }
+    };
     request.onerror = function (event) {
       //TODO look at event.target.Code and change error constant accordingly
       callback("Error opening database!", null);
     };
     request.onblocked = function (event) {
       callback("Opening database request is blocked.", null);
     };
   },
@@ -293,17 +293,17 @@ SmsDatabaseService.prototype = {
         return;
       }
 
       let message = cursor.value;
       message.messageClass = MESSAGE_CLASS_NORMAL;
       message.deliveryStatus = DELIVERY_STATUS_NOT_APPLICABLE;
       cursor.update(message);
       cursor.continue();
-    }
+    };
   },
 
   upgradeSchema3: function upgradeSchema3(db, transaction) {
     // Delete redundant "id" index.
     let objectStore = transaction.objectStore(STORE_NAME);
     if (objectStore.indexNames.contains("id")) {
       objectStore.deleteIndex("id");
     }
@@ -353,20 +353,20 @@ SmsDatabaseService.prototype = {
         }
       } else {
         threads[contact] = {
           senderOrReceiver: contact,
           id: message.id,
           timestamp: message.timestamp,
           body: message.body,
           unreadCount: message.read ? 0 : 1
-        }
+        };
       }
       cursor.continue();
-    }
+    };
   },
 
   upgradeSchema5: function upgradeSchema5(transaction) {
     // Don't perform any upgrade. See Bug 819560.
   },
 
   upgradeSchema6: function upgradeSchema6(transaction) {
     let objectStore = transaction.objectStore(STORE_NAME);
@@ -405,17 +405,17 @@ SmsDatabaseService.prototype = {
       message.deliveryIndex = [message.delivery, timestamp];
       message.numberIndex = [
         [message.sender, timestamp],
         [message.receiver, timestamp]
       ];
       message.readIndex = [message.read, timestamp];
       cursor.update(message);
       cursor.continue();
-    }
+    };
   },
 
   createMessageFromRecord: function createMessageFromRecord(record) {
     if (DEBUG) debug("createMessageFromRecord: " + JSON.stringify(record));
     return gSmsService.createSmsMessage(record.id,
                                         record.delivery,
                                         record.deliveryStatus,
                                         record.sender,
@@ -494,24 +494,24 @@ SmsDatabaseService.prototype = {
         aMessageList.listId = self.lastMessageListId;
         self.messageLists[self.lastMessageListId] = aMessageList;
         if (DEBUG) {
           debug("notifyMessageListCreated - listId: "
                 + aMessageList.listId + ", messageId: " + firstMessageId);
         }
         smsRequest.notifyMessageListCreated(aMessageList.listId, sms);
       }
-    }
+    };
     getRequest.onerror = function onerror(event) {
       if (DEBUG) {
         debug("notifyReadMessageListFailed - listId: "
               + aMessageList.listId + ", messageId: " + firstMessageId);
       }
       smsRequest.notifyReadMessageListFailed(Ci.nsISmsRequest.INTERNAL_ERROR);
-    }
+    };
   },
 
   /**
    * Queue up {aMessageId, aTimestamp} pairs, find out intersections and report
    * to onNextMessageInListGot. Return true if it is still possible to have
    * another match.
    */
   onNextMessageInMultiFiltersGot: function onNextMessageInMultiFiltersGot(
@@ -642,31 +642,51 @@ SmsDatabaseService.prototype = {
                                             tres[i].id, tres[i].timestamp);
       }
       this.onNextMessageInMultiFiltersGot(aObjectStore, aMessageList,
                                           aContextIndex, 0, 0);
     }
     return false;
   },
 
-  saveMessage: function saveMessage(message) {
+  saveMessage: function saveMessage(message, callback) {
     this.lastKey += 1;
     message.id = this.lastKey;
     if (DEBUG) debug("Going to store " + JSON.stringify(message));
+
+    let self = this;
+    function notifyResult(rv) {
+      if (!callback) {
+        return;
+      }
+      let sms = self.createMessageFromRecord(message);
+      callback.notify(rv, sms);
+    }
+
     this.newTxn(READ_WRITE, function(error, txn, stores) {
       if (error) {
+        // TODO bug 832140 check event.target.errorCode
+        notifyResult(Cr.NS_ERROR_FAILURE);
         return;
       }
+      txn.oncomplete = function oncomplete(event) {
+        notifyResult(Cr.NS_OK);
+      };
+      txn.onabort = function onabort(event) {
+        // TODO bug 832140 check event.target.errorCode
+        notifyResult(Cr.NS_ERROR_FAILURE);
+      };
+
       // First add to main objectStore.
       stores[0].put(message);
 
       let number = numberFromMessage(message);
 
       // Next update the other objectStore.
-      stores[1].get(number).onsuccess = function(event) {
+      stores[1].get(number).onsuccess = function onsuccess(event) {
         let mostRecentEntry = event.target.result;
         if (mostRecentEntry) {
           let needsUpdate = false;
 
           if (mostRecentEntry.timestamp <= message.timestamp) {
             mostRecentEntry.timestamp = message.timestamp;
             mostRecentEntry.body = message.body;
             needsUpdate = true;
@@ -682,29 +702,32 @@ SmsDatabaseService.prototype = {
           }
         } else {
           event.target.source.add({ senderOrReceiver: number,
                                     timestamp: message.timestamp,
                                     body: message.body,
                                     id: message.id,
                                     unreadCount: message.read ? 0 : 1 });
         }
-      }
+      };
     }, [STORE_NAME, MOST_RECENT_STORE_NAME]);
     // We return the key that we expect to store in the db
     return message.id;
   },
 
 
   /**
    * nsIRilSmsDatabaseService API
    */
 
-  saveReceivedMessage: function saveReceivedMessage(aSender, aBody, aMessageClass, aDate) {
-    let receiver = this.mRIL.rilContext.icc ? this.mRIL.rilContext.icc.msisdn : null;
+  saveReceivedMessage: function saveReceivedMessage(
+      aSender, aBody, aMessageClass, aDate, aCallback) {
+    let receiver = this.mRIL.rilContext.icc
+                 ? this.mRIL.rilContext.icc.msisdn
+                 : null;
 
     // Workaround an xpconnect issue with undefined string objects.
     // See bug 808220
     if (receiver === undefined || receiver === "undefined") {
       receiver = null;
     }
 
     if (receiver) {
@@ -731,29 +754,32 @@ SmsDatabaseService.prototype = {
       deliveryStatus: DELIVERY_STATUS_SUCCESS,
       sender:         sender,
       receiver:       receiver,
       body:           aBody,
       messageClass:   aMessageClass,
       timestamp:      aDate,
       read:           FILTER_READ_UNREAD
     };
-    return this.saveMessage(message);
+    return this.saveMessage(message, aCallback);
   },
 
-  saveSendingMessage: function saveSendingMessage(aReceiver, aBody, aDate) {
-    let sender = this.mRIL.rilContext.icc ? this.mRIL.rilContext.icc.msisdn : null;
+  saveSendingMessage: function saveSendingMessage(
+      aReceiver, aBody, aDeliveryStatus, aDate, aCallback) {
+    let sender = this.mRIL.rilContext.icc
+               ? this.mRIL.rilContext.icc.msisdn
+               : null;
 
     // Workaround an xpconnect issue with undefined string objects.
     // See bug 808220
     if (sender === undefined || sender === "undefined") {
       sender = null;
     }
 
-    let receiver = aReceiver
+    let receiver = aReceiver;
     if (receiver) {
       let parsedNumber = PhoneNumberUtils.parse(receiver.toString());
       receiver = (parsedNumber && parsedNumber.internationalNumber)
                  ? parsedNumber.internationalNumber
                  : receiver;
     }
 
     if (sender) {
@@ -764,41 +790,64 @@ SmsDatabaseService.prototype = {
     }
 
     let message = {
       deliveryIndex:  [DELIVERY_SENDING, aDate],
       numberIndex:    [[sender, aDate], [receiver, aDate]],
       readIndex:      [FILTER_READ_READ, aDate],
 
       delivery:       DELIVERY_SENDING,
-      deliveryStatus: DELIVERY_STATUS_PENDING,
+      deliveryStatus: aDeliveryStatus,
       sender:         sender,
       receiver:       receiver,
       body:           aBody,
       messageClass:   MESSAGE_CLASS_NORMAL,
       timestamp:      aDate,
       read:           FILTER_READ_READ
     };
-    return this.saveMessage(message);
+    return this.saveMessage(message, aCallback);
   },
 
-  setMessageDelivery: function setMessageDelivery(messageId, delivery, deliveryStatus) {
+  setMessageDelivery: function setMessageDelivery(
+      messageId, delivery, deliveryStatus, callback) {
     if (DEBUG) {
       debug("Setting message " + messageId + " delivery to " + delivery
             + ", and deliveryStatus to " + deliveryStatus);
     }
+
+    let self = this;
+    let message;
+    function notifyResult(rv) {
+      if (!callback) {
+        return;
+      }
+      let sms = null;
+      if (message) {
+        sms = self.createMessageFromRecord(message);
+      }
+      callback.notify(rv, sms);
+    }
+
     this.newTxn(READ_WRITE, function (error, txn, store) {
       if (error) {
-        if (DEBUG) debug(error);
+        // TODO bug 832140 check event.target.errorCode
+        notifyResult(Cr.NS_ERROR_FAILURE);
         return;
       }
+      txn.oncomplete = function oncomplete(event) {
+        notifyResult(Cr.NS_OK);
+      };
+      txn.onabort = function onabort(event) {
+        // TODO bug 832140 check event.target.errorCode
+        notifyResult(Cr.NS_ERROR_FAILURE);
+      };
 
       let getRequest = store.get(messageId);
       getRequest.onsuccess = function onsuccess(event) {
-        let message = event.target.result;
+        message = event.target.result;
         if (!message) {
           if (DEBUG) debug("Message ID " + messageId + " not found");
           return;
         }
         if (message.id != messageId) {
           if (DEBUG) {
             debug("Retrieve message ID (" + messageId + ") is " +
                   "different from the one we got");
--- a/dom/sms/tests/marionette/manifest.ini
+++ b/dom/sms/tests/marionette/manifest.ini
@@ -23,8 +23,10 @@ qemu = true
 [test_filter_read.js]
 [test_filter_unread.js]
 [test_filter_mixed.js]
 [test_segment_info.js]
 [test_mark_msg_read.js]
 [test_mark_msg_read_error.js]
 [test_bug814761.js]
 [test_strict_7bit_encoding.js]
+[test_incoming_max_segments.js]
+[test_outgoing_max_segments.js]
--- a/dom/sms/tests/marionette/test_getmessage.js
+++ b/dom/sms/tests/marionette/test_getmessage.js
@@ -1,63 +1,59 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 10000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
+const REMOTE = "5559997777";
+const REMOTE_FMT = "+15559997777"; // the normalized remote number
+const EMU_FMT = "+15555215554"; // the emulator's number
+
 let sms = window.navigator.mozSms;
-let myNumber = "15555215554";
-let myNumberFormats = ["15555215554", "+15555215554"];
 let inText = "Incoming SMS message. Mozilla Firefox OS!";
-let remoteNumber = "5559997777";
-let remoteNumberFormats = ["5559997777", "+15559997777"];
 let outText = "Outgoing SMS message. Mozilla Firefox OS!";
 let gotSmsOnsent = false;
 let gotReqOnsuccess = false;
-let inSmsid = 0;
-let outSmsid = 0;
+let inSmsId = 0;
+let outSmsId = 0;
 let inSmsTimeStamp;
 let outSmsTimeStamp;
 
 function verifyInitialState() {
   log("Verifying initial state.");
   ok(sms, "mozSms");
   simulateIncomingSms();  
 }
 
-function isIn(aVal, aArray, aMsg) {
-  ok(aArray.indexOf(aVal) >= 0, aMsg);
-}
-
 function simulateIncomingSms() {
   log("Simulating incoming SMS.");
 
   sms.onreceived = function onreceived(event) {
     log("Received 'onreceived' smsmanager event.");
     let incomingSms = event.message;
     ok(incomingSms, "incoming sms");
     ok(incomingSms.id, "sms id");
     inSmsId = incomingSms.id;
     log("Received SMS (id: " + inSmsId + ").");
     is(incomingSms.body, inText, "msg body");
     is(incomingSms.delivery, "received", "delivery");
     is(incomingSms.deliveryStatus, "success", "deliveryStatus");
     is(incomingSms.read, false, "read");
-    is(incomingSms.receiver, null, "receiver");
-    isIn(incomingSms.sender, remoteNumberFormats, "sender");
+    is(incomingSms.receiver, EMU_FMT, "receiver");
+    is(incomingSms.sender, REMOTE_FMT, "sender");
     is(incomingSms.messageClass, "normal", "messageClass");
     ok(incomingSms.timestamp instanceof Date, "timestamp is instanceof date");
     inSmsTimeStamp = incomingSms.timestamp;
     sendSms();
   };
   // Simulate incoming sms sent from remoteNumber to our emulator
-  runEmulatorCmd("sms send " + remoteNumber + " " + inText, function(result) {
+  runEmulatorCmd("sms send " + REMOTE + " " + inText, function(result) {
     is(result[0], "OK", "emulator output");
   });
 }
 
 function sendSms() {
   log("Sending an SMS.");
   sms.onsent = function(event) {
     log("Received 'onsent' smsmanager event.");
@@ -66,26 +62,26 @@ function sendSms() {
     ok(sentSms, "outgoing sms");
     ok(sentSms.id, "sms id");
     outSmsId = sentSms.id;
     log("Sent SMS (id: " + outSmsId + ").");
     is(sentSms.body, outText, "msg body");
     is(sentSms.delivery, "sent", "delivery");
     is(sentSms.deliveryStatus, "pending", "deliveryStatus");
     is(sentSms.read, true, "read");
-    isIn(sentSms.receiver, remoteNumberFormats, "receiver");
-    is(sentSms.sender, null, "sender");
+    is(sentSms.receiver, REMOTE_FMT, "receiver");
+    is(sentSms.sender, EMU_FMT, "sender");
     is(sentSms.messageClass, "normal", "messageClass");
     ok(sentSms.timestamp instanceof Date, "timestamp is instanceof date");  
     outSmsTimeStamp = sentSms.timestamp;
 
     if (gotSmsOnsent && gotReqOnsuccess) { getReceivedSms(); }
   };
 
-  let requestRet = sms.send(remoteNumber, outText);
+  let requestRet = sms.send(REMOTE, outText);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     gotReqOnsuccess = true;
     if(event.target.result){
       if (gotSmsOnsent && gotReqOnsuccess) { getReceivedSms(); }
     } else {
@@ -115,18 +111,18 @@ function getReceivedSms() {
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, inSmsId, "SMS id matches");
     log("Got SMS (id: " + foundSms.id + ").");
     is(foundSms.body, inText, "SMS msg text matches");
     is(foundSms.delivery, "received", "delivery");
     is(foundSms.deliveryStatus, "success", "deliveryStatus");
     is(foundSms.read, false, "read");
-    isIn(foundSms.receiver, myNumberFormats, "receiver");
-    isIn(foundSms.sender, remoteNumberFormats, "sender");
+    is(foundSms.receiver, EMU_FMT, "receiver");
+    is(foundSms.sender, REMOTE_FMT, "sender");
     is(foundSms.messageClass, "normal", "messageClass");
     ok(foundSms.timestamp instanceof Date, "timestamp is instanceof date");
     is(foundSms.timestamp.getTime(), inSmsTimeStamp.getTime(), "timestamp matches");
     getSentSms();
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
@@ -148,18 +144,18 @@ function getSentSms() {
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, outSmsId, "SMS id matches");
     log("Got SMS (id: " + foundSms.id + ").");
     is(foundSms.body, outText, "SMS msg text matches");
     is(foundSms.delivery, "sent", "delivery");
     is(foundSms.deliveryStatus, "pending", "deliveryStatus");
     is(foundSms.read, true, "read");
-    isIn(foundSms.receiver, remoteNumberFormats, "receiver");
-    isIn(foundSms.sender, myNumberFormats, "sender");
+    is(foundSms.receiver, REMOTE_FMT, "receiver");
+    is(foundSms.sender, EMU_FMT, "sender");
     is(foundSms.messageClass, "normal", "messageClass");
     ok(foundSms.timestamp instanceof Date, "timestamp is instanceof date");
     is(foundSms.timestamp.getTime(), outSmsTimeStamp.getTime(), "timestamp matches");
     deleteMsgs();
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
--- a/dom/sms/tests/marionette/test_incoming.js
+++ b/dom/sms/tests/marionette/test_incoming.js
@@ -1,38 +1,41 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 10000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
+const REMOTE = "5555552368";
+const SENDER = "+15555552368"; // the normalized remote number
+const RECEIVER = "+15555215554"; // the emulator's number
+
 let sms = window.navigator.mozSms;
-let sender = "5555552368";
 let body = "Hello SMS world!";
 let now = Date.now();
 
 let completed = false;
-runEmulatorCmd("sms send " + sender + " " + body, function(result) {
+runEmulatorCmd("sms send " + REMOTE + " " + body, function(result) {
   log("Sent fake SMS: " + result);
   is(result[0], "OK");
   completed = true;
 });
 
 sms.onreceived = function onreceived(event) {
   log("Received an SMS!");
 
   let message = event.message;
   ok(message instanceof MozSmsMessage);
 
   is(message.delivery, "received");
   is(message.deliveryStatus, "success");
-  is(message.sender, sender);
-  is(message.receiver, null);
+  is(message.sender, SENDER);
+  is(message.receiver, RECEIVER);
   is(message.body, body);
   is(message.messageClass, "normal");
   ok(message.timestamp instanceof Date);
   // SMSC timestamp is in seconds.
   ok(Math.floor(message.timestamp.getTime() / 1000) >= Math.floor(now / 1000));
 
   cleanUp();
 };
--- a/dom/sms/tests/marionette/test_incoming_delete.js
+++ b/dom/sms/tests/marionette/test_incoming_delete.js
@@ -1,18 +1,21 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 10000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
+const REMOTE = "5555552368";
+const SENDER = "+15555552368"; // the normalized remote number
+const RECEIVER = "+15555215554"; // the emulator's number
+
 let sms = window.navigator.mozSms;
-let fromNumber = "5551234567";
 let msgText = "Mozilla Firefox OS!";
 
 function verifyInitialState() {
   log("Verifying initial state.");
   ok(sms, "mozSms");
   simulateIncomingSms();  
 }
 
@@ -24,39 +27,45 @@ function simulateIncomingSms() {
     let incomingSms = event.message;
     ok(incomingSms, "incoming sms");
     ok(incomingSms.id, "sms id");
     log("Received SMS (id: " + incomingSms.id + ").");
     is(incomingSms.body, msgText, "msg body");
     is(incomingSms.delivery, "received", "delivery");
     is(incomingSms.deliveryStatus, "success", "deliveryStatus");
     is(incomingSms.read, false, "read");
-    is(incomingSms.receiver, null, "receiver");
-    is(incomingSms.sender, fromNumber, "sender");
+    is(incomingSms.receiver, RECEIVER, "receiver");
+    is(incomingSms.sender, SENDER, "sender");
     is(incomingSms.messageClass, "normal", "messageClass");
     ok(incomingSms.timestamp instanceof Date, "timestamp is istanceof date");
 
     verifySmsExists(incomingSms);
   };
-  runEmulatorCmd("sms send " + fromNumber + " " + msgText, function(result) {
+  runEmulatorCmd("sms send " + REMOTE + " " + msgText, function(result) {
     is(result[0], "OK", "emulator output");
   });
 }
 
 function verifySmsExists(incomingSms) {
   log("Getting SMS (id: " + incomingSms.id + ").");
   let requestRet = sms.getMessage(incomingSms.id);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, incomingSms.id, "found SMS id matches");
     is(foundSms.body, msgText, "found SMS msg text matches");
+    is(foundSms.delivery, "received", "delivery");
+    is(foundSms.deliveryStatus, "success", "deliveryStatus");
+    is(foundSms.read, false, "read");
+    is(foundSms.receiver, RECEIVER, "receiver");
+    is(foundSms.sender, SENDER, "sender");
+    is(foundSms.messageClass, "normal", "messageClass");
     log("Got SMS (id: " + foundSms.id + ") as expected.");
     deleteSms(incomingSms);
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
     is(event.target.error.name, "NotFoundError", "error returned");
new file mode 100644
--- /dev/null
+++ b/dom/sms/tests/marionette/test_incoming_max_segments.js
@@ -0,0 +1,113 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 20000;
+
+SpecialPowers.setBoolPref("dom.sms.enabled", true);
+SpecialPowers.addPermission("sms", true, document);
+
+let sms = window.navigator.mozSms;
+// https://developer.mozilla.org/en-US/docs/DOM/SmsManager
+let maxCharsPerSms = 160;
+let maxSegments = 10; // 10 message segments concatenated into 1 multipart SMS
+
+const REMOTE = "5551234567";
+const REMOTE_FMT = "+15551234567"; // the normalized remote number
+const EMU_FMT = "+15555215554"; // the emulator's number
+
+function verifyInitialState() {
+  log("Verifying initial state.");
+  ok(sms, "mozSms");
+  simulateIncomingSms();
+}
+
+function simulateIncomingSms() {
+  let msgText = "";
+
+  // Build the message text
+  msgText = new Array((maxCharsPerSms * maxSegments) + 1).join('a');
+  log("Simulating incoming multipart SMS (" + msgText.length +
+      " chars total).");
+
+  sms.onreceived = function onreceived(event) {
+    sms.onreceived = null;
+    log("Received 'onreceived' smsmanager event.");
+
+    let incomingSms = event.message;
+    ok(incomingSms, "incoming sms");
+    ok(incomingSms.id, "sms id");
+    log("Received SMS (id: " + incomingSms.id + ").");
+    is(incomingSms.body.length, msgText.length, "msg body length");
+    is(incomingSms.body, msgText, "msg body");
+    is(incomingSms.delivery, "received", "delivery");
+    is(incomingSms.read, false, "read");
+    is(incomingSms.receiver, EMU_FMT, "receiver");
+    is(incomingSms.sender, REMOTE_FMT, "sender");
+    ok(incomingSms.timestamp instanceof Date, "timestamp is instanceof date");
+
+    verifySmsExists(incomingSms);
+  };
+  runEmulatorCmd("sms send " + REMOTE + " " + msgText, function(result) {
+    is(result[0], "OK", "emulator output");
+  });
+}
+
+function verifySmsExists(incomingSms) {
+  log("Getting SMS (id: " + incomingSms.id + ").");
+  let requestRet = sms.getMessage(incomingSms.id);
+  ok(requestRet, "smsrequest obj returned");
+
+  requestRet.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    ok(event.target.result, "smsrequest event.target.result");
+    let foundSms = event.target.result;
+    is(foundSms.id, incomingSms.id, "found SMS id matches");
+    is(foundSms.body.length, incomingSms.body.length, "SMS text length");
+    is(foundSms.body, incomingSms.body, "found SMS msg text matches");
+    log("Got SMS (id: " + foundSms.id + ") as expected.");
+    deleteSms(incomingSms);
+  };
+
+  requestRet.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    is(event.target.error.name, "NotFoundError", "error returned");
+    log("Could not get SMS (id: " + incomingSms.id + ") but should have.");
+    ok(false, "SMS was not found");
+    cleanUp();
+  };
+}
+
+function deleteSms(smsMsgObj){
+  log("Deleting SMS (id: " + smsMsgObj.id + ") using smsmsg obj parameter.");
+  let requestRet = sms.delete(smsMsgObj);
+  ok(requestRet, "smsrequest obj returned");
+
+  requestRet.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    if (event.target.result) {
+      cleanUp();
+    } else {
+      log("smsrequest returned false for sms.delete");
+      ok(false, "SMS delete failed");
+      cleanUp();
+    }
+  };
+
+  requestRet.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 cleanUp() {
+  SpecialPowers.removePermission("sms", document);
+  SpecialPowers.clearUserPref("dom.sms.enabled");
+  finish();
+}
+
+// Start the test
+verifyInitialState();
--- a/dom/sms/tests/marionette/test_incoming_multipart.js
+++ b/dom/sms/tests/marionette/test_incoming_multipart.js
@@ -1,26 +1,29 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 10000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
+const REMOTE = "5555552368";
+const SENDER = "+15555552368"; // the normalized remote number
+const RECEIVER = "+15555215554"; // the emulator's number
+
 let sms = window.navigator.mozSms;
 
 function verifyInitialState() {
   log("Verifying initial state.");
   ok(sms, "mozSms");
   simulateIncomingSms();  
 }
 
 function simulateIncomingSms() {
-  let fromNumber = "5551234567";
   let msgText = "";
 
   log("Simulating incoming SMS.");
 
   // Have message text > max SMS size (160 char) so will be a multi-part SMS
   for (var x = 1; x <= 24; x++) {
     msgText += 'FirefoxOS ';
   }
@@ -29,38 +32,42 @@ function simulateIncomingSms() {
     log("Received 'onreceived' smsmanager event.");
     let incomingSms = event.message;
     ok(incomingSms, "incoming sms");
     ok(incomingSms.id, "sms id");
     log("Received SMS (id: " + incomingSms.id + ").");
     is(incomingSms.body, msgText, "msg body");
     is(incomingSms.delivery, "received", "delivery");
     is(incomingSms.read, false, "read");
-    is(incomingSms.receiver, null, "receiver");
-    is(incomingSms.sender, fromNumber, "sender");
+    is(incomingSms.receiver, RECEIVER, "receiver");
+    is(incomingSms.sender, SENDER, "sender");
     ok(incomingSms.timestamp instanceof Date, "timestamp is istanceof date");
 
     verifySmsExists(incomingSms);
   };
-  runEmulatorCmd("sms send " + fromNumber + " " + msgText, function(result) {
+  runEmulatorCmd("sms send " + REMOTE + " " + msgText, function(result) {
     is(result[0], "OK", "emulator output");
   });
 }
 
 function verifySmsExists(incomingSms) {
   log("Getting SMS (id: " + incomingSms.id + ").");
   let requestRet = sms.getMessage(incomingSms.id);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, incomingSms.id, "found SMS id matches");
     is(foundSms.body, incomingSms.body, "found SMS msg text matches");
+    is(foundSms.delivery, "received", "delivery");
+    is(foundSms.read, false, "read");
+    is(foundSms.receiver, RECEIVER, "receiver");
+    is(foundSms.sender, SENDER, "sender");
     log("Got SMS (id: " + foundSms.id + ") as expected.");
     deleteSms(incomingSms);
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
     is(event.target.error.name, "NotFoundError", "error returned");
--- a/dom/sms/tests/marionette/test_outgoing.js
+++ b/dom/sms/tests/marionette/test_outgoing.js
@@ -2,16 +2,18 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 40000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.setBoolPref("dom.sms.strict7BitEncoding", false);
 SpecialPowers.addPermission("sms", true, document);
 
+const SENDER = "+15555215554"; // the emulator's number
+
 let sms = window.navigator.mozSms;
 const SHORT_BODY = "Hello SMS world!";
 const LONG_BODY = "Let me not to the marriage of true minds\n"
                 + "Admit impediments. Love is not love\n"
                 + "Which alters when it alteration finds,\n"
                 + "Or bends with the remover to remove:\n\n"
                 + "O, no! it is an ever-fix`ed mark,\n"
                 + "That looks on tempests and is never shaken;\n"
@@ -27,17 +29,17 @@ const LONG_BODY = "Let me not to the mar
 function checkMessage(message, delivery, body) {
   ok(message, "message is valid");
   ok(message instanceof MozSmsMessage,
      "message is instanceof " + message.constructor);
 
   ok(message.id, "message.id");
   is(message.delivery, delivery, "message.delivery");
   is(message.deliveryStatus, "pending", "message.deliveryStatus");
-  is(message.sender, null, "message.sender");
+  is(message.sender, SENDER, "message.sender");
   ok(message.receiver, "message.receiver");
   is(message.body, body, "message.body");
   is(message.messageClass, "normal", "message.messageClass");
   ok(message.timestamp instanceof Date,
      "message.timestamp is instanceof " + message.timestamp.constructor);
   is(message.read, true, "message.read");
 }
 
--- a/dom/sms/tests/marionette/test_outgoing_delete.js
+++ b/dom/sms/tests/marionette/test_outgoing_delete.js
@@ -1,18 +1,21 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 10000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
+const SENDER = "+15555215554"; // the emulator's number
+const DEST = "5551117777";
+const RECEIVER = "+15551117777"; // normalized destination number
+
 let sms = window.navigator.mozSms;
-let destNumber = "5551117777";
 let msgText = "Mozilla Firefox OS!";
 let gotSmsOnsent = false;
 let gotReqOnsuccess = false;
 
 function verifyInitialState() {
   log("Verifying initial state.");
   ok(sms, "mozSms");
   sendSms();
@@ -29,25 +32,25 @@ function sendSms() {
     ok(sentSms, "outgoing sms");
     ok(sentSms.id, "sms id");
     smsId = sentSms.id;
     log("Sent SMS (id: " + smsId + ").");
     is(sentSms.body, msgText, "msg body");
     is(sentSms.delivery, "sent", "delivery");
     is(sentSms.deliveryStatus, "pending", "deliveryStatus");
     is(sentSms.read, true, "read");
-    is(sentSms.receiver, destNumber, "receiver");
-    is(sentSms.sender, null, "sender");
+    is(sentSms.receiver, RECEIVER, "receiver");
+    is(sentSms.sender, SENDER, "sender");
     is(sentSms.messageClass, "normal", "messageClass");
     ok(sentSms.timestamp instanceof Date, "timestamp is istanceof date");
 
     if (gotSmsOnsent && gotReqOnsuccess) { verifySmsExists(smsId); }
   };
 
-  let requestRet = sms.send(destNumber, msgText);
+  let requestRet = sms.send(DEST, msgText);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     gotReqOnsuccess = true;
     if(event.target.result){
       if (gotSmsOnsent && gotReqOnsuccess) { verifySmsExists(smsId); }
     } else {
@@ -72,16 +75,21 @@ function verifySmsExists(smsId) {
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, smsId, "found SMS id matches");
     is(foundSms.body, msgText, "found SMS msg text matches");
+    is(foundSms.delivery, "sent", "delivery");
+    is(foundSms.read, true, "read");
+    is(foundSms.receiver, RECEIVER, "receiver");
+    is(foundSms.sender, SENDER, "sender");
+    is(foundSms.messageClass, "normal", "messageClass");
     log("Got SMS (id: " + foundSms.id + ") as expected.");
     deleteSms(smsId);
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
     is(event.target.error.name, "NotFoundError", "error returned");
new file mode 100644
--- /dev/null
+++ b/dom/sms/tests/marionette/test_outgoing_max_segments.js
@@ -0,0 +1,129 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 20000;
+
+SpecialPowers.setBoolPref("dom.sms.enabled", true);
+SpecialPowers.addPermission("sms", true, document);
+
+let sms = window.navigator.mozSms;
+// https://developer.mozilla.org/en-US/docs/DOM/SmsManager
+let maxCharsPerSms = 160;
+let maxSegments = 10; // 10 message segments concatenated into 1 multipart SMS
+
+function verifyInitialState() {
+  log("Verifying initial state.");
+  ok(sms, "mozSms");
+  sendSms();
+}
+
+function sendSms() {
+  let destNumber = "5551234567";
+  let msgText = "";
+  let gotReqOnSuccess = false;
+  let gotSmsOnSent = false;
+  let sentSms;
+
+  // Build the message text
+  msgText = new Array((maxCharsPerSms * maxSegments) + 1).join('a');
+  log("Sending multipart SMS (" + msgText.length + " chars total).");
+
+  sms.onsent = function(event) {
+    sms.onsent = null;
+    log("Received 'onsent' smsmanager event.");
+
+    gotSmsOnSent = true;
+    sentSms = event.message;
+    ok(sentSms, "outgoing sms");
+    ok(sentSms.id, "sms id");
+    log("Sent SMS (id: " + sentSms.id + ").");
+    is(sentSms.body.length, msgText.length, "text length");
+    is(sentSms.body, msgText, "msg body");
+    is(sentSms.delivery, "sent", "delivery");
+
+    if (gotReqOnSuccess) { verifySmsExists(sentSms); }
+  };
+
+  let requestRet = sms.send(destNumber, msgText);
+  ok(requestRet, "smsrequest obj returned");
+
+  requestRet.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    gotReqOnSuccess = true;
+    if (event.target.result) {
+      if (gotSmsOnSent) { verifySmsExists(sentSms); }
+    } else {
+      log("smsrequest returned false for sms.send");
+      ok(false, "SMS send failed");
+      cleanUp();
+    }
+  };
+
+  requestRet.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    ok(false, "sms.send request returned unexpected error: " +
+              event.target.error.name);
+    cleanUp();
+  };
+}
+
+function verifySmsExists(sentSms) {
+  log("Getting SMS (id: " + sentSms.id + ").");
+  let requestRet = sms.getMessage(sentSms.id);
+  ok(requestRet, "smsrequest obj returned");
+
+  requestRet.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    ok(event.target.result, "smsrequest event.target.result");
+    let foundSms = event.target.result;
+    is(foundSms.id, sentSms.id, "found SMS id matches");
+    is(foundSms.body.length, sentSms.body.length, "found SMS text length");
+    is(foundSms.body, sentSms.body, "found SMS msg text matches");
+    log("Got SMS (id: " + foundSms.id + ") as expected.");
+    deleteSms(sentSms);
+  };
+
+  requestRet.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    is(event.target.error.name, "NotFoundError", "error returned");
+    log("Could not get SMS (id: " + sentSms.id + ") but should have.");
+    ok(false, "SMS was not found");
+    cleanUp();
+  };
+}
+
+function deleteSms(smsMsgObj) {
+  log("Deleting SMS (id: " + smsMsgObj.id + ") using smsmsg obj parameter.");
+  let requestRet = sms.delete(smsMsgObj);
+  ok(requestRet,"smsrequest obj returned");
+
+  requestRet.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    if (event.target.result) {
+      cleanUp();
+    } else {
+      log("smsrequest returned false for sms.delete");
+      ok(false, "SMS delete failed");
+      cleanUp();
+    }
+  };
+
+  requestRet.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 cleanUp() {
+  SpecialPowers.removePermission("sms", document);
+  SpecialPowers.clearUserPref("dom.sms.enabled");
+  finish();
+}
+
+// Start the test
+verifyInitialState();
--- a/dom/src/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/src/jsurl/nsJSProtocolHandler.cpp
@@ -335,16 +335,22 @@ nsresult nsJSThunk::EvaluateScript(nsICh
         // so we shouldn't propagate JS exceptions out of here, or we
         // can't be sure that our caller is JS (and if it's not we'll
         // lose the error), or it might be JS that then proceeds to
         // cause an error of its own (which will also make us lose
         // this error).
         ::JS_ReportPendingException(cx);
     }
 
+    // If we took the sandbox path above, v might be in the sandbox
+    // compartment.
+    if (!JS_WrapValue(cx, &v)) {
+        return NS_ERROR_OUT_OF_MEMORY;
+    }
+
     if (NS_FAILED(rv)) {
         rv = NS_ERROR_MALFORMED_URI;
     }
     else if (v.isUndefined()) {
         rv = NS_ERROR_DOM_RETVAL_UNDEFINED;
     }
     else {
         nsDependentJSString result;
--- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp
+++ b/dom/system/gonk/GonkGPSGeolocationProvider.cpp
@@ -385,21 +385,17 @@ void
 GonkGPSGeolocationProvider::ReleaseDataConnection()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mRIL) {
     return;
   }
 
-  if (mCid.IsEmpty()) {
-    // We didn't request data call or the data call failed, bail out.
-    return;
-  }
-  mRIL->DeactivateDataCall(mCid, NS_LITERAL_STRING("Close SUPL session"));
+  mRIL->DeactivateDataCallByType(NS_LITERAL_STRING("supl"));
 }
 
 void
 GonkGPSGeolocationProvider::RequestSetID(uint32_t flags)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mRIL) {
--- a/dom/system/gonk/GonkGPSGeolocationProvider.h
+++ b/dom/system/gonk/GonkGPSGeolocationProvider.h
@@ -94,12 +94,11 @@ private:
   bool mSupportsTimeInjection;
 
   const GpsInterface* mGpsInterface;
   const AGpsInterface* mAGpsInterface;
   const AGpsRilInterface* mAGpsRilInterface;
   nsCOMPtr<nsIGeolocationUpdate> mLocationCallback;
   nsCOMPtr<nsIThread> mInitThread;
   nsCOMPtr<nsIRadioInterfaceLayer> mRIL;
-  nsAutoString mCid;
 };
 
 #endif /* GonkGPSGeolocationProvider_h */
--- a/dom/system/gonk/NetworkManager.js
+++ b/dom/system/gonk/NetworkManager.js
@@ -206,30 +206,38 @@ NetworkManager.prototype = {
                 network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
                 network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL) {
               this.addHostRoute(network);
             }
             // Remove pre-created default route and let setAndConfigureActive()
             // to set default route only on preferred network
             this.removeDefaultRoute(network.name);
             this.setAndConfigureActive();
+            // Update data connection when Wifi connected/disconnected
+            if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
+              this.mRIL.updateRILNetworkInterface();
+            }
             // Turn on wifi tethering when the callback is set.
             if (this.waitForConnectionReadyCallback) {
               this.waitForConnectionReadyCallback.call(this);
               this.waitForConnectionReadyCallback = null;
             }
             break;
           case Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED:
             // Remove host route for data calls
             if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE ||
                 network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
                 network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL) {
               this.removeHostRoute(network);
             }
             this.setAndConfigureActive();
+            // Update data connection when Wifi connected/disconnected
+            if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
+              this.mRIL.updateRILNetworkInterface();
+            }
             break;
         }
         break;
       case TOPIC_MOZSETTINGS_CHANGED:
         let setting = JSON.parse(data);
         this.handle(setting.key, setting.value);
         break;
       case TOPIC_PREF_CHANGED:
@@ -822,16 +830,22 @@ NetworkManager.prototype = {
     // Disable tethering settings when fail to enable it.
     if (isError(code)) {
       this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
       settingsLock.set("tethering.usb.enabled", false, null);
     }
   }
 };
 
+XPCOMUtils.defineLazyGetter(NetworkManager.prototype, "mRIL", function () {
+    return Cc["@mozilla.org/telephony/system-worker-manager;1"]
+              .getService(Ci.nsIInterfaceRequestor)
+              .getInterface(Ci.nsIRadioInterfaceLayer);
+});
+
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkManager]);
 
 
 let debug;
 if (DEBUG) {
   debug = function (s) {
     dump("-*- NetworkManager: " + s + "\n");
   };
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -148,17 +148,17 @@ function convertRILCallState(state) {
     case RIL.CALL_STATE_HOLDING:
       return nsIRadioInterfaceLayer.CALL_STATE_HELD;
     case RIL.CALL_STATE_DIALING:
       return nsIRadioInterfaceLayer.CALL_STATE_DIALING;
     case RIL.CALL_STATE_ALERTING:
       return nsIRadioInterfaceLayer.CALL_STATE_ALERTING;
     case RIL.CALL_STATE_INCOMING:
     case RIL.CALL_STATE_WAITING:
-      return nsIRadioInterfaceLayer.CALL_STATE_INCOMING; 
+      return nsIRadioInterfaceLayer.CALL_STATE_INCOMING;
     case RIL.CALL_STATE_BUSY:
       return nsIRadioInterfaceLayer.CALL_STATE_BUSY;
     default:
       throw new Error("Unknown rilCallState: " + state);
   }
 }
 
 /**
@@ -605,16 +605,27 @@ RadioInterfaceLayer.prototype = {
         let callback = this._contactsCallbacks[message.requestId];
         if (callback) {
           delete this._contactsCallbacks[message.requestId];
           callback.receiveContactsList(message.errorMsg,
                                        message.contactType,
                                        message.contacts);
         }
         break;
+      case "icccontactupdate":
+        if (!this._contactUpdateCallbacks) {
+          return;
+        }
+        let updateCallback = this._contactUpdateCallbacks[message.requestId];
+        if (updateCallback) {
+          delete this._contactUpdateCallbacks[message.requestId];
+          updateCallback.onUpdated(message.errorMsg,
+                                   message.contactType);
+        }
+        break;
       case "iccmbdn":
         this.handleICCMbdn(message);
         break;
       case "USSDReceived":
         debug("USSDReceived " + JSON.stringify(message));
         this.handleUSSDReceived(message);
         break;
       case "sendMMI":
@@ -1103,23 +1114,23 @@ RadioInterfaceLayer.prototype = {
     }
   },
 
   updateRILNetworkInterface: function updateRILNetworkInterface() {
     if (this._dataCallSettingsToRead.length) {
       debug("We haven't read completely the APN data from the " +
             "settings DB yet. Wait for that.");
       return;
-    } 
-
-    // This check avoids data call connection if the radio is not ready 
-    // yet after toggling off airplane mode. 
+    }
+
+    // This check avoids data call connection if the radio is not ready
+    // yet after toggling off airplane mode.
     if (this.rilContext.radioState != RIL.GECKO_RADIOSTATE_READY) {
       debug("RIL is not ready for data connection: radio's not ready");
-      return; 
+      return;
     }
 
     // We only watch at "ril.data.enabled" flag changes for connecting or
     // disconnecting the data call. If the value of "ril.data.enabled" is
     // true and any of the remaining flags change the setting application
     // should turn this flag to false and then to true in order to reload
     // the new values and reconnect the data call.
     if (this._oldRilDataEnabledState == this.dataCallSettings["enabled"]) {
@@ -1138,32 +1149,42 @@ RadioInterfaceLayer.prototype = {
       dataInfo.state == RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED;
     let haveDataConnection =
       dataInfo.type != RIL.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN;
     if (!isRegistered || !haveDataConnection) {
       debug("RIL is not ready for data connection: Phone's not registered " +
             "or doesn't have data connection.");
       return;
     }
+    let wifi_active = false;
+    if (gNetworkManager.active &&
+        gNetworkManager.active.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
+      wifi_active = true;
+    }
 
     if (this.dataNetworkInterface.connected &&
         (!this.dataCallSettings["enabled"] ||
-         (dataInfo.roaming && !this.dataCallSettings["roaming_enabled"]))) {
+         (dataInfo.roaming && !this.dataCallSettings["roaming_enabled"]) ||
+         (wifi_active && this.shareDefaultAPNCounter == 0))) {
       debug("Data call settings: disconnect data call.");
       this.dataNetworkInterface.disconnect();
       return;
     }
     if (!this.dataCallSettings["enabled"] || this.dataNetworkInterface.connected) {
       debug("Data call settings: nothing to do.");
       return;
     }
     if (dataInfo.roaming && !this.dataCallSettings["roaming_enabled"]) {
       debug("We're roaming, but data roaming is disabled.");
       return;
     }
+    if (wifi_active && this.shareDefaultAPNCounter == 0) {
+      debug("Don't connect data call when Wifi is connected.");
+      return;
+    }
     if (this._changingRadioPower) {
       // We're changing the radio power currently, ignore any changes.
       return;
     }
 
     debug("Data call settings: connect data call.");
     this.dataNetworkInterface.connect(this.dataCallSettings);
   },
@@ -1365,44 +1386,67 @@ RadioInterfaceLayer.prototype = {
     let mwi = message.mwi;
     if (mwi) {
       mwi.returnNumber = message.sender || null;
       mwi.returnMessage = message.fullBody || null;
       this._sendTargetMessage("voicemail", "RIL:VoicemailNotification", mwi);
       return;
     }
 
-    let id = -1;
+    let notifyReceived = function notifyReceived(rv, sms) {
+      let success = Components.isSuccessCode(rv);
+
+      // Acknowledge the reception of the SMS.
+      message.rilMessageType = "ackSMS";
+      if (!success) {
+        message.result = RIL.PDU_FCS_MEMORY_CAPACITY_EXCEEDED;
+      }
+      this.worker.postMessage(message);
+
+      if (!success) {
+        // At this point we could send a message to content to notify the user
+        // that storing an incoming SMS failed, most likely due to a full disk.
+        debug("Could not store SMS " + message.id + ", error code " + rv);
+        return;
+      }
+
+      gSystemMessenger.broadcastMessage("sms-received", {
+          id: message.id,
+          delivery: DOM_SMS_DELIVERY_RECEIVED,
+          deliveryStatus: RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
+          sender: message.sender || null,
+          receiver: message.receiver || null,
+          body: message.fullBody || null,
+          messageClass: message.messageClass,
+          timestamp: message.timestamp,
+          read: false
+      });
+      Services.obs.notifyObservers(sms, kSmsReceivedObserverTopic, null);
+    }.bind(this);
+
     if (message.messageClass != RIL.GECKO_SMS_MESSAGE_CLASSES[RIL.PDU_DCS_MSG_CLASS_0]) {
-      id = gSmsDatabaseService.saveReceivedMessage(message.sender || null,
-                                                   message.fullBody || null,
-                                                   message.messageClass,
-                                                   message.timestamp);
+      message.id = gSmsDatabaseService.saveReceivedMessage(
+          message.sender || null,
+          message.fullBody || null,
+          message.messageClass,
+          message.timestamp,
+          notifyReceived);
+    } else {
+      message.id = -1;
+      let sms = gSmsService.createSmsMessage(message.id,
+                                             DOM_SMS_DELIVERY_RECEIVED,
+                                             RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
+                                             message.sender || null,
+                                             message.receiver || null,
+                                             message.fullBody || null,
+                                             message.messageClass,
+                                             message.timestamp,
+                                             false);
+      notifyReceived(Cr.NS_OK, sms);
     }
-    let sms = gSmsService.createSmsMessage(id,
-                                           DOM_SMS_DELIVERY_RECEIVED,
-                                           RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
-                                           message.sender || null,
-                                           message.receiver || null,
-                                           message.fullBody || null,
-                                           message.messageClass,
-                                           message.timestamp,
-                                           false);
-
-    gSystemMessenger.broadcastMessage("sms-received",
-                                      {id: id,
-                                       delivery: DOM_SMS_DELIVERY_RECEIVED,
-                                       deliveryStatus: RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
-                                       sender: message.sender || null,
-                                       receiver: message.receiver || null,
-                                       body: message.fullBody || null,
-                                       messageClass: message.messageClass,
-                                       timestamp: message.timestamp,
-                                       read: false});
-    Services.obs.notifyObservers(sms, kSmsReceivedObserverTopic, null);
   },
 
   /**
    * Local storage for sent SMS messages.
    */
   _sentSmsEnvelopes: null,
   createSmsEnvelope: function createSmsEnvelope(options) {
     let i;
@@ -1420,78 +1464,62 @@ RadioInterfaceLayer.prototype = {
 
     let options = this._sentSmsEnvelopes[message.envelopeId];
     if (!options) {
       return;
     }
 
     gSmsDatabaseService.setMessageDelivery(options.sms.id,
                                            DOM_SMS_DELIVERY_SENT,
-                                           options.sms.deliveryStatus);
-
-    let sms = gSmsService.createSmsMessage(options.sms.id,
-                                           DOM_SMS_DELIVERY_SENT,
                                            options.sms.deliveryStatus,
-                                           null,
-                                           options.sms.receiver,
-                                           options.sms.body,
-                                           options.sms.messageClass,
-                                           options.sms.timestamp,
-                                           true);
-
-    gSystemMessenger.broadcastMessage("sms-sent",
-                                      {id: options.sms.id,
-                                       delivery: DOM_SMS_DELIVERY_SENT,
-                                       deliveryStatus: options.sms.deliveryStatus,
-                                       sender: message.sender || null,
-                                       receiver: options.sms.receiver,
-                                       body: options.sms.body,
-                                       messageClass: options.sms.messageClass,
-                                       timestamp: options.sms.timestamp,
-                                       read: true});
-
-    if (!options.requestStatusReport) {
-      // No more used if STATUS-REPORT not requested.
-      delete this._sentSmsEnvelopes[message.envelopeId];
-    } else {
-      options.sms = sms;
-    }
-
-    options.request.notifyMessageSent(sms);
-
-    Services.obs.notifyObservers(sms, kSmsSentObserverTopic, null);
+                                           function notifyResult(rv, sms) {
+      //TODO bug 832140 handle !Components.isSuccessCode(rv)
+      gSystemMessenger.broadcastMessage("sms-sent",
+                                        {id: options.sms.id,
+                                         delivery: DOM_SMS_DELIVERY_SENT,
+                                         deliveryStatus: options.sms.deliveryStatus,
+                                         sender: message.sender || null,
+                                         receiver: options.sms.receiver,
+                                         body: options.sms.body,
+                                         messageClass: options.sms.messageClass,
+                                         timestamp: options.sms.timestamp,
+                                         read: true});
+
+      if (!options.requestStatusReport) {
+        // No more used if STATUS-REPORT not requested.
+        delete this._sentSmsEnvelopes[message.envelopeId];
+      } else {
+        options.sms = sms;
+      }
+
+      options.request.notifyMessageSent(sms);
+
+      Services.obs.notifyObservers(sms, kSmsSentObserverTopic, null);
+    }.bind(this));
   },
 
   handleSmsDelivery: function handleSmsDelivery(message) {
     debug("handleSmsDelivery: " + JSON.stringify(message));
 
     let options = this._sentSmsEnvelopes[message.envelopeId];
     if (!options) {
       return;
     }
     delete this._sentSmsEnvelopes[message.envelopeId];
 
     gSmsDatabaseService.setMessageDelivery(options.sms.id,
                                            options.sms.delivery,
-                                           message.deliveryStatus);
-
-    let sms = gSmsService.createSmsMessage(options.sms.id,
-                                           options.sms.delivery,
                                            message.deliveryStatus,
-                                           null,
-                                           options.sms.receiver,
-                                           options.sms.body,
-                                           options.sms.messageClass,
-                                           options.sms.timestamp,
-                                           true);
-
-    let topic = (message.deliveryStatus == RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS)
-                ? kSmsDeliverySuccessObserverTopic
-                : kSmsDeliveryErrorObserverTopic;
-    Services.obs.notifyObservers(sms, topic, null);
+                                           function notifyResult(rv, sms) {
+      //TODO bug 832140 handle !Components.isSuccessCode(rv)
+      let topic = (message.deliveryStatus == RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS)
+                  ? kSmsDeliverySuccessObserverTopic
+                  : kSmsDeliveryErrorObserverTopic;
+      Services.obs.notifyObservers(sms, topic, null);
+    });
   },
 
   handleSmsSendFailed: function handleSmsSendFailed(message) {
     debug("handleSmsSendFailed: " + JSON.stringify(message));
 
     let options = this._sentSmsEnvelopes[message.envelopeId];
     if (!options) {
       return;
@@ -1502,