Merge mozilla-central into build-system
authorMs2ger <ms2ger@gmail.com>
Thu, 03 Jan 2013 10:46:16 +0100
changeset 127814 5d2e27411f1880db908abc4a1d6368d03ef95efc
parent 127813 d6ca11be410942856d09ab0af1efa1ee4bbfbfef (current diff)
parent 126472 6955309291ee4afe219fee09987f3838ccf5ac83 (diff)
child 127815 e250665ff21214b980a8a2577fa790d9c8512f25
push id1
push usersledru@mozilla.com
push dateThu, 04 Dec 2014 17:57:20 +0000
milestone20.0a1
Merge mozilla-central into build-system
Makefile.in
configure.in
content/html/content/src/nsHTMLTitleElement.cpp
mobile/android/base/resources/drawable/abouthome_divider.xml
--- a/Makefile.in
+++ b/Makefile.in
@@ -146,23 +146,16 @@ ifdef MOZ_SYMBOLS_EXTRA_BUILDID
 EXTRA_BUILDID := -$(MOZ_SYMBOLS_EXTRA_BUILDID)
 endif
 
 SYMBOL_INDEX_NAME = \
   $(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_TARGET)-$(BUILDID)-$(CPU_ARCH)$(EXTRA_BUILDID)-symbols.txt
 
 buildsymbols:
 ifdef MOZ_CRASHREPORTER
-ifdef USE_ELF_HACK
-    ifeq (mobile,$(MOZ_BUILD_APP))
-		$(MAKE) -C mobile/xul/installer elfhack
-    else
-		$(MAKE) -C $(MOZ_BUILD_APP)/installer elfhack
-    endif
-endif
 	echo building symbol store
 	$(RM) -r $(DIST)/crashreporter-symbols
 	$(RM) "$(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip"
 	$(NSINSTALL) -D $(DIST)/crashreporter-symbols
 	OBJCOPY="$(OBJCOPY)" \
 	$(PYTHON) $(topsrcdir)/toolkit/crashreporter/tools/symbolstore.py \
 	  $(MAKE_SYM_STORE_ARGS)                                          \
 	  $(foreach dir,$(SYM_STORE_SOURCE_DIRS),-s $(dir))               \
--- a/accessible/src/base/AccEvent.cpp
+++ b/accessible/src/base/AccEvent.cpp
@@ -1,9 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AccEvent.h"
 
 #include "ApplicationAccessibleWrap.h"
 #include "nsAccessibilityService.h"
@@ -112,20 +113,22 @@ AccTextChangeEvent::CreateXPCOMObject()
 // AccReorderEvent
 ////////////////////////////////////////////////////////////////////////////////
 
 uint32_t
 AccReorderEvent::IsShowHideEventTarget(const Accessible* aTarget) const
 {
   uint32_t count = mDependentEvents.Length();
   for (uint32_t index = count - 1; index < count; index--) {
-    if (mDependentEvents[index]->mAccessible == aTarget &&
-        mDependentEvents[index]->mEventType == nsIAccessibleEvent::EVENT_SHOW ||
-        mDependentEvents[index]->mEventType == nsIAccessibleEvent::EVENT_HIDE) {
-      return mDependentEvents[index]->mEventType;
+    if (mDependentEvents[index]->mAccessible == aTarget) {
+      uint32_t eventType = mDependentEvents[index]->mEventType;
+      if (eventType == nsIAccessibleEvent::EVENT_SHOW ||
+          eventType == nsIAccessibleEvent::EVENT_HIDE) {
+        return mDependentEvents[index]->mEventType;
+      }
     }
   }
 
   return 0;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccHideEvent
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -636,17 +636,16 @@ NotificationController::CoalesceTextChan
   }
 
   aTailEvent->mTextChangeEvent.swap(aThisEvent->mTextChangeEvent);
 }
 
 void
 NotificationController::CreateTextChangeEventFor(AccMutationEvent* aEvent)
 {
-  DocAccessible* document = aEvent->GetDocAccessible();
   Accessible* container = aEvent->mAccessible->Parent();
   if (!container)
     return;
 
   HyperTextAccessible* textAccessible = container->AsHyperText();
   if (!textAccessible)
     return;
 
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -1455,16 +1455,19 @@ nsAccessibilityService::CreateAccessible
     case ePluginType: {
       nsObjectFrame* objectFrame = do_QueryFrame(aFrame);
       newAcc = CreatePluginAccessible(objectFrame, aContent, aContext);
       break;
     }
     case eTextLeafType:
       newAcc = new TextLeafAccessibleWrap(aContent, document);
       break;
+    default:
+      MOZ_ASSERT(false);
+      break;
   }
 
   return newAcc.forget();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessibilityService (DON'T put methods here)
 
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -259,16 +259,26 @@ Accessible::Name(nsString& aName)
       aName.CompressWhitespace();
       return eNameFromTooltip;
     }
   } else if (mContent->IsXUL()) {
     if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, aName)) {
       aName.CompressWhitespace();
       return eNameFromTooltip;
     }
+  } else if (mContent->IsSVG()) {
+    // If user agents need to choose among multiple ‘desc’ or ‘title’ elements
+    // for processing, the user agent shall choose the first one.
+    for (nsIContent* childElm = mContent->GetFirstChild(); childElm;
+         childElm = childElm->GetNextSibling()) {
+      if (childElm->IsSVG(nsGkAtoms::title)) {
+        nsTextEquivUtils::AppendTextEquivFromContent(this, childElm, &aName);
+        return eNameFromTooltip;
+      }
+    }
   }
 
   if (nameFlag != eNoNameOnPurpose)
     aName.SetIsVoid(true);
 
   return nameFlag;
 }
 
@@ -302,35 +312,50 @@ Accessible::Description(nsString& aDescr
                            aDescription);
 
   if (aDescription.IsEmpty()) {
     bool isXUL = mContent->IsXUL();
     if (isXUL) {
       // Try XUL <description control="[id]">description text</description>
       XULDescriptionIterator iter(Document(), mContent);
       Accessible* descr = nullptr;
-      while ((descr = iter.Next()))
+      while ((descr = iter.Next())) {
         nsTextEquivUtils::AppendTextEquivFromContent(this, descr->GetContent(),
                                                      &aDescription);
       }
-
-      if (aDescription.IsEmpty()) {
-        nsIAtom *descAtom = isXUL ? nsGkAtoms::tooltiptext :
-                                    nsGkAtoms::title;
-        if (mContent->GetAttr(kNameSpaceID_None, descAtom, aDescription)) {
-          nsAutoString name;
-          Name(name);
-          if (name.IsEmpty() || aDescription == name)
-            // Don't use tooltip for a description if this object
-            // has no name or the tooltip is the same as the name
-            aDescription.Truncate();
+    }
+
+    if (aDescription.IsEmpty()) {
+      // Keep the Name() method logic.
+      if (mContent->IsHTML()) {
+        mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aDescription);
+      } else if (mContent->IsXUL()) {
+        mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, aDescription);
+      } else if (mContent->IsSVG()) {
+        for (nsIContent* childElm = mContent->GetFirstChild(); childElm;
+             childElm = childElm->GetNextSibling()) {
+          if (childElm->IsSVG(nsGkAtoms::title)) {
+            nsTextEquivUtils::AppendTextEquivFromContent(this, childElm,
+                                                         &aDescription);
+            break;
+          }
         }
       }
+
+      if (!aDescription.IsEmpty()) {
+        nsAutoString name;
+        ENameValueFlag nameFlag = Name(name);
+
+        // Don't use tooltip for a description if it was used for a name.
+        if (nameFlag == eNameFromTooltip)
+          aDescription.Truncate();
+      }
     }
-    aDescription.CompressWhitespace();
+  }
+  aDescription.CompressWhitespace();
 }
 
 NS_IMETHODIMP
 Accessible::GetAccessKey(nsAString& aAccessKey)
 {
   aAccessKey.Truncate();
 
   if (IsDefunct())
@@ -2489,16 +2514,28 @@ ENameValueFlag
 Accessible::NativeName(nsString& aName)
 {
   if (mContent->IsHTML())
     return GetHTMLName(aName);
 
   if (mContent->IsXUL())
     return GetXULName(aName);
 
+  if (mContent->IsSVG()) {
+    // If user agents need to choose among multiple ‘desc’ or ‘title’ elements
+    // for processing, the user agent shall choose the first one.
+    for (nsIContent* childElm = mContent->GetFirstChild(); childElm;
+         childElm = childElm->GetNextSibling()) {
+      if (childElm->IsSVG(nsGkAtoms::desc)) {
+        nsTextEquivUtils::AppendTextEquivFromContent(this, childElm, &aName);
+        return eNameOK;
+      }
+    }
+  }
+
   return eNameOK;
 }
 
 // Accessible protected
 void
 Accessible::BindToParent(Accessible* aParent, uint32_t aIndexInParent)
 {
   NS_PRECONDITION(aParent, "This method isn't used to set null parent!");
--- a/accessible/tests/mochitest/name.js
+++ b/accessible/tests/mochitest/name.js
@@ -12,8 +12,21 @@ function testName(aAccOrElmOrID, aName, 
   var txtID = prettyName(aAccOrElmOrID);
   try {
     is(acc.name, aName, msg + "Wrong name of the accessible for " + txtID);
   } catch (e) {
     ok(false, msg + "Can't get name of the accessible for " + txtID);
   }
   return acc;
 }
+
+/**
+ * Test accessible description for the given accessible.
+ */
+function testDescr(aAccOrElmOrID, aDescr)
+{
+  var acc = getAccessible(aAccOrElmOrID);
+  if (!acc)
+   return;
+
+  is(acc.description, aDescr,
+     "Wrong description for " + prettyName(aAccOrElmOrID));
+}
--- a/accessible/tests/mochitest/name/Makefile.in
+++ b/accessible/tests/mochitest/name/Makefile.in
@@ -16,14 +16,15 @@ MOCHITEST_A11Y_FILES =\
 		general.xbl \
 		markup.js \
 		test_button.html \
 		test_general.html \
 		test_general.xul \
 		test_link.html \
 		test_list.html \
 		test_markup.html \
+		test_svg.html \
 		test_browserui.xul \
 		test_tree.xul \
 		markuprules.xml \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/name/test_svg.html
@@ -0,0 +1,56 @@
+<html>
+
+<head>
+  <title>Accessible name and description for SVG elements</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../name.js"></script>
+
+  <script type="application/javascript">
+
+    function doTest()
+    {
+      testName("svg1", "A name");
+      testDescr("svg1", "A description");
+      testName("svg2", "A tooltip");
+      testDescr("svg2", "");
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+
+</head>
+
+<body>
+
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=459357"
+     title="Support accessible name computation for SVG">
+    Mozilla Bug 459357
+  </a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg1">
+    <title>A description</title>
+    <desc>A name</desc>
+  </svg>
+
+  <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="svg2">
+    <title>A tooltip</title>
+  </svg>
+
+</body>
+</html>
--- a/accessible/tests/mochitest/test_descr.html
+++ b/accessible/tests/mochitest/test_descr.html
@@ -3,28 +3,20 @@
 <head>
   <title>nsIAccessible::description tests</title>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript"
           src="common.js"></script>
+  <script type="application/javascript"
+          src="name.js"></script>
 
   <script type="application/javascript">
-    function testDescr(aAccOrElmOrID, aDescr)
-    {
-      var acc = getAccessible(aAccOrElmOrID);
-      if (!acc)
-        return;
-
-      is(acc.description, aDescr,
-         "Wrong description for " + prettyName(aAccOrElmOrID));
-    }
-
     function doTest()
     {
       // Description from aria-describedby attribute
       testDescr("img1", "aria description");
 
       // No description from @title attribute because it is used to generate
       // name.
       testDescr("img2", "");
--- a/b2g/components/UpdatePrompt.js
+++ b/b2g/components/UpdatePrompt.js
@@ -187,25 +187,25 @@ UpdatePrompt.prototype = {
       return;
     }
 
     // Schedule a fallback timeout in case the UI is unable to respond or show
     // a prompt for some reason.
     this._applyPromptTimer = this.createTimer(this.applyPromptTimeout);
   },
 
+  _copyProperties: ["appVersion", "buildID", "detailsURL", "displayVersion",
+                    "errorCode", "isOSUpdate", "platformVersion",
+                    "previousAppVersion", "state", "statusText"],
+
   sendUpdateEvent: function UP_sendUpdateEvent(aType, aUpdate) {
-    let detail = {
-      displayVersion: aUpdate.displayVersion,
-      detailsURL: aUpdate.detailsURL,
-      statusText: aUpdate.statusText,
-      state: aUpdate.state,
-      errorCode: aUpdate.errorCode,
-      isOSUpdate: aUpdate.isOSUpdate
-    };
+    let detail = {};
+    for each (let property in this._copyProperties) {
+      detail[property] = aUpdate[property];
+    }
 
     let patch = aUpdate.selectedPatch;
     if (!patch && aUpdate.patchCount > 0) {
       // For now we just check the first patch to get size information if a
       // patch hasn't been selected yet.
       patch = aUpdate.getPatchAt(0);
     }
 
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1745,17 +1745,16 @@ var BrowserShutdown       = gBrowserInit
 #ifdef XP_MACOSX
 var nonBrowserWindowStartup        = gBrowserInit.nonBrowserWindowStartup.bind(gBrowserInit);
 var nonBrowserWindowDelayedStartup = gBrowserInit.nonBrowserWindowDelayedStartup.bind(gBrowserInit);
 var nonBrowserWindowShutdown       = gBrowserInit.nonBrowserWindowShutdown.bind(gBrowserInit);
 #endif
 
 
 function HandleAppCommandEvent(evt) {
-  evt.stopPropagation();
   switch (evt.command) {
   case "Back":
     BrowserBack();
     break;
   case "Forward":
     BrowserForward();
     break;
   case "Reload":
@@ -1769,19 +1768,45 @@ function HandleAppCommandEvent(evt) {
     BrowserSearch.webSearch();
     break;
   case "Bookmarks":
     toggleSidebar('viewBookmarksSidebar');
     break;
   case "Home":
     BrowserHome();
     break;
-  default:
+  case "New":
+    BrowserOpenTab();
+    break;
+  case "Close":
+    BrowserCloseTabOrWindow();
+    break;
+  case "Find":
+    gFindBar.onFindCommand();
+    break;
+  case "Help":
+    openHelpLink('firefox-help');
+    break;
+  case "Open":
+    BrowserOpenFileWindow();
     break;
+  case "Print":
+    PrintUtils.print();
+    break;
+  case "Save":
+    saveDocument(window.content.document);
+    break;
+  case "SendMail":
+    MailIntegration.sendLinkForWindow(window.content);
+    break;
+  default:
+    return;
   }
+  evt.stopPropagation();
+  evt.preventDefault();
 }
 
 function gotoHistoryIndex(aEvent) {
   let index = aEvent.target.getAttribute("index");
   if (!index)
     return false;
 
   let where = whereToOpenLink(aEvent);
--- a/browser/components/downloads/content/allDownloadsViewOverlay.css
+++ b/browser/components/downloads/content/allDownloadsViewOverlay.css
@@ -16,18 +16,19 @@ richlistitem.download {
 .download-state:not(:-moz-any([state="1"], /* Finished           */
                               [state="2"], /* Failed             */
                               [state="3"], /* Canceled           */
                               [state="6"], /* Blocked (parental) */
                               [state="8"], /* Blocked (dirty)    */
                               [state="9"]) /* Blocked (policy)   */)
                                            .downloadRemoveFromHistoryMenuItem,
 .download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
-                              [state="5"], /* Starting (queued)  */
                               [state="0"], /* Downloading        */
-                              [state="4"]) /* Paused             */)
+                              [state="1"], /* Finished           */
+                              [state="4"], /* Paused             */
+                              [state="5"]) /* Starting (queued)  */)
                                            .downloadShowMenuItem,
 
 .download-state[state="7"]                 .downloadCommandsSeparator
 
 {
   display: none;
 }
--- a/browser/components/downloads/content/contentAreaDownloadsView.js
+++ b/browser/components/downloads/content/contentAreaDownloadsView.js
@@ -1,10 +1,15 @@
 /* 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/. */
 
+Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
+
 let ContentAreaDownloadsView = {
   init: function CADV_init() {
     let view = new DownloadsPlacesView(document.getElementById("downloadsRichListBox"));
-    view.place = "place:transition=7&sort=4";
+    // Do not display the Places downloads in private windows
+    if (!PrivateBrowsingUtils.isWindowPrivate(window)) {
+      view.place = "place:transition=7&sort=4";
+    }
   }
 };
--- a/browser/components/downloads/content/downloads.css
+++ b/browser/components/downloads/content/downloads.css
@@ -52,19 +52,20 @@ richlistitem[type="download"]:not([selec
                               [state="2"], /* Failed             */
                               [state="3"], /* Canceled           */
                               [state="6"], /* Blocked (parental) */
                               [state="8"], /* Blocked (dirty)    */
                               [state="9"]) /* Blocked (policy)   */)
                                            .downloadRemoveFromHistoryMenuItem,
 
 .download-state:not(:-moz-any([state="-1"],/* Starting (initial) */
-                              [state="5"], /* Starting (queued)  */
                               [state="0"], /* Downloading        */
-                              [state="4"]) /* Paused             */)
+                              [state="1"], /* Finished           */
+                              [state="4"], /* Paused             */
+                              [state="5"]) /* Starting (queued)  */)
                                            .downloadShowMenuItem,
 
 .download-state[state="7"]                 .downloadCommandsSeparator
 
 {
   display: none;
 }
 
--- a/browser/components/downloads/src/DownloadsUI.js
+++ b/browser/components/downloads/src/DownloadsUI.js
@@ -27,16 +27,18 @@ Cu.import("resource://gre/modules/XPCOMU
 
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
                                   "resource:///modules/DownloadsCommon.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "gBrowserGlue",
                                    "@mozilla.org/browser/browserglue;1",
                                    "nsIBrowserGlue");
 XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
                                   "resource:///modules/RecentWindow.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
+                                  "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 ////////////////////////////////////////////////////////////////////////////////
 //// DownloadsUI
 
 function DownloadsUI()
 {
   XPCOMUtils.defineLazyGetter(this, "_toolkitUI", function () {
     // Create Toolkit's nsIDownloadManagerUI implementation.
@@ -107,38 +109,43 @@ DownloadsUI.prototype = {
   },
 
   /**
    * Helper function that opens the download manager UI.
    */
   _showDownloadManagerUI:
   function DUI_showDownloadManagerUI(aWindowContext, aID, aReason)
   {
-    let organizer = Services.wm.getMostRecentWindow("Places:Organizer");
-    if (!organizer) {
-      let parentWindow = aWindowContext;
-      // 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.
+    // 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();
       if (!parentWindow) {
-        parentWindow = RecentWindow.getMostRecentBrowserWindow();
-        if (!parentWindow) {
-          Components.utils
-                    .reportError("Couldn't find a browser window to open " +
-                                 "the Places Downloads View from.");
-          return;
-        }
+        Components.utils.reportError(
+          "Couldn't find a browser window to open the Places Downloads View " +
+          "from.");
+        return;
       }
-      parentWindow.openDialog("chrome://browser/content/places/places.xul",
-                              "", "chrome,toolbar=yes,dialog=no,resizable",
-                              "Downloads");
     }
-    else {
-      organizer.PlacesOrganizer.selectLeftPaneQuery("Downloads");
-      organizer.focus();
+
+    // If window is private then show it in a tab.
+    if (PrivateBrowsingUtils.isWindowPrivate(parentWindow)) {
+      parentWindow.openUILinkIn("about:downloads", "tab");
+      return;
+    } else {
+      let organizer = Services.wm.getMostRecentWindow("Places:Organizer");
+      if (!organizer) {
+        parentWindow.openDialog("chrome://browser/content/places/places.xul",
+                                "", "chrome,toolbar=yes,dialog=no,resizable",
+                                "Downloads");
+      } else {
+        organizer.PlacesOrganizer.selectLeftPaneQuery("Downloads");
+        organizer.focus();
+      }
     }
   }
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 //// Module
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DownloadsUI]);
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -905,32 +905,33 @@ BrowserGlue.prototype = {
     /*
      * Display an opt-out notification when telemetry is enabled by default,
      * an opt-in prompt otherwise.
      *
      * But do not display this prompt/notification if:
      *
      * - The last accepted/refused policy (either by accepting the prompt or by
      *   manually flipping the telemetry preference) is already at version
-     *   TELEMETRY_DISPLAY_REV.
+     *   TELEMETRY_DISPLAY_REV or higher (to avoid the prompt in tests).
      */
     var telemetryDisplayed;
     try {
       telemetryDisplayed = Services.prefs.getIntPref(PREF_TELEMETRY_DISPLAYED);
     } catch(e) {}
-    if (telemetryDisplayed === TELEMETRY_DISPLAY_REV)
+    if (telemetryDisplayed >= TELEMETRY_DISPLAY_REV)
       return;
 
 #ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
     /*
      * Additionally, in opt-out builds, don't display the notification if:
      *
      * - Telemetry is disabled
      * - Telemetry was explicitly refused through the UI
-     * - Opt-in telemetry was enabled and this is the first run with opt-out.
+     * - Opt-in telemetry was already enabled, don't notify the user until next
+     *   policy update. (Do the check only at first run with opt-out builds)
      */
 
     var telemetryEnabled = Services.prefs.getBoolPref(PREF_TELEMETRY_ENABLED);
     if (!telemetryEnabled)
       return;
 
     // If telemetry was explicitly refused through the UI,
     // also disable opt-out telemetry and bail out.
--- a/browser/components/preferences/in-content/sync.js
+++ b/browser/components/preferences/in-content/sync.js
@@ -112,17 +112,17 @@ let gSyncPane = {
    * 
    * @param wizardType
    *        Indicates type of wizard to launch:
    *          null    -- regular set up wizard
    *          "pair"  -- pair a device first
    *          "reset" -- reset sync
    */
   openSetup: function (wizardType) {
-    var win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
+    let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
     if (win)
       win.focus();
     else {
       window.openDialog("chrome://browser/content/sync/setup.xul",
                         "weaveSetup", "centerscreen,chrome,resizable=no",
                         wizardType);
     }
   },
@@ -145,11 +145,11 @@ let gSyncPane = {
       win.focus();
     else 
       window.openDialog("chrome://browser/content/sync/addDevice.xul",
                         "syncAddDevice", "centerscreen,chrome,resizable=no");
   },
 
   resetSync: function () {
     this.openSetup("reset");
-  }
-}
+  },
+};
 
--- a/browser/components/preferences/sync.js
+++ b/browser/components/preferences/sync.js
@@ -113,17 +113,17 @@ let gSyncPane = {
    * 
    * @param wizardType
    *        Indicates type of wizard to launch:
    *          null    -- regular set up wizard
    *          "pair"  -- pair a device first
    *          "reset" -- reset sync
    */
   openSetup: function (wizardType) {
-    var win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
+    let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
     if (win)
       win.focus();
     else {
       window.openDialog("chrome://browser/content/sync/setup.xul",
                         "weaveSetup", "centerscreen,chrome,resizable=no",
                         wizardType);
     }
   },
@@ -146,11 +146,11 @@ let gSyncPane = {
       win.focus();
     else 
       window.openDialog("chrome://browser/content/sync/addDevice.xul",
                         "syncAddDevice", "centerscreen,chrome,resizable=no");
   },
 
   resetSync: function () {
     this.openSetup("reset");
-  }
-}
+  },
+};
 
--- a/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_DownloadLastDirWithCPS.js
+++ b/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_DownloadLastDirWithCPS.js
@@ -1,16 +1,17 @@
 /* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 let gTests;
 function test() {
   waitForExplicitFinish();
+  requestLongerTimeout(2);
   gTests = runTest();
   moveAlong();
 }
 
 function moveAlong() {
   try {
     gTests.next();
   } catch (x if x instanceof StopIteration) {
--- a/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_cookieacceptdialog.js
+++ b/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_cookieacceptdialog.js
@@ -30,17 +30,17 @@ function test() {
           if (expectedDisabled)
             is(remember.getAttribute("disabled"), "true",
                "The checkbox should be disabled");
           else
             ok(!remember.hasAttribute("disabled"),
                "The checkbox should not be disabled");
 
           win.close();
-          callback();
+          executeSoon(callback);
         });
       }, false);
     }
     Services.ww.registerNotification(observer);
 
     let remember = {};
     const time = (new Date("Jan 1, 2030")).getTime() / 1000;
     let cookie = {
--- a/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_crh.js
+++ b/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_crh.js
@@ -13,17 +13,17 @@ function test() {
       let crhCommand = aWindow.document.getElementById("Tools:Sanitize");
       ok(crhCommand, "The clear recent history command should exist");
 
       is(PrivateBrowsingUtils.isWindowPrivate(aWindow), aPrivateMode,
         "PrivateBrowsingUtils should report the correct per-window private browsing status");
       is(crhCommand.hasAttribute("disabled"), aPrivateMode,
         "Clear Recent History command should be disabled according to the private browsing mode");
 
-      aCallback();
+      executeSoon(aCallback);
     });
   };
 
   let windowsToClose = [];
   function testOnWindow(options, callback) {
     let win = OpenBrowserWindow(options);
     win.addEventListener("load", function onLoad() {
       win.removeEventListener("load", onLoad, false);
--- a/browser/components/sessionstore/test/browser_819510_perwindowpb.js
+++ b/browser/components/sessionstore/test/browser_819510_perwindowpb.js
@@ -3,17 +3,16 @@
 
 const originalState = ss.getBrowserState();
 
 /** Private Browsing Test for Bug 819510 **/
 function test() {
   waitForExplicitFinish();
 
   registerCleanupFunction(function() {
-    Services.prefs.clearUserPref("browser.sessionstore.interval");
     ss.setBrowserState(originalState);
   });
 
   runNextTest();
 }
 
 let tests = [test_1, test_2, test_3 ];
 
@@ -29,18 +28,16 @@ function runNextTest() {
   // Set an empty state
   closeAllButPrimaryWindow();
 
   // Run the next test, or finish
   if (tests.length) {
     let currentTest = tests.shift();
     waitForBrowserState(testState, currentTest);
   } else {
-    Services.prefs.clearUserPref("browser.sessionstore.interval");
-    ss.setBrowserState(originalState);
     finish();
   }
 }
 
 // Test opening default mochitest-normal-private-normal-private windows
 // (saving the state with last window being private)
 function test_1() {
   testOnWindow(false, function(aWindow) {
@@ -100,82 +97,88 @@ function test_2() {
       });
     });
   });
 }
 
 // Test opening default-normal-private-normal windows and closing a normal window
 function test_3() {
   testOnWindow(false, function(normalWindow) {
-    let tab = normalWindow.gBrowser.addTab("http://www.example.com/1");
-    whenBrowserLoaded(tab.linkedBrowser, function() {
+    waitForTabLoad(normalWindow, "http://www.example.com/", function() {
       testOnWindow(true, function(aWindow) {
-        aWindow.gBrowser.addTab("http://www.example.com/2");
-        testOnWindow(false, function(aWindow) {
-          aWindow.gBrowser.addTab("http://www.example.com/3");
+        waitForTabLoad(aWindow, "http://www.example.com/", function() {
+          testOnWindow(false, function(aWindow) {
+            waitForTabLoad(aWindow, "http://www.example.com/", function() {
 
-          let curState = JSON.parse(ss.getBrowserState());
-          is (curState.windows.length, 4, "Browser has opened 4 windows");
-          is (curState.windows[2].isPrivate, true, "Window 2 is private");
-          is (curState.selectedWindow, 4, "Last window opened is the one selected");
+              let curState = JSON.parse(ss.getBrowserState());
+              is(curState.windows.length, 4, "Browser has opened 4 windows");
+              is(curState.windows[2].isPrivate, true, "Window 2 is private");
+              is(curState.selectedWindow, 4, "Last window opened is the one selected");
 
-          waitForWindowClose(normalWindow, function() {
-            forceWriteState(function(state) {
-              is(state.windows.length, 2,
-                 "sessionstore state: 2 windows in data being writted to disk");
-              is(state.selectedWindow, 2,
-                 "Selected window is updated to match one of the saved windows");
-              state.windows.forEach(function(win) {
-                is(!win.isPrivate, true, "Saved window is not private");
+              waitForWindowClose(normalWindow, function() {
+                forceWriteState(function(state) {
+                  is(state.windows.length, 2,
+                     "sessionstore state: 2 windows in data being writted to disk");
+                  is(state.selectedWindow, 2,
+                     "Selected window is updated to match one of the saved windows");
+                  state.windows.forEach(function(win) {
+                    is(!win.isPrivate, true, "Saved window is not private");
+                  });
+                  is(state._closedWindows.length, 1,
+                     "sessionstore state: 1 closed window in data being writted to disk");
+                  state._closedWindows.forEach(function(win) {
+                    is(!win.isPrivate, true, "Closed window is not private");
+                  });
+                  runNextTest();
+                });
               });
-              is(state._closedWindows.length, 1,
-                 "sessionstore state: 1 closed window in data being writted to disk");
-              state._closedWindows.forEach(function(win) {
-                is(!win.isPrivate, true, "Closed window is not private");
-              });
-              runNextTest();
             });
           });
         });
       });
     });
   });
 }
 
 function waitForWindowClose(aWin, aCallback) {
-  Services.obs.addObserver(function observe(aSubject, aTopic, aData) {
-    if (aTopic == "domwindowclosed" && aWin == aSubject) {
-      Services.obs.removeObserver(observe, aTopic);
-      checkWindowIsClosed(aWin, aCallback);
+  let winCount = JSON.parse(ss.getBrowserState()).windows.length;
+  aWin.addEventListener("SSWindowClosing", function onWindowClosing() {
+    aWin.removeEventListener("SSWindowClosing", onWindowClosing, false);
+    function checkCount() {
+      let state = JSON.parse(ss.getBrowserState());
+      if (state.windows.length == (winCount - 1)) {
+        aCallback();
+      } else {
+        executeSoon(checkCount);
+      }
     }
-  }, "domwindowclosed", false);
+    executeSoon(checkCount);
+  }, false);
   aWin.close();
 }
 
-function checkWindowIsClosed(aWin, aCallback) {
-  if (aWin.closed) {
-    info("Window is closed");
-    executeSoon(aCallback);
-  } else {
-    executeSoon(function() {
-      checkWindowIsClosed(aWin, aCallback);
-    });
-  }
-}
-
 function forceWriteState(aCallback) {
   Services.obs.addObserver(function observe(aSubject, aTopic, aData) {
     if (aTopic == "sessionstore-state-write") {
       Services.obs.removeObserver(observe, aTopic);
+      Services.prefs.clearUserPref("browser.sessionstore.interval");
       aSubject.QueryInterface(Ci.nsISupportsString);
       aCallback(JSON.parse(aSubject.data));
     }
   }, "sessionstore-state-write", false);
   Services.prefs.setIntPref("browser.sessionstore.interval", 0);
 }
 
 function testOnWindow(aIsPrivate, aCallback) {
   let win = OpenBrowserWindow({private: aIsPrivate});
   win.addEventListener("load", function onLoad() {
     win.removeEventListener("load", onLoad, false);
     executeSoon(function() { aCallback(win); });
   }, false);
 }
+
+function waitForTabLoad(aWin, aURL, aCallback) {
+  aWin.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+    aWin.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+    aCallback();
+  }, true);
+  aWin.gBrowser.selectedBrowser.loadURI(aURL);
+}
--- a/browser/config/mozconfigs/win32/debug
+++ b/browser/config/mozconfigs/win32/debug
@@ -13,12 +13,15 @@ if test -z "${_PYMAKE}"; then
 fi
 
 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
   . $topsrcdir/build/win32/mozconfig.vs2010-win64
 else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
 
+# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+ac_add_options --enable-warnings-as-errors
+
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win32/nightly
+++ b/browser/config/mozconfigs/win32/nightly
@@ -22,12 +22,15 @@ if test -z "${_PYMAKE}"; then
 fi
 
 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
   . $topsrcdir/build/win32/mozconfig.vs2010-win64
 else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
 
+# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+ac_add_options --enable-warnings-as-errors
+
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win32/release
+++ b/browser/config/mozconfigs/win32/release
@@ -19,12 +19,15 @@ if test -z "${_PYMAKE}"; then
 fi
 
 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
   . $topsrcdir/build/win32/mozconfig.vs2010-win64
 else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
 
+# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+ac_add_options --enable-warnings-as-errors
+
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win64/debug
+++ b/browser/config/mozconfigs/win64/debug
@@ -8,14 +8,17 @@ ENABLE_MARIONETTE=1
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 if test -z "${_PYMAKE}"; then
   mk_add_options MOZ_MAKE_FLAGS=-j1
 fi
 
+# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+ac_add_options --enable-warnings-as-errors
+
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 . $topsrcdir/build/win64/mozconfig.vs2010
 
 . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/config/mozconfigs/win64/nightly
+++ b/browser/config/mozconfigs/win64/nightly
@@ -17,14 +17,17 @@ ac_add_options --enable-js-diagnostics
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 if test -z "${_PYMAKE}"; then
   mk_add_options MOZ_MAKE_FLAGS=-j1
 fi
 
+# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+ac_add_options --enable-warnings-as-errors
+
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
 . $topsrcdir/build/win64/mozconfig.vs2010
 
 . "$topsrcdir/build/mozconfig.common.override"
--- a/browser/themes/pinstripe/downloads/downloads.css
+++ b/browser/themes/pinstripe/downloads/downloads.css
@@ -13,20 +13,23 @@
   padding: 4px;
   color: inherit;
 }
 
 #downloadsPanel:not([hasdownloads]) > #downloadsListBox {
   display: none;
 }
 
+#downloadsFooter {
+  border-bottom-left-radius: 6px;
+  border-bottom-right-radius: 6px;
+}
+
 #downloadsHistory {
   background: transparent;
-  border-bottom-left-radius: 6px;
-  border-bottom-right-radius: 6px;
   color: hsl(210,100%,75%);
   cursor: pointer;
 }
 
 #downloadsPanel:not([hasdownloads]) > #downloadsFooter > #downloadsHistory {
   border-top-left-radius: 6px;
   border-top-right-radius: 6px;
 }
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -402,18 +402,19 @@ user_pref("test.mousescroll", true);
 user_pref("security.default_personal_cert", "Select Automatically"); // Need to client auth test be w/o any dialogs
 user_pref("network.http.prompt-temp-redirect", false);
 user_pref("media.cache_size", 100);
 user_pref("security.warn_viewing_mixed", false);
 user_pref("app.update.enabled", false);
 user_pref("app.update.staging.enabled", false);
 user_pref("browser.panorama.experienced_first_run", true); // Assume experienced
 user_pref("dom.w3c_touch_events.enabled", 1);
-#expand user_pref("toolkit.telemetry.prompted", __MOZ_TELEMETRY_DISPLAY_REV__);
-#expand user_pref("toolkit.telemetry.notifiedOptOut", __MOZ_TELEMETRY_DISPLAY_REV__);
+// Set a future policy version to avoid the telemetry prompt.
+user_pref("toolkit.telemetry.prompted", 999);
+user_pref("toolkit.telemetry.notifiedOptOut", 999);
 // Existing tests assume there is no font size inflation.
 user_pref("font.size.inflation.emPerLine", 0);
 user_pref("font.size.inflation.minTwips", 0);
 
 // Only load extensions from the application and user profile
 // AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
 user_pref("extensions.enabledScopes", 5);
 // Disable metadata caching for installed add-ons by default
--- a/build/unix/elfhack/elf.cpp
+++ b/build/unix/elfhack/elf.cpp
@@ -580,17 +580,17 @@ void ElfSegment::addSection(ElfSection *
 void ElfSegment::removeSection(ElfSection *section)
 {
     sections.remove(section);
     section->removeFromSegment(this);
 }
 
 unsigned int ElfSegment::getFileSize()
 {
-    if (type == PT_GNU_RELRO)
+    if (type == PT_GNU_RELRO || isElfHackFillerSegment())
         return filesz;
 
     if (sections.empty())
         return 0;
     // Search the last section that is not SHT_NOBITS
     std::list<ElfSection *>::reverse_iterator i;
     for (i = sections.rbegin(); (i != sections.rend()) && ((*i)->getType() == SHT_NOBITS); ++i);
     // All sections are SHT_NOBITS
@@ -599,42 +599,49 @@ unsigned int ElfSegment::getFileSize()
 
     unsigned int end = (*i)->getAddr() + (*i)->getSize();
 
     return end - sections.front()->getAddr();
 }
 
 unsigned int ElfSegment::getMemSize()
 {
-    if (type == PT_GNU_RELRO)
+    if (type == PT_GNU_RELRO || isElfHackFillerSegment())
         return memsz;
 
     if (sections.empty())
         return 0;
 
     unsigned int end = sections.back()->getAddr() + sections.back()->getSize();
 
     return end - sections.front()->getAddr();
 }
 
 unsigned int ElfSegment::getOffset()
 {
     if ((type == PT_GNU_RELRO) && !sections.empty() &&
         (sections.front()->getAddr() != vaddr))
         throw std::runtime_error("PT_GNU_RELRO segment doesn't start on a section start");
 
+    // Neither bionic nor glibc linkers seem to like when the offset of that segment is 0
+    if (isElfHackFillerSegment())
+        return vaddr;
+
     return sections.empty() ? 0 : sections.front()->getOffset();
 }
 
 unsigned int ElfSegment::getAddr()
 {
     if ((type == PT_GNU_RELRO) && !sections.empty() &&
         (sections.front()->getAddr() != vaddr))
         throw std::runtime_error("PT_GNU_RELRO segment doesn't start on a section start");
 
+    if (isElfHackFillerSegment())
+        return vaddr;
+
     return sections.empty() ? 0 : sections.front()->getAddr();
 }
 
 void ElfSegment::clear()
 {
     for (std::list<ElfSection *>::iterator i = sections.begin(); i != sections.end(); ++i)
         (*i)->removeFromSegment(this);
     sections.clear();
--- a/build/unix/elfhack/elfhack.cpp
+++ b/build/unix/elfhack/elfhack.cpp
@@ -371,17 +371,17 @@ void set_relative_reloc(Elf_Rel *rel, El
 
 void set_relative_reloc(Elf_Rela *rel, Elf *elf, unsigned int value) {
     // ld puts the value of relocated relocations both in the addend and
     // at r_offset. For consistency, keep it that way.
     set_relative_reloc((Elf_Rel *)rel, elf, value);
     rel->r_addend = value;
 }
 
-void maybe_split_segment(Elf *elf, ElfSegment *segment)
+void maybe_split_segment(Elf *elf, ElfSegment *segment, bool fill)
 {
     std::list<ElfSection *>::iterator it = segment->begin();
     for (ElfSection *last = *(it++); it != segment->end(); last = *(it++)) {
         // When two consecutive non-SHT_NOBITS sections are apart by more
         // than the alignment of the section, the second can be moved closer
         // to the first, but this requires the segment to be split.
         if (((*it)->getType() != SHT_NOBITS) && (last->getType() != SHT_NOBITS) &&
             ((*it)->getOffset() - last->getOffset() - last->getSize() > segment->getAlign())) {
@@ -391,29 +391,50 @@ void maybe_split_segment(Elf *elf, ElfSe
             phdr.p_vaddr = 0;
             phdr.p_paddr = phdr.p_vaddr + segment->getVPDiff();
             phdr.p_flags = segment->getFlags();
             phdr.p_align = segment->getAlign();
             phdr.p_filesz = (unsigned int)-1;
             phdr.p_memsz = (unsigned int)-1;
             ElfSegment *newSegment = new ElfSegment(&phdr);
             elf->insertSegmentAfter(segment, newSegment);
+            ElfSection *section = *it;
             for (; it != segment->end(); ++it) {
                 newSegment->addSection(*it);
             }
             for (it = newSegment->begin(); it != newSegment->end(); it++) {
                 segment->removeSection(*it);
             }
+            // Fill the virtual address space gap left between the two PT_LOADs
+            // with a new PT_LOAD with no permissions. This avoids the linker
+            // (especially bionic's) filling the gap with anonymous memory,
+            // which breakpad doesn't like.
+            // /!\ running strip on a elfhacked binary will break this filler
+            // PT_LOAD.
+            if (!fill)
+                break;
+            ElfSection *previous = section->getPrevious();
+            phdr.p_vaddr = (previous->getAddr() + previous->getSize() + segment->getAlign() - 1) & ~(segment->getAlign() - 1);
+            phdr.p_paddr = phdr.p_vaddr + segment->getVPDiff();
+            phdr.p_flags = 0;
+            phdr.p_align = 0;
+            phdr.p_filesz = (section->getAddr() & ~(newSegment->getAlign() - 1)) - phdr.p_vaddr;
+            phdr.p_memsz = phdr.p_filesz;
+            if (phdr.p_filesz) {
+                newSegment = new ElfSegment(&phdr);
+                assert(newSegment->isElfHackFillerSegment());
+                elf->insertSegmentAfter(segment, newSegment);
+            }
             break;
         }
     }
 }
 
 template <typename Rel_Type>
-int do_relocation_section(Elf *elf, unsigned int rel_type, unsigned int rel_type2, bool force)
+int do_relocation_section(Elf *elf, unsigned int rel_type, unsigned int rel_type2, bool force, bool fill)
 {
     ElfDynamic_Section *dyn = elf->getDynSection();
     if (dyn ==NULL) {
         fprintf(stderr, "Couldn't find SHT_DYNAMIC section\n");
         return -1;
     }
 
     ElfSegment *relro = elf->getSegmentByType(PT_GNU_RELRO);
@@ -563,17 +584,17 @@ int do_relocation_section(Elf *elf, unsi
     if (section->getOffset() + section->getSize() >= old_end) {
         fprintf(stderr, "No gain. Skipping\n");
         return -1;
     }
 
     // Adjust PT_LOAD segments
     for (ElfSegment *segment = elf->getSegmentByType(PT_LOAD); segment;
          segment = elf->getSegmentByType(PT_LOAD, segment)) {
-        maybe_split_segment(elf, segment);
+        maybe_split_segment(elf, segment, fill);
     }
 
     // Ensure Elf sections will be at their final location.
     elf->normalize();
     ElfLocation *init = new ElfLocation(relhackcode, relhackcode->getEntryPoint());
     if (init_array) {
         // Adjust the first DT_INIT_ARRAY entry to point at the injected code
         // by transforming its relocation into a relative one pointing to the
@@ -594,17 +615,17 @@ int do_relocation_section(Elf *elf, unsi
 
 static inline int backup_file(const char *name)
 {
     std::string fname(name);
     fname += ".bak";
     return rename(name, fname.c_str());
 }
 
-void do_file(const char *name, bool backup = false, bool force = false)
+void do_file(const char *name, bool backup = false, bool force = false, bool fill = false)
 {
     std::ifstream file(name, std::ios::in|std::ios::binary);
     Elf elf(file);
     unsigned int size = elf.getSize();
     fprintf(stderr, "%s: ", name);
     if (elf.getType() != ET_DYN) {
         fprintf(stderr, "Not a shared object. Skipping\n");
         return;
@@ -617,23 +638,23 @@ void do_file(const char *name, bool back
             fprintf(stderr, "Already elfhacked. Skipping\n");
             return;
         }
     }
 
     int exit = -1;
     switch (elf.getMachine()) {
     case EM_386:
-        exit = do_relocation_section<Elf_Rel>(&elf, R_386_RELATIVE, R_386_32, force);
+        exit = do_relocation_section<Elf_Rel>(&elf, R_386_RELATIVE, R_386_32, force, fill);
         break;
     case EM_X86_64:
-        exit = do_relocation_section<Elf_Rela>(&elf, R_X86_64_RELATIVE, R_X86_64_64, force);
+        exit = do_relocation_section<Elf_Rela>(&elf, R_X86_64_RELATIVE, R_X86_64_64, force, fill);
         break;
     case EM_ARM:
-        exit = do_relocation_section<Elf_Rel>(&elf, R_ARM_RELATIVE, R_ARM_ABS32, force);
+        exit = do_relocation_section<Elf_Rel>(&elf, R_ARM_RELATIVE, R_ARM_ABS32, force, fill);
         break;
     }
     if (exit == 0) {
         if (!force && (elf.getSize() >= size)) {
             fprintf(stderr, "No gain. Skipping\n");
         } else if (backup && backup_file(name) != 0) {
             fprintf(stderr, "Couln't create backup file\n");
         } else {
@@ -672,54 +693,65 @@ void undo_file(const char *name, bool ba
     }
     if (data != text->getNext()) {
         fprintf(stderr, elfhack_data " section not following " elfhack_text ". Skipping\n");
         return;
     }
 
     ElfSegment *first = elf.getSegmentByType(PT_LOAD);
     ElfSegment *second = elf.getSegmentByType(PT_LOAD, first);
+    ElfSegment *filler = NULL;
+    // If the second PT_LOAD is a filler from elfhack --fill, check the third.
+    if (!second->isElfHackFillerSegment()) {
+        filler = second;
+        second = elf.getSegmentByType(PT_LOAD, filler);
+    }
     if (second->getFlags() != first->getFlags()) {
-        fprintf(stderr, "First two PT_LOAD segments don't have the same flags. Skipping\n");
+        fprintf(stderr, "Couldn't identify elfhacked PT_LOAD segments. Skipping\n");
         return;
     }
     // Move sections from the second PT_LOAD to the first, and remove the
     // second PT_LOAD segment.
     for (std::list<ElfSection *>::iterator section = second->begin();
          section != second->end(); ++section)
         first->addSection(*section);
 
     elf.removeSegment(second);
+    if (filler)
+        elf.removeSegment(filler);
 
     if (backup && backup_file(name) != 0) {
         fprintf(stderr, "Couln't create backup file\n");
     } else {
         std::ofstream ofile(name, std::ios::out|std::ios::binary|std::ios::trunc);
         elf.write(ofile);
         fprintf(stderr, "Grown by %d bytes\n", elf.getSize() - size);
     }
 }
 
 int main(int argc, char *argv[])
 {
     int arg;
     bool backup = false;
     bool force = false;
     bool revert = false;
+    bool fill = false;
     char *lastSlash = rindex(argv[0], '/');
     if (lastSlash != NULL)
         rundir = strndup(argv[0], lastSlash - argv[0]);
     for (arg = 1; arg < argc; arg++) {
         if (strcmp(argv[arg], "-f") == 0)
             force = true;
         else if (strcmp(argv[arg], "-b") == 0)
             backup = true;
         else if (strcmp(argv[arg], "-r") == 0)
             revert = true;
-        else if (revert)
+        else if (strcmp(argv[arg], "--fill") == 0)
+            fill = true;
+        else if (revert) {
             undo_file(argv[arg], backup);
-        else
-            do_file(argv[arg], backup, force);
+        } else
+            do_file(argv[arg], backup, force, fill);
     }
 
     free(rundir);
     return 0;
 }
--- a/build/unix/elfhack/elfxx.h
+++ b/build/unix/elfhack/elfxx.h
@@ -455,16 +455,20 @@ public:
 
     void addSection(ElfSection *section);
     void removeSection(ElfSection *section);
 
     std::list<ElfSection *>::iterator begin() { return sections.begin(); }
     std::list<ElfSection *>::iterator end() { return sections.end(); }
 
     void clear();
+
+    bool isElfHackFillerSegment() {
+      return type == PT_LOAD && flags == 0;
+    }
 private:
     unsigned int type;
     int v_p_diff; // Difference between physical and virtual address
     unsigned int flags;
     unsigned int align;
     std::list<ElfSection *> sections;
     // The following are only really used for PT_GNU_RELRO until something
     // better is found.
--- a/configure.in
+++ b/configure.in
@@ -3705,18 +3705,18 @@ fi
 
 dnl Using the custom linker on ARMv6 requires 16k alignment of ELF segments.
 if test -n "$MOZ_LINKER"; then
   if test "$CPU_ARCH" = arm; then
     dnl Determine the target ARM architecture (5 for ARMv5, v5T, v5E, etc.; 6 for ARMv6, v6K, etc.)
     ARM_ARCH=`${CC-cc} ${CFLAGS} -dM -E - < /dev/null | sed -n 's/.*__ARM_ARCH_\([[0-9]]*\).*/\1/p'`
     dnl When building for < ARMv7, we need to ensure 16k alignment of ELF segments
     if test -n "$ARM_ARCH" && test "$ARM_ARCH" -lt 7; then
-      LDFLAGS="$LDFLAGS -Wl,-z,max-page-size=0x4000"
-      _SUBDIR_LDFLAGS="$_SUBDIR_LDFLAGS -Wl,-z,max-page-size=0x4000"
+      LDFLAGS="$LDFLAGS -Wl,-z,max-page-size=0x4000 -Wl,-z,common-page-size=0x4000"
+      _SUBDIR_LDFLAGS="$_SUBDIR_LDFLAGS -Wl,-z,max-page-size=0x4000 -Wl,-z,common-page-size=0x4000"
     fi
   fi
 fi
 
 dnl The custom linker doesn't support text relocations, but NDK >= r6b
 dnl creates some (http://code.google.com/p/android/issues/detail?id=23203)
 dnl We however want to avoid these text relocations, and this can be done
 dnl by making gcc not link crtbegin and crtend. In the broken NDKs, crtend
new file mode 100644
--- /dev/null
+++ b/content/base/crashtests/822691.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+
+function boom()
+{
+  var frameDoc = document.getElementById("f").contentDocument;
+
+  var confusedNode = frameDoc.createTextNode("y");
+  confusedNode.__proto__ = document.createTextNode("x");
+  confusedNode.setUserData("key", "data", null);
+  confusedNode.setUserData("key", "data", null);
+}
+
+</script>
+</head>
+<body onload="boom();">
+<iframe src="data:text/html,1" id="f"></iframe>
+</body>
+</html>
--- a/content/base/crashtests/crashtests.list
+++ b/content/base/crashtests/crashtests.list
@@ -114,9 +114,10 @@ load 771639.html
 load 752226-1.html
 load 752226-2.html
 HTTP(..) load xhr_abortinprogress.html
 load 786854.html
 load xhr_empty_datauri.html
 load 815477.html
 load 815500.html
 load 816253.html
+load 822691.html
 load 822723.html
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1936,18 +1936,20 @@ public:
              nsISupports* aResult, mozilla::ErrorResult& rv);
   // Touch event handlers already on nsINode
   already_AddRefed<nsIDOMTouch>
     CreateTouch(nsIDOMWindow* aView, nsISupports* aTarget,
                 int32_t aIdentifier, int32_t aPageX, int32_t aPageY,
                 int32_t aScreenX, int32_t aScreenY, int32_t aClientX,
                 int32_t aClientY, int32_t aRadiusX, int32_t aRadiusY,
                 float aRotationAngle, float aForce);
+  already_AddRefed<nsIDOMTouchList> CreateTouchList();
   already_AddRefed<nsIDOMTouchList>
-    CreateTouchList(nsIDOMTouch* aTouch);
+    CreateTouchList(nsIDOMTouch* aTouch,
+                    const mozilla::dom::Sequence<nsRefPtr<nsIDOMTouch> >& aTouches);
   already_AddRefed<nsIDOMTouchList>
     CreateTouchList(const mozilla::dom::Sequence<nsRefPtr<nsIDOMTouch> >& aTouches);
 
 private:
   uint64_t mWarnedAbout;
 
 protected:
   ~nsIDocument();
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -1869,188 +1869,188 @@ extern const nsIID kThisPtrOffsetsSID;
     NS_INTERFACE_TABLE_ENTRY(_class, _i8)                                     \
     NS_INTERFACE_TABLE_ENTRY(_class, _i9)                                     \
   NS_OFFSET_AND_INTERFACE_TABLE_END                                           \
   NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
 
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsINode, NS_INODE_IID)
 
-#define NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER(_final) \
-  NS_IMETHOD GetNodeName(nsAString& aNodeName) _final \
+#define NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER(...) \
+  NS_IMETHOD GetNodeName(nsAString& aNodeName) __VA_ARGS__ \
   { \
     nsINode::GetNodeName(aNodeName); \
     return NS_OK; \
   } \
-  NS_IMETHOD GetNodeValue(nsAString& aNodeValue) _final \
+  NS_IMETHOD GetNodeValue(nsAString& aNodeValue) __VA_ARGS__ \
   { \
     nsINode::GetNodeValue(aNodeValue); \
     return NS_OK; \
   } \
-  NS_IMETHOD SetNodeValue(const nsAString& aNodeValue) _final \
+  NS_IMETHOD SetNodeValue(const nsAString& aNodeValue) __VA_ARGS__ \
   { \
     mozilla::ErrorResult rv; \
     nsINode::SetNodeValue(aNodeValue, rv); \
     return rv.ErrorCode(); \
   } \
-  NS_IMETHOD GetNodeType(uint16_t* aNodeType) _final \
+  NS_IMETHOD GetNodeType(uint16_t* aNodeType) __VA_ARGS__ \
   { \
     *aNodeType = nsINode::NodeType(); \
     return NS_OK; \
   } \
-  NS_IMETHOD GetParentNode(nsIDOMNode** aParentNode) _final \
+  NS_IMETHOD GetParentNode(nsIDOMNode** aParentNode) __VA_ARGS__ \
   { \
     return nsINode::GetParentNode(aParentNode); \
   } \
-  NS_IMETHOD GetParentElement(nsIDOMElement** aParentElement) _final \
+  NS_IMETHOD GetParentElement(nsIDOMElement** aParentElement) __VA_ARGS__ \
   { \
     return nsINode::GetParentElement(aParentElement); \
   } \
-  NS_IMETHOD GetChildNodes(nsIDOMNodeList** aChildNodes) _final \
+  NS_IMETHOD GetChildNodes(nsIDOMNodeList** aChildNodes) __VA_ARGS__ \
   { \
     return nsINode::GetChildNodes(aChildNodes); \
   } \
-  NS_IMETHOD GetFirstChild(nsIDOMNode** aFirstChild) _final \
+  NS_IMETHOD GetFirstChild(nsIDOMNode** aFirstChild) __VA_ARGS__ \
   { \
     return nsINode::GetFirstChild(aFirstChild); \
   } \
-  NS_IMETHOD GetLastChild(nsIDOMNode** aLastChild) _final \
+  NS_IMETHOD GetLastChild(nsIDOMNode** aLastChild) __VA_ARGS__ \
   { \
     return nsINode::GetLastChild(aLastChild); \
   } \
-  NS_IMETHOD GetPreviousSibling(nsIDOMNode** aPreviousSibling) _final \
+  NS_IMETHOD GetPreviousSibling(nsIDOMNode** aPreviousSibling) __VA_ARGS__ \
   { \
     return nsINode::GetPreviousSibling(aPreviousSibling); \
   } \
-  NS_IMETHOD GetNextSibling(nsIDOMNode** aNextSibling) _final \
+  NS_IMETHOD GetNextSibling(nsIDOMNode** aNextSibling) __VA_ARGS__ \
   { \
     return nsINode::GetNextSibling(aNextSibling); \
   } \
-  NS_IMETHOD GetAttributes(nsIDOMNamedNodeMap** aAttributes) _final \
+  NS_IMETHOD GetAttributes(nsIDOMNamedNodeMap** aAttributes) __VA_ARGS__ \
   { \
     return nsINode::GetAttributes(aAttributes); \
   } \
-  NS_IMETHOD GetOwnerDocument(nsIDOMDocument** aOwnerDocument) _final \
+  NS_IMETHOD GetOwnerDocument(nsIDOMDocument** aOwnerDocument) __VA_ARGS__ \
   { \
     return nsINode::GetOwnerDocument(aOwnerDocument); \
   } \
-  NS_IMETHOD InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNode** aResult) _final \
+  NS_IMETHOD InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNode** aResult) __VA_ARGS__ \
   { \
     return ReplaceOrInsertBefore(false, aNewChild, aRefChild, aResult); \
   } \
-  NS_IMETHOD ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNode** aResult) _final \
+  NS_IMETHOD ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNode** aResult) __VA_ARGS__ \
   { \
     return ReplaceOrInsertBefore(true, aNewChild, aOldChild, aResult); \
   } \
-  NS_IMETHOD RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aResult) _final \
+  NS_IMETHOD RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aResult) __VA_ARGS__ \
   { \
     return nsINode::RemoveChild(aOldChild, aResult); \
   } \
-  NS_IMETHOD AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aResult) _final \
+  NS_IMETHOD AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aResult) __VA_ARGS__ \
   { \
     return InsertBefore(aNewChild, nullptr, aResult); \
   } \
-  NS_IMETHOD HasChildNodes(bool* aResult) _final \
+  NS_IMETHOD HasChildNodes(bool* aResult) __VA_ARGS__ \
   { \
     *aResult = nsINode::HasChildNodes(); \
     return NS_OK; \
   } \
-  NS_IMETHOD CloneNode(bool aDeep, uint8_t aArgc, nsIDOMNode** aResult) _final \
+  NS_IMETHOD CloneNode(bool aDeep, uint8_t aArgc, nsIDOMNode** aResult) __VA_ARGS__ \
   { \
     if (aArgc == 0) { \
       aDeep = true; \
     } \
     mozilla::ErrorResult rv; \
     nsCOMPtr<nsINode> clone = nsINode::CloneNode(aDeep, rv); \
     if (rv.Failed()) { \
       return rv.ErrorCode(); \
     } \
     *aResult = clone.forget().get()->AsDOMNode(); \
     return NS_OK; \
   } \
-  NS_IMETHOD Normalize() _final \
+  NS_IMETHOD Normalize() __VA_ARGS__ \
   { \
     nsINode::Normalize(); \
     return NS_OK; \
   } \
-  NS_IMETHOD IsSupported(const nsAString& aFeature, const nsAString& aVersion, bool* aResult) _final \
+  NS_IMETHOD IsSupported(const nsAString& aFeature, const nsAString& aVersion, bool* aResult) __VA_ARGS__ \
   { \
     *aResult = nsINode::IsSupported(aFeature, aVersion); \
     return NS_OK; \
   } \
-  NS_IMETHOD GetNamespaceURI(nsAString& aNamespaceURI) _final \
+  NS_IMETHOD GetNamespaceURI(nsAString& aNamespaceURI) __VA_ARGS__ \
   { \
     mozilla::ErrorResult rv; \
     nsINode::GetNamespaceURI(aNamespaceURI, rv); \
     return rv.ErrorCode(); \
   } \
-  NS_IMETHOD GetPrefix(nsAString& aPrefix) _final \
+  NS_IMETHOD GetPrefix(nsAString& aPrefix) __VA_ARGS__ \
   { \
     nsINode::GetPrefix(aPrefix); \
     return NS_OK; \
   } \
-  NS_IMETHOD GetLocalName(nsAString& aLocalName) _final \
+  NS_IMETHOD GetLocalName(nsAString& aLocalName) __VA_ARGS__ \
   { \
     nsINode::GetLocalName(aLocalName); \
     return NS_OK; \
   } \
   using nsINode::HasAttributes; \
-  NS_IMETHOD HasAttributes(bool* aResult) _final \
+  NS_IMETHOD HasAttributes(bool* aResult) __VA_ARGS__ \
   { \
     *aResult = nsINode::HasAttributes(); \
     return NS_OK; \
   } \
-  NS_IMETHOD GetDOMBaseURI(nsAString& aBaseURI) _final \
+  NS_IMETHOD GetDOMBaseURI(nsAString& aBaseURI) __VA_ARGS__ \
   { \
     nsINode::GetBaseURI(aBaseURI); \
     return NS_OK; \
   } \
-  NS_IMETHOD CompareDocumentPosition(nsIDOMNode* aOther, uint16_t* aResult) _final \
+  NS_IMETHOD CompareDocumentPosition(nsIDOMNode* aOther, uint16_t* aResult) __VA_ARGS__ \
   { \
     return nsINode::CompareDocumentPosition(aOther, aResult); \
   } \
-  NS_IMETHOD GetTextContent(nsAString& aTextContent) _final \
+  NS_IMETHOD GetTextContent(nsAString& aTextContent) __VA_ARGS__ \
   { \
     nsINode::GetTextContent(aTextContent); \
     return NS_OK; \
   } \
-  NS_IMETHOD SetTextContent(const nsAString& aTextContent) _final \
+  NS_IMETHOD SetTextContent(const nsAString& aTextContent) __VA_ARGS__ \
   { \
     mozilla::ErrorResult rv; \
     nsINode::SetTextContent(aTextContent, rv); \
     return rv.ErrorCode(); \
   } \
-  NS_IMETHOD LookupPrefix(const nsAString& aNamespaceURI, nsAString& aResult) _final \
+  NS_IMETHOD LookupPrefix(const nsAString& aNamespaceURI, nsAString& aResult) __VA_ARGS__ \
   { \
     nsINode::LookupPrefix(aNamespaceURI, aResult); \
     return NS_OK; \
   } \
-  NS_IMETHOD IsDefaultNamespace(const nsAString& aNamespaceURI, bool* aResult) _final \
+  NS_IMETHOD IsDefaultNamespace(const nsAString& aNamespaceURI, bool* aResult) __VA_ARGS__ \
   { \
     *aResult = nsINode::IsDefaultNamespace(aNamespaceURI); \
     return NS_OK; \
   } \
-  NS_IMETHOD LookupNamespaceURI(const nsAString& aPrefix, nsAString& aResult) _final \
+  NS_IMETHOD LookupNamespaceURI(const nsAString& aPrefix, nsAString& aResult) __VA_ARGS__ \
   { \
     nsINode::LookupNamespaceURI(aPrefix, aResult); \
     return NS_OK; \
   } \
-  NS_IMETHOD IsEqualNode(nsIDOMNode* aArg, bool* aResult) _final \
+  NS_IMETHOD IsEqualNode(nsIDOMNode* aArg, bool* aResult) __VA_ARGS__ \
   { \
     return nsINode::IsEqualNode(aArg, aResult); \
   } \
-  NS_IMETHOD SetUserData(const nsAString& aKey, nsIVariant* aData, nsIDOMUserDataHandler* aHandler, nsIVariant** aResult) _final \
+  NS_IMETHOD SetUserData(const nsAString& aKey, nsIVariant* aData, nsIDOMUserDataHandler* aHandler, nsIVariant** aResult) __VA_ARGS__ \
   { \
     return nsINode::SetUserData(aKey, aData, aHandler, aResult); \
   } \
-  NS_IMETHOD GetUserData(const nsAString& aKey, nsIVariant** aResult) _final \
+  NS_IMETHOD GetUserData(const nsAString& aKey, nsIVariant** aResult) __VA_ARGS__ \
   { \
     return nsINode::GetUserData(aKey, aResult); \
   } \
-  NS_IMETHOD Contains(nsIDOMNode* aOther, bool* aResult) _final \
+  NS_IMETHOD Contains(nsIDOMNode* aOther, bool* aResult) __VA_ARGS__ \
   { \
     return nsINode::Contains(aOther, aResult); \
   }
 
 #define NS_FORWARD_NSIDOMNODE_TO_NSINODE \
   NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER(MOZ_FINAL)
 
 #define NS_FORWARD_NSIDOMNODE_TO_NSINODE_OVERRIDABLE \
--- a/content/base/src/nsDOMBlobBuilder.h
+++ b/content/base/src/nsDOMBlobBuilder.h
@@ -120,17 +120,18 @@ protected:
     using mozilla::CheckedUint32;
 
     if (mDataBufferLen >= mDataLen + aSize) {
       mDataLen += aSize;
       return true;
     }
 
     // Start at 1 or we'll loop forever.
-    CheckedUint32 bufferLen = NS_MAX<uint32_t>(mDataBufferLen, 1);
+    CheckedUint32 bufferLen =
+      NS_MAX<uint32_t>(static_cast<uint32_t>(mDataBufferLen), 1);
     while (bufferLen.isValid() && bufferLen.value() < mDataLen + aSize)
       bufferLen *= 2;
 
     if (!bufferLen.isValid())
       return false;
 
     void* data = moz_realloc(mData, bufferLen.value());
     if (!data)
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -610,18 +610,17 @@ nsDOMMemoryFile::GetInternalStream(nsIIn
 }
 
 /* static */ StaticAutoPtr<LinkedList<nsDOMMemoryFile::DataOwner> >
 nsDOMMemoryFile::DataOwner::sDataOwners;
 
 /* static */ bool
 nsDOMMemoryFile::DataOwner::sMemoryReporterRegistered;
 
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMMemoryFileDataOwnerSizeOf,
-                                     "memory-file-data");
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMMemoryFileDataOwnerMallocSizeOf)
 
 class nsDOMMemoryFileDataOwnerMemoryReporter MOZ_FINAL
   : public nsIMemoryMultiReporter
 {
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD GetName(nsACString& aName)
   {
@@ -646,17 +645,17 @@ class nsDOMMemoryFileDataOwnerMemoryRepo
     }
 
     const size_t LARGE_OBJECT_MIN_SIZE = 8 * 1024;
     size_t smallObjectsTotal = 0;
 
     for (DataOwner *owner = DataOwner::sDataOwners->getFirst();
          owner; owner = owner->getNext()) {
 
-      size_t size = DOMMemoryFileDataOwnerSizeOf(owner->mData);
+      size_t size = DOMMemoryFileDataOwnerMallocSizeOf(owner->mData);
 
       if (size < LARGE_OBJECT_MIN_SIZE) {
         smallObjectsTotal += size;
       }
       else {
         SHA1Sum sha1;
         sha1.update(owner->mData, owner->mLength);
         uint8_t digest[SHA1Sum::HashSize]; // SHA1 digests are 20 bytes long.
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -8671,20 +8671,31 @@ nsDocument::CreateTouchList(nsIVariant* 
     }
   }
 
   *aRetVal = retval.forget().get();
   return NS_OK;
 }
 
 already_AddRefed<nsIDOMTouchList>
-nsIDocument::CreateTouchList(nsIDOMTouch* aTouch)
+nsIDocument::CreateTouchList()
+{
+  nsRefPtr<nsDOMTouchList> retval = new nsDOMTouchList();
+  return retval.forget();
+}
+
+already_AddRefed<nsIDOMTouchList>
+nsIDocument::CreateTouchList(nsIDOMTouch* aTouch,
+                             const Sequence<nsRefPtr<nsIDOMTouch> >& aTouches)
 {
   nsRefPtr<nsDOMTouchList> retval = new nsDOMTouchList();
   retval->Append(aTouch);
+  for (uint32_t i = 0; i < aTouches.Length(); ++i) {
+    retval->Append(aTouches[i]);
+  }
   return retval.forget();
 }
 
 already_AddRefed<nsIDOMTouchList>
 nsIDocument::CreateTouchList(const Sequence<nsRefPtr<nsIDOMTouch> >& aTouches)
 {
   nsRefPtr<nsDOMTouchList> retval = new nsDOMTouchList();
   for (uint32_t i = 0; i < aTouches.Length(); ++i) {
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -2009,16 +2009,26 @@ GK_ATOM(Reload, "Reload")
 GK_ATOM(Stop, "Stop")
 GK_ATOM(Search, "Search")
 GK_ATOM(Bookmarks, "Bookmarks")
 GK_ATOM(Home, "Home")
 GK_ATOM(Clear, "Clear")
 GK_ATOM(VolumeUp, "VolumeUp")
 GK_ATOM(VolumeDown, "VolumeDown")
 GK_ATOM(Menu, "Menu")
+GK_ATOM(New, "New")
+GK_ATOM(Open, "Open")
+GK_ATOM(Close, "Close")
+GK_ATOM(Save, "Save")
+GK_ATOM(Find, "Find")
+GK_ATOM(Help, "Help")
+GK_ATOM(Print, "Print")
+GK_ATOM(SendMail, "SendMail")
+GK_ATOM(ForwardMail, "ForwardMail")
+GK_ATOM(ReplyToMail, "ReplyToMail")
 
 // Smooth scroll events origins
 GK_ATOM(mouseWheel, "mouseWheel")  // For discrete wheel events (e.g. not OSX magic mouse)
 GK_ATOM(pixels,     "pixels")
 GK_ATOM(lines,      "lines")
 GK_ATOM(pages,      "pages")
 GK_ATOM(scrollbars, "scrollbars")
 GK_ATOM(other,      "other")
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -693,30 +693,32 @@ nsINode::SetUserData(JSContext* aCx, con
     return JS::UndefinedValue();
   }
 
   if (!oldData) {
     return JS::NullValue();
   }
 
   JS::Value result;
+  JSAutoCompartment ac(aCx, GetWrapper());
   aError = nsContentUtils::XPConnect()->VariantToJS(aCx, GetWrapper(), oldData,
                                                     &result);
   return result;
 }
 
 JS::Value
 nsINode::GetUserData(JSContext* aCx, const nsAString& aKey, ErrorResult& aError)
 {
   nsIVariant* data = GetUserData(aKey);
   if (!data) {
     return JS::NullValue();
   }
 
   JS::Value result;
+  JSAutoCompartment ac(aCx, GetWrapper());
   aError = nsContentUtils::XPConnect()->VariantToJS(aCx, GetWrapper(), data,
                                                     &result);
   return result;
 }
 
 uint16_t
 nsINode::CompareDocumentPosition(nsINode& aOtherNode) const
 {
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -137,18 +137,16 @@ nsImageLoadingContent::Notify(imgIReques
   if (aType == imgINotificationObserver::LOAD_COMPLETE) {
     // We should definitely have a request here
     NS_ABORT_IF_FALSE(aRequest, "no request?");
 
     NS_PRECONDITION(aRequest == mCurrentRequest || aRequest == mPendingRequest,
                     "Unknown request");
   }
 
-  NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
-
   LOOP_OVER_OBSERVERS(Notify(aRequest, aType, aData));
 
   if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
     // Have to check for state changes here, since we might have been in
     // the LOADING state before.
     UpdateImageState(true);
   }
 
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -3,23 +3,24 @@
 # 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/.
 
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
-FAIL_ON_WARNINGS = 1
-
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 LIBRARY_NAME	= gkconcvs_s
 LIBXUL_LIBRARY  = 1
+ifndef _MSC_VER
+FAIL_ON_WARNINGS = 1
+endif # !_MSC_VER
 
 EXPORTS_NAMESPACES = mozilla/dom
 
 EXPORTS_mozilla/dom = \
 	CanvasUtils.h \
 	CanvasRenderingContext2D.h \
   ImageData.h \
   $(NULL)
--- a/content/canvas/src/WebGLContextReporter.cpp
+++ b/content/canvas/src/WebGLContextReporter.cpp
@@ -135,42 +135,42 @@ WebGLMemoryMultiReporterWrapper::WebGLMe
     NS_RegisterMemoryMultiReporter(mReporter);
 }
 
 WebGLMemoryMultiReporterWrapper::~WebGLMemoryMultiReporterWrapper()
 {
     NS_UnregisterMemoryMultiReporter(mReporter);
 }
 
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WebGLBufferMallocSizeOfFun, "webgl-buffer")
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WebGLBufferMallocSizeOf)
 
 int64_t 
 WebGLMemoryMultiReporterWrapper::GetBufferCacheMemoryUsed() {
     const ContextsArrayType & contexts = Contexts();
     int64_t result = 0;
     for(size_t i = 0; i < contexts.Length(); ++i) {
         for (const WebGLBuffer *buffer = contexts[i]->mBuffers.getFirst();
              buffer;
              buffer = buffer->getNext())
         {
             if (buffer->Target() == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
-                result += buffer->SizeOfIncludingThis(WebGLBufferMallocSizeOfFun);
+                result += buffer->SizeOfIncludingThis(WebGLBufferMallocSizeOf);
         }
     }
     return result;
 }
 
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WebGLShaderMallocSizeOfFun, "webgl-shader")
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WebGLShaderMallocSizeOf)
 
 int64_t 
 WebGLMemoryMultiReporterWrapper::GetShaderSize() {
     const ContextsArrayType & contexts = Contexts();
     int64_t result = 0;
     for(size_t i = 0; i < contexts.Length(); ++i) {
         for (const WebGLShader *shader = contexts[i]->mShaders.getFirst();
              shader;
              shader = shader->getNext())
         {
-            result += shader->SizeOfIncludingThis(WebGLShaderMallocSizeOfFun);
+            result += shader->SizeOfIncludingThis(WebGLShaderMallocSizeOf);
         }
     }
     return result;
 }
--- a/content/events/src/Makefile.in
+++ b/content/events/src/Makefile.in
@@ -8,17 +8,19 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 LIBRARY_NAME	= gkconevents_s
 LIBXUL_LIBRARY  = 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS = 1
+endif # !_MSC_VER
 
 EXPORTS		= \
 		nsEventStateManager.h \
 		nsEventListenerManager.h \
 		nsDOMEventTargetHelper.h \
 		nsDOMEvent.h \
 		nsDOMTouchEvent.h \
 		nsDOMUIEvent.h \
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/HTMLTitleElement.cpp
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/HTMLTitleElement.h"
+
+#include "mozilla/dom/HTMLTitleElementBinding.h"
+#include "mozilla/ErrorResult.h"
+#include "nsStyleConsts.h"
+#include "nsIDocument.h"
+#include "nsContentUtils.h"
+
+
+NS_IMPL_NS_NEW_HTML_ELEMENT(Title)
+
+namespace mozilla {
+namespace dom {
+
+HTMLTitleElement::HTMLTitleElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+  : nsGenericHTMLElement(aNodeInfo)
+{
+  SetIsDOMBinding();
+  AddMutationObserver(this);
+}
+
+HTMLTitleElement::~HTMLTitleElement()
+{
+}
+
+
+NS_IMPL_ADDREF_INHERITED(HTMLTitleElement, Element)
+NS_IMPL_RELEASE_INHERITED(HTMLTitleElement, Element)
+
+} // namespace dom
+} // namespace mozilla
+
+DOMCI_NODE_DATA(HTMLTitleElement, mozilla::dom::HTMLTitleElement)
+
+namespace mozilla {
+namespace dom {
+
+// QueryInterface implementation for HTMLTitleElement
+NS_INTERFACE_TABLE_HEAD(HTMLTitleElement)
+  NS_HTML_CONTENT_INTERFACE_TABLE2(HTMLTitleElement,
+                                   nsIDOMHTMLTitleElement,
+                                   nsIMutationObserver)
+  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLTitleElement,
+                                               nsGenericHTMLElement)
+NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLTitleElement)
+
+
+NS_IMPL_ELEMENT_CLONE(HTMLTitleElement)
+
+JSObject*
+HTMLTitleElement::WrapNode(JSContext* cx, JSObject* scope, bool* triedToWrap)
+{
+  return HTMLTitleElementBinding::Wrap(cx, scope, this, triedToWrap);
+}
+
+
+NS_IMETHODIMP 
+HTMLTitleElement::GetText(nsAString& aTitle)
+{
+  nsContentUtils::GetNodeTextContent(this, false, aTitle);
+  return NS_OK;
+}
+
+NS_IMETHODIMP 
+HTMLTitleElement::SetText(const nsAString& aTitle)
+{
+  return nsContentUtils::SetNodeTextContent(this, aTitle, true);
+}
+
+void
+HTMLTitleElement::CharacterDataChanged(nsIDocument *aDocument,
+                                       nsIContent *aContent,
+                                       CharacterDataChangeInfo *aInfo)
+{
+  SendTitleChangeEvent(false);
+}
+
+void
+HTMLTitleElement::ContentAppended(nsIDocument *aDocument,
+                                  nsIContent *aContainer,
+                                  nsIContent *aFirstNewContent,
+                                  int32_t aNewIndexInContainer)
+{
+  SendTitleChangeEvent(false);
+}
+
+void
+HTMLTitleElement::ContentInserted(nsIDocument *aDocument,
+                                  nsIContent *aContainer,
+                                  nsIContent *aChild,
+                                  int32_t aIndexInContainer)
+{
+  SendTitleChangeEvent(false);
+}
+
+void
+HTMLTitleElement::ContentRemoved(nsIDocument *aDocument,
+                                 nsIContent *aContainer,
+                                 nsIContent *aChild,
+                                 int32_t aIndexInContainer,
+                                 nsIContent *aPreviousSibling)
+{
+  SendTitleChangeEvent(false);
+}
+
+nsresult
+HTMLTitleElement::BindToTree(nsIDocument *aDocument,
+                             nsIContent *aParent,
+                             nsIContent *aBindingParent,
+                             bool aCompileEventHandlers)
+{
+  // Let this fall through.
+  nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
+                                                 aBindingParent,
+                                                 aCompileEventHandlers);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  SendTitleChangeEvent(true);
+
+  return NS_OK;
+}
+
+void
+HTMLTitleElement::UnbindFromTree(bool aDeep, bool aNullParent)
+{
+  SendTitleChangeEvent(false);
+
+  // Let this fall through.
+  nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
+}
+
+void
+HTMLTitleElement::DoneAddingChildren(bool aHaveNotified)
+{
+  if (!aHaveNotified) {
+    SendTitleChangeEvent(false);
+  }
+}
+
+void
+HTMLTitleElement::SendTitleChangeEvent(bool aBound)
+{
+  nsIDocument* doc = GetCurrentDoc();
+  if (doc) {
+    doc->NotifyPossibleTitleChange(aBound);
+  }
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/HTMLTitleElement.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_HTMLTITLEElement_h_
+#define mozilla_dom_HTMLTITLEElement_h_
+
+#include "mozilla/Attributes.h"
+#include "nsIDOMHTMLTitleElement.h"
+#include "nsGenericHTMLElement.h"
+#include "nsStubMutationObserver.h"
+
+namespace mozilla {
+class ErrorResult;
+
+namespace dom {
+
+class HTMLTitleElement : public nsGenericHTMLElement,
+                         public nsIDOMHTMLTitleElement,
+                         public nsStubMutationObserver
+{
+public:
+  using Element::GetText;
+  using Element::SetText;
+
+  HTMLTitleElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  virtual ~HTMLTitleElement();
+
+  // nsISupports
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // nsIDOMNode
+  NS_FORWARD_NSIDOMNODE_TO_NSINODE
+
+  // nsIDOMElement
+  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
+
+  // nsIDOMHTMLElement
+  NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
+
+  // nsIDOMHTMLTitleElement
+  NS_DECL_NSIDOMHTMLTITLEELEMENT
+
+  //HTMLTitleElement
+  //The xpcom GetTextContent() never fails so we just use that.
+  void SetText(const nsAString& aText, ErrorResult& aError)
+  {
+    aError = SetText(aText);
+  }
+
+  // nsIMutationObserver
+  NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
+  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
+
+  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+  virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
+                              nsIContent *aBindingParent,
+                              bool aCompileEventHandlers);
+
+  virtual void UnbindFromTree(bool aDeep = true,
+                              bool aNullParent = true);
+
+  virtual void DoneAddingChildren(bool aHaveNotified);
+
+  virtual nsXPCClassInfo* GetClassInfo();
+
+  virtual nsIDOMNode* AsDOMNode() { return this; }
+
+protected:
+
+  virtual JSObject* WrapNode(JSContext* cx, JSObject* scope, bool* triedToWrap)
+    MOZ_OVERRIDE MOZ_FINAL;
+
+private:
+  void SendTitleChangeEvent(bool aBound);
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_HTMLTitleElement_h_
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -8,17 +8,19 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 LIBRARY_NAME	= gkconhtmlcon_s
 LIBXUL_LIBRARY	= 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS = 1
+endif # !_MSC_VER
 
 
 EXPORTS		= \
 		HTMLPropertiesCollection.h \
 		nsGenericHTMLElement.h \
 		nsHTMLIFrameElement.h \
 		nsClientRect.h \
 		nsHTMLDNSPrefetch.h \
@@ -30,16 +32,17 @@ EXPORTS_NAMESPACES = mozilla/dom
 EXPORTS_mozilla/dom = \
 		HTMLBodyElement.h \
 		HTMLDataListElement.h \
 		HTMLDivElement.h \
 		HTMLFontElement.h \
 		HTMLFrameSetElement.h \
 		HTMLHeadingElement.h \
 		HTMLLabelElement.h \
+		HTMLTitleElement.h \
 		HTMLUnknownElement.h
 
 CPPSRCS		= \
 		HTMLPropertiesCollection.cpp \
 		nsClientRect.cpp \
 		nsHTMLDNSPrefetch.cpp \
 		nsGenericHTMLElement.cpp \
 		nsGenericHTMLFrameElement.cpp \
@@ -90,17 +93,17 @@ CPPSRCS		= \
 		nsHTMLStyleElement.cpp \
 		nsHTMLTableElement.cpp \
 		nsHTMLTableCaptionElement.cpp \
 		nsHTMLTableCellElement.cpp \
 		nsHTMLTableColElement.cpp \
 		nsHTMLTableRowElement.cpp \
 		nsHTMLTableSectionElement.cpp \
 		nsHTMLTextAreaElement.cpp \
-		nsHTMLTitleElement.cpp \
+		HTMLTitleElement.cpp \
 		HTMLUnknownElement.cpp \
 		nsDOMValidityState.cpp \
 		nsIConstraintValidation.cpp \
 		nsRadioVisitor.cpp \
 		nsDOMStringMap.cpp \
 		$(NULL)
 
 ifdef MOZ_MEDIA
deleted file mode 100644
--- a/content/html/content/src/nsHTMLTitleElement.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "nsIDOMHTMLTitleElement.h"
-#include "nsIDOMEventTarget.h"
-#include "nsGenericHTMLElement.h"
-#include "nsStyleConsts.h"
-#include "nsIDocument.h"
-#include "nsContentUtils.h"
-#include "nsStubMutationObserver.h"
-
-using namespace mozilla::dom;
-
-class nsHTMLTitleElement : public nsGenericHTMLElement,
-                           public nsIDOMHTMLTitleElement,
-                           public nsStubMutationObserver
-{
-public:
-  using Element::GetText;
-  using Element::SetText;
-
-  nsHTMLTitleElement(already_AddRefed<nsINodeInfo> aNodeInfo);
-  virtual ~nsHTMLTitleElement();
-
-  // nsISupports
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-
-  // nsIDOMElement
-  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
-
-  // nsIDOMHTMLElement
-  NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
-
-  // nsIDOMHTMLTitleElement
-  NS_DECL_NSIDOMHTMLTITLEELEMENT
-
-  // nsIMutationObserver
-  NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
-  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
-  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
-  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
-
-  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-
-  virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
-                              nsIContent *aBindingParent,
-                              bool aCompileEventHandlers);
-
-  virtual void UnbindFromTree(bool aDeep = true,
-                              bool aNullParent = true);
-
-  virtual void DoneAddingChildren(bool aHaveNotified);
-
-  virtual nsXPCClassInfo* GetClassInfo();
-
-  virtual nsIDOMNode* AsDOMNode() { return this; }
-private:
-  void SendTitleChangeEvent(bool aBound);
-};
-
-
-NS_IMPL_NS_NEW_HTML_ELEMENT(Title)
-
-
-nsHTMLTitleElement::nsHTMLTitleElement(already_AddRefed<nsINodeInfo> aNodeInfo)
-  : nsGenericHTMLElement(aNodeInfo)
-{
-  AddMutationObserver(this);
-}
-
-nsHTMLTitleElement::~nsHTMLTitleElement()
-{
-}
-
-
-NS_IMPL_ADDREF_INHERITED(nsHTMLTitleElement, Element)
-NS_IMPL_RELEASE_INHERITED(nsHTMLTitleElement, Element)
-
-
-DOMCI_NODE_DATA(HTMLTitleElement, nsHTMLTitleElement)
-
-// QueryInterface implementation for nsHTMLTitleElement
-NS_INTERFACE_TABLE_HEAD(nsHTMLTitleElement)
-  NS_HTML_CONTENT_INTERFACE_TABLE2(nsHTMLTitleElement,
-                                   nsIDOMHTMLTitleElement,
-                                   nsIMutationObserver)
-  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLTitleElement,
-                                               nsGenericHTMLElement)
-NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLTitleElement)
-
-
-NS_IMPL_ELEMENT_CLONE(nsHTMLTitleElement)
-
-
-NS_IMETHODIMP 
-nsHTMLTitleElement::GetText(nsAString& aTitle)
-{
-  nsContentUtils::GetNodeTextContent(this, false, aTitle);
-  return NS_OK;
-}
-
-NS_IMETHODIMP 
-nsHTMLTitleElement::SetText(const nsAString& aTitle)
-{
-  return nsContentUtils::SetNodeTextContent(this, aTitle, true);
-}
-
-void
-nsHTMLTitleElement::CharacterDataChanged(nsIDocument *aDocument,
-                                         nsIContent *aContent,
-                                         CharacterDataChangeInfo *aInfo)
-{
-  SendTitleChangeEvent(false);
-}
-
-void
-nsHTMLTitleElement::ContentAppended(nsIDocument *aDocument,
-                                    nsIContent *aContainer,
-                                    nsIContent *aFirstNewContent,
-                                    int32_t aNewIndexInContainer)
-{
-  SendTitleChangeEvent(false);
-}
-
-void
-nsHTMLTitleElement::ContentInserted(nsIDocument *aDocument,
-                                    nsIContent *aContainer,
-                                    nsIContent *aChild,
-                                    int32_t aIndexInContainer)
-{
-  SendTitleChangeEvent(false);
-}
-
-void
-nsHTMLTitleElement::ContentRemoved(nsIDocument *aDocument,
-                                   nsIContent *aContainer,
-                                   nsIContent *aChild,
-                                   int32_t aIndexInContainer,
-                                   nsIContent *aPreviousSibling)
-{
-  SendTitleChangeEvent(false);
-}
-
-nsresult
-nsHTMLTitleElement::BindToTree(nsIDocument *aDocument,
-                               nsIContent *aParent,
-                               nsIContent *aBindingParent,
-                               bool aCompileEventHandlers)
-{
-  // Let this fall through.
-  nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
-                                                 aBindingParent,
-                                                 aCompileEventHandlers);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  SendTitleChangeEvent(true);
-
-  return NS_OK;
-}
-
-void
-nsHTMLTitleElement::UnbindFromTree(bool aDeep, bool aNullParent)
-{
-  SendTitleChangeEvent(false);
-
-  // Let this fall through.
-  nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
-}
-
-void
-nsHTMLTitleElement::DoneAddingChildren(bool aHaveNotified)
-{
-  if (!aHaveNotified) {
-    SendTitleChangeEvent(false);
-  }
-}
-
-void
-nsHTMLTitleElement::SendTitleChangeEvent(bool aBound)
-{
-  nsIDocument* doc = GetCurrentDoc();
-  if (doc) {
-    doc->NotifyPossibleTitleChange(aBound);
-  }
-}
--- a/content/html/document/src/Makefile.in
+++ b/content/html/document/src/Makefile.in
@@ -8,17 +8,19 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 LIBRARY_NAME	= gkconhtmldoc_s
 LIBXUL_LIBRARY	= 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS = 1
+endif # !_MSC_VER
 
 CPPSRCS		= \
 		nsHTMLContentSink.cpp \
 		nsHTMLDocument.cpp \
 		ImageDocument.cpp \
 		MediaDocument.cpp \
 		PluginDocument.cpp \
 		$(NULL)
--- a/content/mathml/content/src/Makefile.in
+++ b/content/mathml/content/src/Makefile.in
@@ -8,17 +8,19 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 LIBRARY_NAME	= gkcontentmathml_s
 LIBXUL_LIBRARY	= 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS = 1
+endif # !_MSC_VER
 
 CPPSRCS		= \
 		nsMathMLElement.cpp               \
 		nsMathMLElementFactory.cpp        \
 		$(NULL)
 
 include $(topsrcdir)/config/config.mk
 
--- a/content/media/Makefile.in
+++ b/content/media/Makefile.in
@@ -1,23 +1,25 @@
 # 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/.
 
 DEPTH     = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
-FAIL_ON_WARNINGS := 1
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = content
 LIBRARY_NAME = gkconmedia_s
 LIBXUL_LIBRARY = 1
+ifndef _MSC_VER
+FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 EXPORTS = \
   AbstractMediaDecoder.h \
   AudioSampleFormat.h \
   AudioSegment.h \
   BufferMediaResource.h \
   DecoderTraits.h \
   FileBlockCache.h \
--- a/content/media/MediaDecoder.h
+++ b/content/media/MediaDecoder.h
@@ -223,16 +223,22 @@ static const uint32_t FRAMEBUFFER_LENGTH
 // has to be within the following range.
 static const uint32_t FRAMEBUFFER_LENGTH_MIN = 512;
 static const uint32_t FRAMEBUFFER_LENGTH_MAX = 16384;
 
 static inline bool IsCurrentThread(nsIThread* aThread) {
   return NS_GetCurrentThread() == aThread;
 }
 
+// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
+// GetTickCount() and conflicts with MediaDecoder::GetCurrentTime implementation.
+#ifdef GetCurrentTime
+#undef GetCurrentTime
+#endif
+
 class MediaDecoder : public nsIObserver,
                      public AbstractMediaDecoder
 {
 public:
   typedef mozilla::layers::Image Image;
   class DecodedStreamMainThreadListener;
 
   NS_DECL_ISUPPORTS
--- a/content/media/MediaSegment.h
+++ b/content/media/MediaSegment.h
@@ -210,16 +210,17 @@ protected:
   MediaSegmentBase(Type aType) : MediaSegment(aType) {}
 
   /**
    * Appends the contents of aSource to this segment, clearing aSource.
    */
   void AppendFromInternal(MediaSegmentBase<C, Chunk>* aSource)
   {
     static_cast<C*>(this)->CheckCompatible(*static_cast<C*>(aSource));
+    MOZ_ASSERT(aSource->mDuration >= 0);
     mDuration += aSource->mDuration;
     aSource->mDuration = 0;
     if (!mChunks.IsEmpty() && !aSource->mChunks.IsEmpty() &&
         mChunks[mChunks.Length() - 1].CanCombineWithFollowing(aSource->mChunks[0])) {
       mChunks[mChunks.Length() - 1].mDuration += aSource->mChunks[0].mDuration;
       aSource->mChunks.RemoveElementAt(0);
     }
     mChunks.MoveElementsFrom(aSource->mChunks);
@@ -243,16 +244,17 @@ protected:
         mChunks.AppendElement(c)->SliceTo(start - offset, end - offset);
       }
       offset = nextOffset;
     }
   }
 
   Chunk* AppendChunk(TrackTicks aDuration)
   {
+    MOZ_ASSERT(aDuration >= 0);
     Chunk* c = mChunks.AppendElement();
     c->mDuration = aDuration;
     mDuration += aDuration;
     return c;
   }
 
   Chunk* FindChunkContaining(TrackTicks aOffset, TrackTicks* aStart = nullptr)
   {
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -797,31 +797,29 @@ MediaStreamGraphImpl::UpdateCurrentTime(
   }
 
   for (uint32_t i = 0; i < mStreams.Length(); ++i) {
     MediaStream* stream = mStreams[i];
 
     // Calculate blocked time and fire Blocked/Unblocked events
     GraphTime blockedTime = 0;
     GraphTime t = prevCurrentTime;
-    // Save current blocked status
-    bool wasBlocked = stream->mBlocked.GetAt(prevCurrentTime);
     while (t < nextCurrentTime) {
       GraphTime end;
       bool blocked = stream->mBlocked.GetAt(t, &end);
       if (blocked) {
         blockedTime += NS_MIN(end, nextCurrentTime) - t;
       }
-      if (blocked != wasBlocked) {
+      if (blocked != stream->mNotifiedBlocked) {
         for (uint32_t j = 0; j < stream->mListeners.Length(); ++j) {
           MediaStreamListener* l = stream->mListeners[j];
           l->NotifyBlockingChanged(this,
               blocked ? MediaStreamListener::BLOCKED : MediaStreamListener::UNBLOCKED);
         }
-        wasBlocked = blocked;
+        stream->mNotifiedBlocked = blocked;
       }
       t = end;
     }
 
     stream->AdvanceTimeVaryingValuesToCurrentTime(nextCurrentTime, blockedTime);
     // Advance mBlocked last so that implementations of
     // AdvanceTimeVaryingValuesToCurrentTime can rely on the value of mBlocked.
     stream->mBlocked.AdvanceCurrentTime(nextCurrentTime);
@@ -1936,17 +1934,17 @@ MediaStream::ChangeExplicitBlockerCount(
   GraphImpl()->AppendMessage(new Message(this, aDelta));
 }
 
 void
 MediaStream::AddListenerImpl(already_AddRefed<MediaStreamListener> aListener)
 {
   MediaStreamListener* listener = *mListeners.AppendElement() = aListener;
   listener->NotifyBlockingChanged(GraphImpl(),
-    mBlocked.GetAt(GraphImpl()->mCurrentTime) ? MediaStreamListener::BLOCKED : MediaStreamListener::UNBLOCKED);
+    mNotifiedBlocked ? MediaStreamListener::BLOCKED : MediaStreamListener::UNBLOCKED);
   if (mNotifiedFinished) {
     listener->NotifyFinished(GraphImpl());
   }
 }
 
 void
 MediaStream::AddListener(MediaStreamListener* aListener)
 {
--- a/content/media/MediaStreamGraph.h
+++ b/content/media/MediaStreamGraph.h
@@ -256,16 +256,17 @@ public:
 
   MediaStream(nsDOMMediaStream* aWrapper)
     : mBufferStartTime(0)
     , mExplicitBlockerCount(0)
     , mBlocked(false)
     , mGraphUpdateIndices(0)
     , mFinished(false)
     , mNotifiedFinished(false)
+    , mNotifiedBlocked(false)
     , mWrapper(aWrapper)
     , mMainThreadCurrentTime(0)
     , mMainThreadFinished(false)
     , mMainThreadDestroyed(false)
   {
   }
   virtual ~MediaStream() {}
 
@@ -452,16 +453,21 @@ protected:
    * buffered data has been consumed.
    */
   bool mFinished;
   /**
    * When true, mFinished is true and we've played all the data in this stream
    * and fired NotifyFinished notifications.
    */
   bool mNotifiedFinished;
+  /**
+   * When true, the last NotifyBlockingChanged delivered to the listeners
+   * indicated that the stream is blocked.
+   */
+  bool mNotifiedBlocked;
 
   // Temporary data for ordering streams by dependency graph
   bool mHasBeenOrdered;
   bool mIsOnOrderingStack;
   // True if the stream is being consumed (i.e. has track data being played,
   // or is feeding into some stream that is being consumed).
   bool mIsConsumed;
   // Temporary data for computing blocking status of streams
--- a/content/media/ogg/Makefile.in
+++ b/content/media/ogg/Makefile.in
@@ -1,23 +1,25 @@
 # 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/.
 
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
-FAIL_ON_WARNINGS := 1
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 LIBRARY_NAME	= gkconogg_s
 LIBXUL_LIBRARY 	= 1
+ifndef _MSC_VER
+FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 
 EXPORTS		+= \
 		OggDecoder.h \
 		OggCodecState.h \
 		OggReader.h \
 		$(NULL)
 
--- a/content/media/raw/Makefile.in
+++ b/content/media/raw/Makefile.in
@@ -2,23 +2,25 @@
 # 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/.
 
 
 DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
-FAIL_ON_WARNINGS := 1
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = content
 LIBRARY_NAME = gkconraw_s
 LIBXUL_LIBRARY = 1
+ifndef _MSC_VER
+FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 EXPORTS += \
   RawDecoder.h \
   RawReader.h \
   RawStructs.h \
   $(NULL)
 
 CPPSRCS += \
--- a/content/media/webaudio/Makefile.in
+++ b/content/media/webaudio/Makefile.in
@@ -1,23 +1,25 @@
 # 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/.
 
 DEPTH            := @DEPTH@
 topsrcdir        := @top_srcdir@
 srcdir           := @srcdir@
 VPATH            := @srcdir@
-FAIL_ON_WARNINGS := 1
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE         := content
 LIBRARY_NAME   := gkconwebaudio_s
 LIBXUL_LIBRARY := 1
+ifndef _MSC_VER
+FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 CPPSRCS := \
   AudioBuffer.cpp \
   AudioBufferSourceNode.cpp \
   AudioContext.cpp \
   AudioDestinationNode.cpp \
   AudioListener.cpp \
   AudioNode.cpp \
--- a/content/media/webaudio/compiledtest/Makefile.in
+++ b/content/media/webaudio/compiledtest/Makefile.in
@@ -2,19 +2,22 @@
 # 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/.
 
 DEPTH          := @DEPTH@
 topsrcdir      := @top_srcdir@
 srcdir         := @srcdir@
 VPATH          := @srcdir@
 relativesrcdir := @relativesrcdir@
-FAIL_ON_WARNINGS = 1
 
 include $(DEPTH)/config/autoconf.mk
 
+ifndef _MSC_VER
+FAIL_ON_WARNINGS = 1
+endif # !_MSC_VER
+
 LOCAL_INCLUDES := -I$(srcdir)/..
 
 CPP_UNIT_TESTS := \
   TestAudioEventTimeline.cpp \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/content/media/webrtc/MediaEngine.h
+++ b/content/media/webrtc/MediaEngine.h
@@ -23,16 +23,22 @@ class MediaEngineAudioSource;
 
 enum MediaEngineState {
   kAllocated,
   kStarted,
   kStopped,
   kReleased
 };
 
+// We only support 1 audio and 1 video track for now.
+enum {
+  kVideoTrack = 1,
+  kAudioTrack = 2
+};
+
 class MediaEngine
 {
 public:
   virtual ~MediaEngine() {}
 
   /* Populate an array of video sources in the nsTArray. Also include devices
    * that are currently unavailable. */
   virtual void EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSource> >*) = 0;
@@ -69,20 +75,24 @@ public:
 
   /* Take a snapshot from this source. In the case of video this is a single
    * image, and for audio, it is a snippet lasting aDuration milliseconds. The
    * duration argument is ignored for a MediaEngineVideoSource.
    */
   virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile) = 0;
 
   /* Called when the stream wants more data */
-  virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime) = 0;
+  virtual void NotifyPull(MediaStreamGraph* aGraph,
+                          SourceMediaStream *aSource,
+                          TrackID aId,
+                          StreamTime aDesiredTime,
+                          TrackTicks &aLastEndTime) = 0;
 
   /* Stop the device and release the corresponding MediaStream */
-  virtual nsresult Stop() = 0;
+  virtual nsresult Stop(SourceMediaStream *aSource, TrackID aID) = 0;
 
   /* Return false if device is currently allocated or started */
   bool IsAvailable() {
     if (mState == kAllocated || mState == kStarted) {
       return false;
     } else {
       return true;
     }
--- a/content/media/webrtc/MediaEngineDefault.cpp
+++ b/content/media/webrtc/MediaEngineDefault.cpp
@@ -163,30 +163,30 @@ MediaEngineDefaultVideoSource::Start(Sou
   // Start timer for subsequent frames
   mTimer->InitWithCallback(this, 1000 / DEFAULT_FPS, nsITimer::TYPE_REPEATING_SLACK);
   mState = kStarted;
 
   return NS_OK;
 }
 
 nsresult
-MediaEngineDefaultVideoSource::Stop()
+MediaEngineDefaultVideoSource::Stop(SourceMediaStream *aSource, TrackID aID)
 {
   if (mState != kStarted) {
     return NS_ERROR_FAILURE;
   }
   if (!mTimer) {
     return NS_ERROR_FAILURE;
   }
 
   mTimer->Cancel();
   mTimer = NULL;
 
-  mSource->EndTrack(mTrackID);
-  mSource->Finish();
+  aSource->EndTrack(aID);
+  aSource->Finish();
 
   mState = kStopped;
   return NS_OK;
 }
 
 nsresult
 MediaEngineDefaultVideoSource::Snapshot(uint32_t aDuration, nsIDOMFile** aFile)
 {
@@ -348,30 +348,30 @@ MediaEngineDefaultAudioSource::Start(Sou
   // 1 Audio frame per Video frame
   mTimer->InitWithCallback(this, 1000 / MediaEngineDefaultVideoSource::DEFAULT_FPS, nsITimer::TYPE_REPEATING_SLACK);
   mState = kStarted;
 
   return NS_OK;
 }
 
 nsresult
-MediaEngineDefaultAudioSource::Stop()
+MediaEngineDefaultAudioSource::Stop(SourceMediaStream *aSource, TrackID aID)
 {
   if (mState != kStarted) {
     return NS_ERROR_FAILURE;
   }
   if (!mTimer) {
     return NS_ERROR_FAILURE;
   }
 
   mTimer->Cancel();
   mTimer = NULL;
 
-  mSource->EndTrack(mTrackID);
-  mSource->Finish();
+  aSource->EndTrack(aID);
+  aSource->Finish();
 
   mState = kStopped;
   return NS_OK;
 }
 
 nsresult
 MediaEngineDefaultAudioSource::Snapshot(uint32_t aDuration, nsIDOMFile** aFile)
 {
--- a/content/media/webrtc/MediaEngineDefault.h
+++ b/content/media/webrtc/MediaEngineDefault.h
@@ -37,19 +37,24 @@ public:
 
   virtual void GetName(nsAString&);
   virtual void GetUUID(nsAString&);
 
   virtual const MediaEngineVideoOptions *GetOptions();
   virtual nsresult Allocate();
   virtual nsresult Deallocate();
   virtual nsresult Start(SourceMediaStream*, TrackID);
-  virtual nsresult Stop();
+  virtual nsresult Stop(SourceMediaStream*, TrackID);
   virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile);
   virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime);
+  virtual void NotifyPull(MediaStreamGraph* aGraph,
+                          SourceMediaStream *aSource,
+                          TrackID aId,
+                          StreamTime aDesiredTime,
+                          TrackTicks &aLastEndTime) {}
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
 
   // Need something better...
   static const int DEFAULT_WIDTH=640;
   static const int DEFAULT_HEIGHT=480;
   static const int DEFAULT_FPS=30;
@@ -74,19 +79,24 @@ public:
   ~MediaEngineDefaultAudioSource();
 
   virtual void GetName(nsAString&);
   virtual void GetUUID(nsAString&);
 
   virtual nsresult Allocate();
   virtual nsresult Deallocate();
   virtual nsresult Start(SourceMediaStream*, TrackID);
-  virtual nsresult Stop();
+  virtual nsresult Stop(SourceMediaStream*, TrackID);
   virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile);
   virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime);
+  virtual void NotifyPull(MediaStreamGraph* aGraph,
+                          SourceMediaStream *aSource,
+                          TrackID aId,
+                          StreamTime aDesiredTime,
+                          TrackTicks &aLastEndTime) {}
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
 
 protected:
   TrackID mTrackID;
   nsCOMPtr<nsITimer> mTimer;
 
--- a/content/media/webrtc/MediaEngineWebRTC.h
+++ b/content/media/webrtc/MediaEngineWebRTC.h
@@ -83,19 +83,23 @@ public:
   ~MediaEngineWebRTCVideoSource() { Shutdown(); }
 
   virtual void GetName(nsAString&);
   virtual void GetUUID(nsAString&);
   virtual const MediaEngineVideoOptions *GetOptions();
   virtual nsresult Allocate();
   virtual nsresult Deallocate();
   virtual nsresult Start(SourceMediaStream*, TrackID);
-  virtual nsresult Stop();
+  virtual nsresult Stop(SourceMediaStream*, TrackID);
   virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile);
-  virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime);
+  virtual void NotifyPull(MediaStreamGraph* aGraph,
+                          SourceMediaStream *aSource,
+                          TrackID aId,
+                          StreamTime aDesiredTime,
+                          TrackTicks &aLastEndTime);
 
   NS_DECL_ISUPPORTS
 
   // This runnable is for creating a temporary file on the main thread.
   NS_IMETHODIMP
   Run()
   {
     nsCOMPtr<nsIFile> tmp;
@@ -131,17 +135,17 @@ private:
 
   int mCaptureIndex;
   bool mCapabilityChosen;
   int mWidth, mHeight;
   TrackID mTrackID;
   TrackTicks mLastEndTime;
 
   mozilla::ReentrantMonitor mMonitor; // Monitor for processing WebRTC frames.
-  SourceMediaStream* mSource;
+  nsTArray<SourceMediaStream *> mSources; // When this goes empty, we shut down HW
 
   int mFps; // Track rate (30 fps by default)
   int mMinFps; // Min rate we want to accept
   bool mInitDone;
   bool mInSnapshotMode;
   nsString* mSnapshotPath;
 
   nsRefPtr<layers::Image> mImage;
@@ -179,19 +183,23 @@ public:
   ~MediaEngineWebRTCAudioSource() { Shutdown(); }
 
   virtual void GetName(nsAString&);
   virtual void GetUUID(nsAString&);
 
   virtual nsresult Allocate();
   virtual nsresult Deallocate();
   virtual nsresult Start(SourceMediaStream*, TrackID);
-  virtual nsresult Stop();
+  virtual nsresult Stop(SourceMediaStream*, TrackID);
   virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile);
-  virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime);
+  virtual void NotifyPull(MediaStreamGraph* aGraph,
+                          SourceMediaStream *aSource,
+                          TrackID aId,
+                          StreamTime aDesiredTime,
+                          TrackTicks &aLastEndTime);
 
   // VoEMediaProcess.
   void Process(const int channel, const webrtc::ProcessingTypes type,
                WebRtc_Word16 audio10ms[], const int length,
                const int samplingFreq, const bool isStereo);
 
   NS_DECL_ISUPPORTS
 
@@ -203,26 +211,26 @@ private:
   void Shutdown();
 
   webrtc::VoiceEngine* mVoiceEngine;
   webrtc::VoEBase* mVoEBase;
   webrtc::VoEExternalMedia* mVoERender;
   webrtc::VoENetwork*  mVoENetwork;
 
   mozilla::ReentrantMonitor mMonitor;
+  nsTArray<SourceMediaStream *> mSources; // When this goes empty, we shut down HW
 
   int mCapIndex;
   int mChannel;
   TrackID mTrackID;
   bool mInitDone;
 
   nsString mDeviceName;
   nsString mDeviceUUID;
 
-  SourceMediaStream* mSource;
   NullTransport *mNullTransport;
 };
 
 class MediaEngineWebRTC : public MediaEngine
 {
 public:
   MediaEngineWebRTC()
   : mMutex("mozilla::MediaEngineWebRTC")
--- a/content/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -44,115 +44,130 @@ MediaEngineWebRTCAudioSource::GetUUID(ns
   }
 
   return;
 }
 
 nsresult
 MediaEngineWebRTCAudioSource::Allocate()
 {
-  if (mState != kReleased) {
-    return NS_ERROR_FAILURE;
+  if (mState == kReleased && mInitDone) {
+    webrtc::VoEHardware* ptrVoEHw = webrtc::VoEHardware::GetInterface(mVoiceEngine);
+    int res = ptrVoEHw->SetRecordingDevice(mCapIndex);
+    ptrVoEHw->Release();
+    if (res) {
+      return NS_ERROR_FAILURE;
+    }
+    mState = kAllocated;
+    LOG(("Audio device %d allocated", mCapIndex));
+  } else if (mSources.IsEmpty()) {
+    LOG(("Audio device %d reallocated", mCapIndex));
+  } else {
+    LOG(("Audio device %d allocated shared", mCapIndex));
   }
-
-  webrtc::VoEHardware* ptrVoEHw = webrtc::VoEHardware::GetInterface(mVoiceEngine);
-  int res = ptrVoEHw->SetRecordingDevice(mCapIndex);
-  ptrVoEHw->Release();
-  if (res) {
-    return NS_ERROR_FAILURE;
-  }
-
-  LOG(("Audio device %d allocated", mCapIndex));
-  mState = kAllocated;
   return NS_OK;
 }
 
 nsresult
 MediaEngineWebRTCAudioSource::Deallocate()
 {
-  if (mState != kStopped && mState != kAllocated) {
-    return NS_ERROR_FAILURE;
+  if (mSources.IsEmpty()) {
+    if (mState != kStopped && mState != kAllocated) {
+      return NS_ERROR_FAILURE;
+    }
+
+    mState = kReleased;
+    LOG(("Audio device %d deallocated", mCapIndex));
+  } else {
+    LOG(("Audio device %d deallocated but still in use", mCapIndex));
   }
-
-  mState = kReleased;
   return NS_OK;
 }
 
 nsresult
 MediaEngineWebRTCAudioSource::Start(SourceMediaStream* aStream, TrackID aID)
 {
-  if (!mInitDone || mState != kAllocated) {
-    return NS_ERROR_FAILURE;
-  }
-  if (!aStream) {
+  if (!mInitDone || !aStream) {
     return NS_ERROR_FAILURE;
   }
 
-  mSource = aStream;
+  mSources.AppendElement(aStream);
 
   AudioSegment* segment = new AudioSegment();
   segment->Init(CHANNELS);
-  mSource->AddTrack(aID, SAMPLE_FREQUENCY, 0, segment);
-  mSource->AdvanceKnownTracksTime(STREAM_TIME_MAX);
+  aStream->AddTrack(aID, SAMPLE_FREQUENCY, 0, segment);
+  aStream->AdvanceKnownTracksTime(STREAM_TIME_MAX);
   LOG(("Initial audio"));
   mTrackID = aID;
 
+  if (mState == kStarted) {
+    return NS_OK;
+  }
+  mState = kStarted;
+
   if (mVoEBase->StartReceive(mChannel)) {
     return NS_ERROR_FAILURE;
   }
   if (mVoEBase->StartSend(mChannel)) {
     return NS_ERROR_FAILURE;
   }
 
   // Attach external media processor, so this::Process will be called.
   mVoERender->RegisterExternalMediaProcessing(mChannel, webrtc::kRecordingPerChannel, *this);
 
-  mState = kStarted;
   return NS_OK;
 }
 
 nsresult
-MediaEngineWebRTCAudioSource::Stop()
+MediaEngineWebRTCAudioSource::Stop(SourceMediaStream *aSource, TrackID aID)
 {
+  if (!mSources.RemoveElement(aSource)) {
+    // Already stopped - this is allowed
+    return NS_OK;
+  }
+  if (!mSources.IsEmpty()) {
+    return NS_OK;
+  }
   if (mState != kStarted) {
     return NS_ERROR_FAILURE;
   }
   if (!mVoEBase) {
     return NS_ERROR_FAILURE;
   }
 
+  {
+    ReentrantMonitorAutoEnter enter(mMonitor);
+    mState = kStopped;
+    aSource->EndTrack(aID);
+  }
+
   mVoERender->DeRegisterExternalMediaProcessing(mChannel, webrtc::kRecordingPerChannel);
 
   if (mVoEBase->StopSend(mChannel)) {
     return NS_ERROR_FAILURE;
   }
   if (mVoEBase->StopReceive(mChannel)) {
     return NS_ERROR_FAILURE;
   }
-
-  {
-    ReentrantMonitorAutoEnter enter(mMonitor);
-    mState = kStopped;
-    mSource->EndTrack(mTrackID);
-  }
-
   return NS_OK;
 }
 
 void
 MediaEngineWebRTCAudioSource::NotifyPull(MediaStreamGraph* aGraph,
-                                         StreamTime aDesiredTime)
+                                         SourceMediaStream *aSource,
+                                         TrackID aID,
+                                         StreamTime aDesiredTime,
+                                         TrackTicks &aLastEndTime)
 {
   // Ignore - we push audio data
 #ifdef DEBUG
-  static TrackTicks mLastEndTime = 0;
   TrackTicks target = TimeToTicksRoundUp(SAMPLE_FREQUENCY, aDesiredTime);
-  TrackTicks delta = target - mLastEndTime;
-  LOG(("Audio:NotifyPull: target %lu, delta %lu",(uint32_t) target, (uint32_t) delta));
-  mLastEndTime = target;
+  TrackTicks delta = target - aLastEndTime;
+  LOG(("Audio: NotifyPull: aDesiredTime %ld, target %ld, delta %ld",(int64_t) aDesiredTime, (int64_t) target, (int64_t) delta));
+  aLastEndTime = target;
 #endif
 }
 
 nsresult
 MediaEngineWebRTCAudioSource::Snapshot(uint32_t aDuration, nsIDOMFile** aFile)
 {
    return NS_ERROR_NOT_IMPLEMENTED;
 }
@@ -230,20 +245,23 @@ MediaEngineWebRTCAudioSource::Shutdown()
     if (mNullTransport) {
       delete mNullTransport;
     }
 
     return;
   }
 
   if (mState == kStarted) {
-    Stop();
+    while (!mSources.IsEmpty()) {
+      Stop(mSources[0], kAudioTrack); // XXX change to support multiple tracks
+    }
+    MOZ_ASSERT(mState == kStopped);
   }
 
-  if (mState == kAllocated) {
+  if (mState == kAllocated || mState == kStopped) {
     Deallocate();
   }
 
   mVoEBase->Terminate();
   if (mChannel != -1) {
     mVoENetwork->DeRegisterExternalTransport(mChannel);
   }
 
@@ -264,24 +282,29 @@ void
 MediaEngineWebRTCAudioSource::Process(const int channel,
   const webrtc::ProcessingTypes type, sample* audio10ms,
   const int length, const int samplingFreq, const bool isStereo)
 {
   ReentrantMonitorAutoEnter enter(mMonitor);
   if (mState != kStarted)
     return;
 
-  nsRefPtr<SharedBuffer> buffer = SharedBuffer::Create(length * sizeof(sample));
+  uint32_t len = mSources.Length();
+  for (uint32_t i = 0; i < len; i++) {
+    nsRefPtr<SharedBuffer> buffer = SharedBuffer::Create(length * sizeof(sample));
 
-  sample* dest = static_cast<sample*>(buffer->Data());
-  memcpy(dest, audio10ms, length * sizeof(sample));
+    sample* dest = static_cast<sample*>(buffer->Data());
+    memcpy(dest, audio10ms, length * sizeof(sample));
 
-  AudioSegment segment;
-  segment.Init(CHANNELS);
-  segment.AppendFrames(
-    buffer.forget(), length, 0, length, AUDIO_FORMAT_S16
-  );
-  mSource->AppendToTrack(mTrackID, &segment);
+    AudioSegment segment;
+    segment.Init(CHANNELS);
+    segment.AppendFrames(buffer.forget(), length, 0, length, AUDIO_FORMAT_S16);
+
+    SourceMediaStream *source = mSources[i];
+    if (source) {
+      source->AppendToTrack(mTrackID, &segment);
+    }
+  }
 
   return;
 }
 
 }
--- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -7,18 +7,20 @@
 #include "ImageTypes.h"
 #include "ImageContainer.h"
 
 namespace mozilla {
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* GetMediaManagerLog();
 #define LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg)
+#define LOGFRAME(msg) PR_LOG(GetMediaManagerLog(), 6, msg)
 #else
 #define LOG(msg)
+#define LOGFRAME(msg)
 #endif
 
 /**
  * Webrtc video source.
  */
 NS_IMPL_THREADSAFE_ISUPPORTS1(MediaEngineWebRTCVideoSource, nsIRunnable)
 
 // ViEExternalRenderer Callback.
@@ -72,19 +74,19 @@ MediaEngineWebRTCVideoSource::DeliverFra
   data.mCbCrSize = gfxIntSize(mWidth/ 2, mHeight/ 2);
   data.mPicX = 0;
   data.mPicY = 0;
   data.mPicSize = gfxIntSize(mWidth, mHeight);
   data.mStereoMode = STEREO_MODE_MONO;
 
   videoImage->SetData(data);
 
-#ifdef LOG_ALL_FRAMES
+#ifdef DEBUG
   static uint32_t frame_num = 0;
-  LOG(("frame %d; timestamp %u, render_time %lu", frame_num++, time_stamp, render_time));
+  LOGFRAME(("frame %d; timestamp %u, render_time %lu", frame_num++, time_stamp, render_time));
 #endif
 
   // we don't touch anything in 'this' until here (except for snapshot,
   // which has it's own lock)
   ReentrantMonitorAutoEnter enter(mMonitor);
 
   // implicitly releases last image
   mImage = image.forget();
@@ -92,35 +94,41 @@ MediaEngineWebRTCVideoSource::DeliverFra
   return 0;
 }
 
 // Called if the graph thinks it's running out of buffered video; repeat
 // the last frame for whatever minimum period it think it needs.  Note that
 // this means that no *real* frame can be inserted during this period.
 void
 MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph,
-                                         StreamTime aDesiredTime)
+                                         SourceMediaStream *aSource,
+                                         TrackID aID,
+                                         StreamTime aDesiredTime,
+                                         TrackTicks &aLastEndTime)
 {
   VideoSegment segment;
 
   ReentrantMonitorAutoEnter enter(mMonitor);
   if (mState != kStarted)
     return;
 
   // Note: we're not giving up mImage here
   nsRefPtr<layers::Image> image = mImage;
   TrackTicks target = TimeToTicksRoundUp(USECS_PER_S, aDesiredTime);
-  TrackTicks delta = target - mLastEndTime;
-#ifdef LOG_ALL_FRAMES
-  LOG(("NotifyPull, target = %lu, delta = %lu", (uint64_t) target, (uint64_t) delta));
-#endif
-  // NULL images are allowed
-  segment.AppendFrame(image ? image.forget() : nullptr, delta, gfxIntSize(mWidth, mHeight));
-  mSource->AppendToTrack(mTrackID, &(segment));
-  mLastEndTime = target;
+  TrackTicks delta = target - aLastEndTime;
+  LOGFRAME(("NotifyPull, desired = %ld, target = %ld, delta = %ld %s", (int64_t) aDesiredTime, 
+            (int64_t) target, (int64_t) delta, image ? "" : "<null>"));
+  // Don't append if we've already provided a frame that supposedly goes past the current aDesiredTime
+  // Doing so means a negative delta and thus messes up handling of the graph
+  if (delta > 0) {
+    // NULL images are allowed
+    segment.AppendFrame(image ? image.forget() : nullptr, delta, gfxIntSize(mWidth, mHeight));
+    aSource->AppendToTrack(aID, &(segment));
+    aLastEndTime = target;
+  }
 }
 
 void
 MediaEngineWebRTCVideoSource::ChooseCapability(uint32_t aWidth, uint32_t aHeight, uint32_t aMinFPS)
 {
   int num = mViECapture->NumberOfCapabilities(mUniqueId, KMaxUniqueIdLength);
 
   NS_WARN_IF_FALSE(!mCapabilityChosen,"Shouldn't select capability of a device twice");
@@ -184,80 +192,85 @@ MediaEngineWebRTCVideoSource::GetUUID(ns
 {
   // mUniqueId is UTF8
   CopyUTF8toUTF16(mUniqueId, aUUID);
 }
 
 nsresult
 MediaEngineWebRTCVideoSource::Allocate()
 {
-  if (mState != kReleased) {
-    return NS_ERROR_FAILURE;
-  }
-
+  LOG((__FUNCTION__));
   if (!mCapabilityChosen) {
     // XXX these should come from constraints
     ChooseCapability(mWidth, mHeight, mMinFps);
   }
 
-  if (mViECapture->AllocateCaptureDevice(mUniqueId, KMaxUniqueIdLength, mCaptureIndex)) {
-    return NS_ERROR_FAILURE;
+  if (mState == kReleased && mInitDone) {
+    if (mViECapture->AllocateCaptureDevice(mUniqueId, KMaxUniqueIdLength, mCaptureIndex)) {
+      return NS_ERROR_FAILURE;
+    }
+    mState = kAllocated;
+    LOG(("Video device %d allocated", mCaptureIndex));
+  } else if (mSources.IsEmpty()) {
+    LOG(("Video device %d reallocated", mCaptureIndex));
+  } else {
+    LOG(("Video device %d allocated shared", mCaptureIndex));
   }
 
-  mState = kAllocated;
   return NS_OK;
 }
 
 nsresult
 MediaEngineWebRTCVideoSource::Deallocate()
 {
-  if (mState != kStopped && mState != kAllocated) {
-    return NS_ERROR_FAILURE;
+  LOG((__FUNCTION__));
+  if (mSources.IsEmpty()) {
+    if (mState != kStopped && mState != kAllocated) {
+      return NS_ERROR_FAILURE;
+    }
+
+    mViECapture->ReleaseCaptureDevice(mCaptureIndex);
+    mState = kReleased;
+    LOG(("Video device %d deallocated", mCaptureIndex));
+  } else {
+    LOG(("Video device %d deallocated but still in use", mCaptureIndex));
   }
-
-  mViECapture->ReleaseCaptureDevice(mCaptureIndex);
-  mState = kReleased;
   return NS_OK;
 }
 
 const MediaEngineVideoOptions*
 MediaEngineWebRTCVideoSource::GetOptions()
 {
   if (!mCapabilityChosen) {
     ChooseCapability(mWidth, mHeight, mMinFps);
   }
   return &mOpts;
 }
 
 nsresult
 MediaEngineWebRTCVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
 {
+  LOG((__FUNCTION__));
   int error = 0;
-  if (!mInitDone || mState != kAllocated) {
+  if (!mInitDone || !aStream) {
     return NS_ERROR_FAILURE;
   }
 
-  if (!aStream) {
-    return NS_ERROR_FAILURE;
-  }
+  mSources.AppendElement(aStream);
+
+  aStream->AddTrack(aID, USECS_PER_S, 0, new VideoSegment());
+  aStream->AdvanceKnownTracksTime(STREAM_TIME_MAX);
 
   if (mState == kStarted) {
     return NS_OK;
   }
-
-  mSource = aStream;
-  mTrackID = aID;
+  mState = kStarted;
 
   mImageContainer = layers::LayerManager::CreateImageContainer();
 
-  mSource->AddTrack(aID, USECS_PER_S, 0, new VideoSegment());
-  mSource->AdvanceKnownTracksTime(STREAM_TIME_MAX);
-  mLastEndTime = 0;
-  mState = kStarted;
-
   error = mViERender->AddRenderer(mCaptureIndex, webrtc::kVideoI420, (webrtc::ExternalRenderer*)this);
   if (error == -1) {
     return NS_ERROR_FAILURE;
   }
 
   error = mViERender->StartRender(mCaptureIndex);
   if (error == -1) {
     return NS_ERROR_FAILURE;
@@ -266,26 +279,38 @@ MediaEngineWebRTCVideoSource::Start(Sour
   if (mViECapture->StartCapture(mCaptureIndex, mCapability) < 0) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult
-MediaEngineWebRTCVideoSource::Stop()
+MediaEngineWebRTCVideoSource::Stop(SourceMediaStream *aSource, TrackID aID)
 {
+  LOG((__FUNCTION__));
+  if (!mSources.RemoveElement(aSource)) {
+    // Already stopped - this is allowed
+    return NS_OK;
+  }
+  if (!mSources.IsEmpty()) {
+    return NS_OK;
+  }
+
   if (mState != kStarted) {
     return NS_ERROR_FAILURE;
   }
 
   {
     ReentrantMonitorAutoEnter enter(mMonitor);
     mState = kStopped;
-    mSource->EndTrack(mTrackID);
+    aSource->EndTrack(aID);
+    // Drop any cached image so we don't start with a stale image on next
+    // usage
+    mImage = nullptr;
   }
 
   mViERender->StopRender(mCaptureIndex);
   mViERender->RemoveRenderer(mCaptureIndex);
   mViECapture->StopCapture(mCaptureIndex);
 
   return NS_OK;
 }
@@ -389,16 +414,17 @@ MediaEngineWebRTCVideoSource::Snapshot(u
  */
 
 void
 MediaEngineWebRTCVideoSource::Init()
 {
   mDeviceName[0] = '\0'; // paranoia
   mUniqueId[0] = '\0';
 
+  LOG((__FUNCTION__));
   if (mVideoEngine == NULL) {
     return;
   }
 
   mViEBase = webrtc::ViEBase::GetInterface(mVideoEngine);
   if (mViEBase == NULL) {
     return;
   }
@@ -418,32 +444,30 @@ MediaEngineWebRTCVideoSource::Init()
   }
 
   mInitDone = true;
 }
 
 void
 MediaEngineWebRTCVideoSource::Shutdown()
 {
-  bool continueShutdown = false;
-
+  LOG((__FUNCTION__));
   if (!mInitDone) {
     return;
   }
 
   if (mState == kStarted) {
-    mViERender->StopRender(mCaptureIndex);
-    mViERender->RemoveRenderer(mCaptureIndex);
-    continueShutdown = true;
+    while (!mSources.IsEmpty()) {
+      Stop(mSources[0], kVideoTrack); // XXX change to support multiple tracks
+    }
+    MOZ_ASSERT(mState == kStopped);
   }
 
-  if (mState == kAllocated || continueShutdown) {
-    mViECapture->StopCapture(mCaptureIndex);
-    mViECapture->ReleaseCaptureDevice(mCaptureIndex);
-    continueShutdown = false;
+  if (mState == kAllocated || mState == kStopped) {
+    Deallocate();
   }
 
   mViECapture->Release();
   mViERender->Release();
   mViEBase->Release();
   mState = kReleased;
   mInitDone = false;
 }
--- a/content/media/wmf/WMF.h
+++ b/content/media/wmf/WMF.h
@@ -24,18 +24,16 @@ which makes Windows Media Foundation una
 #include <mfidl.h>
 #include <mfreadwrite.h>
 #include <mfobjects.h>
 #include <stdio.h>
 #include <mferror.h>
 #include <propvarutil.h>
 #include <wmcodecdsp.h>
 
-#pragma comment(lib,"uuid.lib")
-#pragma comment(lib,"mfuuid.lib")
 
 namespace mozilla {
 namespace wmf {
 
 // Loads/Unloads all the DLLs in which the WMF functions are located.
 // The DLLs must be loaded before any of the WMF functions below will work.
 // All the function definitions below are wrappers which locate the
 // corresponding WMF function in the appropriate DLL (hence why LoadDLL()
--- a/content/smil/Makefile.in
+++ b/content/smil/Makefile.in
@@ -8,17 +8,19 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 LIBRARY_NAME	= gkconsmil_s
 LIBXUL_LIBRARY	= 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS = 1
+endif # !_MSC_VER
 
 EXPORTS	= \
 	nsISMILAnimationElement.h \
 	nsISMILAttr.h \
 	nsISMILType.h \
 	nsSMILAnimationController.h \
 	nsSMILCompositorTable.h \
 	nsSMILCSSProperty.h \
--- a/content/svg/content/src/Makefile.in
+++ b/content/svg/content/src/Makefile.in
@@ -8,17 +8,19 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 LIBRARY_NAME	= gkcontentsvg_s
 LIBXUL_LIBRARY	= 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS	= 1
+endif # !_MSC_VER
 
 CPPSRCS		= \
 		DOMSVGAnimatedLengthList.cpp \
 		DOMSVGAnimatedNumberList.cpp \
 		DOMSVGAnimatedTransformList.cpp \
 		DOMSVGLength.cpp \
 		DOMSVGLengthList.cpp \
 		DOMSVGMatrix.cpp \
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -1754,17 +1754,18 @@ this.DOMApplicationRegistry = {
     }
 
     function download() {
       debug("About to download " + aManifest.fullPackagePath());
 
       let requestChannel = NetUtil.newChannel(aManifest.fullPackagePath())
                                   .QueryInterface(Ci.nsIHttpChannel);
       if (app.packageEtag) {
-        requestChannel.setRequestHeader("If-None-Match", app.packageEtag);
+        debug('Add If-None-Match header: ' + app.packageEtag);
+        requestChannel.setRequestHeader("If-None-Match", app.packageEtag, false);
       }
 
       AppDownloadManager.add(aApp.manifestURL,
         {
           channel: requestChannel,
           appId: id,
           previousState: aIsUpdate ? "installed" : "pending"
         }
@@ -1829,17 +1830,27 @@ this.DOMApplicationRegistry = {
       let bufferedOutputStream = Cc['@mozilla.org/network/buffered-output-stream;1']
                                    .createInstance(Ci.nsIBufferedOutputStream);
       bufferedOutputStream.init(outputStream, 1024);
 
       // Create a listener that will give data to the file output stream.
       let listener = Cc["@mozilla.org/network/simple-stream-listener;1"]
                        .createInstance(Ci.nsISimpleStreamListener);
       listener.init(bufferedOutputStream, {
-        onStartRequest: function(aRequest, aContext) { },
+        onStartRequest: function(aRequest, aContext) {
+          // early check for ETag header
+          try {
+            requestChannel.getResponseHeader("Etag");
+          } catch (e) {
+            // in https://bugzilla.mozilla.org/show_bug.cgi?id=825218
+            // we might do something cleaner to have a proper user error
+            debug("We found no ETag Header, canceling the request");
+            requestChannel.cancel(Cr.NS_BINDING_ABORTED);
+          }
+        },
         onStopRequest: function(aRequest, aContext, aStatusCode) {
           debug("onStopRequest " + aStatusCode);
           bufferedOutputStream.close();
           outputStream.close();
 
           if (requestChannel.responseStatus == 304) {
             // The package's Etag has not changed.
             // We send a "applied" event right away.
@@ -1856,20 +1867,16 @@ this.DOMApplicationRegistry = {
             self._saveApps();
             let file = FileUtils.getFile("TmpD", ["webapps", id], false);
             if (file && file.exists()) {
               file.remove(true);
             }
             return;
           }
 
-          // Save the new Etag for the package.
-          app.packageEtag = requestChannel.getResponseHeader("Etag");
-          debug("Package etag=" + app.packageEtag);
-
           if (!Components.isSuccessCode(aStatusCode)) {
             cleanup("NETWORK_ERROR");
             return;
           }
 
           let certdb;
           try {
             certdb = Cc["@mozilla.org/security/x509certdb;1"]
@@ -1926,16 +1933,27 @@ this.DOMApplicationRegistry = {
               let maxStatus = isDevMode ? Ci.nsIPrincipal.APP_STATUS_CERTIFIED
                             : isSigned  ? Ci.nsIPrincipal.APP_STATUS_PRIVILEGED
                                         : Ci.nsIPrincipal.APP_STATUS_INSTALLED;
 
               if (AppsUtils.getAppManifestStatus(manifest) > maxStatus) {
                 throw "INVALID_SECURITY_LEVEL";
               }
               aApp.appStatus = AppsUtils.getAppManifestStatus(manifest);
+              // Save the new Etag for the package.
+              try {
+                app.packageEtag = requestChannel.getResponseHeader("Etag");
+                debug("Package etag=" + app.packageEtag);
+              } catch (e) {
+                // in https://bugzilla.mozilla.org/show_bug.cgi?id=825218
+                // we'll fail gracefully in this case
+                // for now, just going on
+                app.packageEtag = null;
+                debug("Can't find an etag, this should not happen");
+              }
 
               if (aOnSuccess) {
                 aOnSuccess(id, manifest);
               }
             } catch (e) {
               // Something bad happened when reading the package.
               if (typeof e == 'object') {
                 debug(e);
--- a/dom/audiochannel/Makefile.in
+++ b/dom/audiochannel/Makefile.in
@@ -20,17 +20,19 @@ VPATH            = @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE           = dom
 LIBRARY_NAME     = domaudiochannel_s
 XPIDL_MODULE     = dom_audiochannel
 LIBXUL_LIBRARY = 1
 FORCE_STATIC_LIB = 1
 EXPORT_LIBRARY = 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 EXPORTS_NAMESPACES = \
   mozilla/dom \
   $(NULL)
 
 EXPORTS = AudioChannelService.h \
           AudioChannelServiceChild.h \
           AudioChannelCommon.h \
--- a/dom/base/Makefile.in
+++ b/dom/base/Makefile.in
@@ -2,24 +2,26 @@
 # 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/.
 
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
-FAIL_ON_WARNINGS := 1
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= dom
 LIBRARY_NAME	= jsdombase_s
 LIBXUL_LIBRARY	= 1
 FORCE_STATIC_LIB = 1
+ifndef _MSC_VER
+FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 DIRS = \
   test \
   $(NULL)
 
 EXTRA_COMPONENTS = \
   SiteSpecificUserAgent.js \
   SiteSpecificUserAgent.manifest \
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -4418,17 +4418,17 @@ nsDOMClassInfo::ResolveConstructor(JSCon
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMClassInfo::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                            JSObject *obj, jsid id, uint32_t flags,
                            JSObject **objp, bool *_retval)
 {
-  if (id == sConstructor_id && !(flags & JSRESOLVE_ASSIGNING)) {
+  if (id == sConstructor_id) {
     return ResolveConstructor(cx, obj, objp);
   }
 
   return NS_OK;
 }
 
 nsISupports*
 nsDOMTouchListSH::GetItemAt(nsISupports *aNative, uint32_t aIndex,
@@ -4902,18 +4902,18 @@ GetDocument(JSObject *obj)
 }
 
 // static
 JSBool
 nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
                                           JSHandleId id, unsigned flags,
                                           JSMutableHandleObject objp)
 {
-  if ((flags & JSRESOLVE_ASSIGNING) || !JSID_IS_STRING(id)) {
-    // Nothing to do if we're assigning or resolving a non-string property.
+  if (!JSID_IS_STRING(id)) {
+    // Nothing to do if we're resolving a non-string property.
     return JS_TRUE;
   }
 
   nsHTMLDocument *document = GetDocument(obj);
 
   if (!document) {
     // If we don't have a document, return early.
 
@@ -6727,23 +6727,21 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
     }
 
     if (did_resolve) {
       *objp = obj;
       return NS_OK;
     }
   }
 
-  if (!(flags & JSRESOLVE_ASSIGNING)) {
-    // We want this code to be before the child frame lookup code
-    // below so that a child frame named 'constructor' doesn't
-    // shadow the window's constructor property.
-    if (sConstructor_id == id) {
-      return ResolveConstructor(cx, obj, objp);
-    }
+  // We want this code to be before the child frame lookup code
+  // below so that a child frame named 'constructor' doesn't
+  // shadow the window's constructor property.
+  if (sConstructor_id == id) {
+    return ResolveConstructor(cx, obj, objp);
   }
 
   if (!my_context || !my_context->IsContextInitialized()) {
     // The context is not yet initialized so there's nothing we can do
     // here yet.
 
     return NS_OK;
   }
@@ -6778,17 +6776,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
       return NS_ERROR_FAILURE;
     }
 
     *objp = obj;
 
     return NS_OK;
   }
 
-  if (sTop_id == id && !(flags & JSRESOLVE_ASSIGNING)) {
+  if (sTop_id == id) {
     nsCOMPtr<nsIDOMWindow> top;
     rv = win->GetScriptableTop(getter_AddRefs(top));
     NS_ENSURE_SUCCESS(rv, rv);
 
     jsval v;
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     rv = WrapNative(cx, obj, top, &NS_GET_IID(nsIDOMWindow), true,
                     &v, getter_AddRefs(holder));
@@ -7189,17 +7187,17 @@ nsLocationSH::AddProperty(nsIXPConnectWr
 
 // DOM Navigator helper
 
 NS_IMETHODIMP
 nsNavigatorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                           JSObject *obj, jsid id, uint32_t flags,
                           JSObject **objp, bool *_retval)
 {
-  if (!JSID_IS_STRING(id) || (flags & JSRESOLVE_ASSIGNING)) {
+  if (!JSID_IS_STRING(id)) {
     return NS_OK;
   }
 
   nsScriptNameSpaceManager *nameSpaceManager =
     nsJSRuntime::GetNameSpaceManager();
   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
 
   nsDependentJSString name(id);
@@ -8383,22 +8381,16 @@ nsHTMLDocumentSH::DocumentAllGetProperty
 
   return JS_TRUE;
 }
 
 JSBool
 nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                         unsigned flags, JSMutableHandleObject objp)
 {
-  if (flags & JSRESOLVE_ASSIGNING) {
-    // Nothing to do here if we're assigning
-
-    return JS_TRUE;
-  }
-
   js::RootedValue v(cx);
 
   if (sItem_id == id || sNamedItem_id == id) {
     // Define the item() or namedItem() method.
 
     JSFunction *fnc = ::JS_DefineFunctionById(cx, obj, id, CallToGetPropMapper,
                                               0, JSPROP_ENUMERATE);
     objp.set(obj);
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -9822,22 +9822,16 @@ nsGlobalWindow::RescheduleTimeout(nsTime
     aTimeout->mTimeRemaining = delay;
     return true;
   }
 
   aTimeout->mWhen = currentNow + delay;
 
   // Reschedule the OS timer. Don't bother returning any error codes if
   // this fails since the callers of this method don't care about them.
-
-  // Make sure to cast the unsigned PR_USEC_PER_MSEC to signed
-  // PRTime to make the division do the right thing on 64-bit
-  // platforms whether delay is positive or negative (which we
-  // know is always positive here, but cast anyways for
-  // consistency).
   nsresult rv = aTimeout->InitTimer(TimerCallback, delay.ToMilliseconds());
 
   if (NS_FAILED(rv)) {
     NS_ERROR("Error initializing timer for DOM timeout!");
 
     // We failed to initialize the new OS timer, this timer does
     // us no good here so we just cancel it (just in case) and
     // null out the pointer to the OS timer, this will release the
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -143,17 +143,18 @@ struct nsTimeout : mozilla::LinkedListEl
   ~nsTimeout();
 
   NS_DECL_CYCLE_COLLECTION_LEGACY_NATIVE_CLASS(nsTimeout)
 
   nsrefcnt Release();
   nsrefcnt AddRef();
 
   nsresult InitTimer(nsTimerCallbackFunc aFunc, uint64_t delay) {
-    return mTimer->InitWithFuncCallback(aFunc, this, delay,
+    return mTimer->InitWithFuncCallback(aFunc, this,
+                                        static_cast<uint32_t>(delay),
                                         nsITimer::TYPE_ONE_SHOT);
   }
 
   // Window for which this timeout fires
   nsRefPtr<nsGlobalWindow> mWindow;
 
   // The actual timer object
   nsCOMPtr<nsITimer> mTimer;
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -172,18 +172,17 @@ static uint32_t sPreviousSuspectedCount 
 static uint32_t sCompartmentGCCount = NS_MAX_COMPARTMENT_GC_COUNT;
 static uint32_t sCleanupsSinceLastGC = UINT32_MAX;
 static bool sNeedsFullCC = false;
 static nsJSContext *sContextList = nullptr;
 
 static nsScriptNameSpaceManager *gNameSpaceManager;
 static nsIMemoryReporter *gReporter;
 
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(ScriptNameSpaceManagerMallocSizeOf,
-                                     "script-namespace-manager")
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(ScriptNameSpaceManagerMallocSizeOf)
 
 static int64_t
 GetScriptNameSpaceManagerSize()
 {
   MOZ_ASSERT(gNameSpaceManager);
   return gNameSpaceManager->SizeOfIncludingThis(
              ScriptNameSpaceManagerMallocSizeOf);
 }
@@ -3060,88 +3059,120 @@ DoMergingCC(bool aForced)
   } else {
     sMergedInARow = 0;
     return false;
   }
 
 }
 
 static void
+FinishAnyIncrementalGC()
+{
+  if (sCCLockedOut) {
+    // We're in the middle of an incremental GC, so finish it.
+    js::PrepareForIncrementalGC(nsJSRuntime::sRuntime);
+    js::FinishIncrementalGC(nsJSRuntime::sRuntime, js::gcreason::CC_FORCED);
+  }
+}
+
+static void
 FireForgetSkippable(uint32_t aSuspected, bool aRemoveChildless)
 {
   PRTime startTime = PR_Now();
+  FinishAnyIncrementalGC();
   nsCycleCollector_forgetSkippable(aRemoveChildless);
   sPreviousSuspectedCount = nsCycleCollector_suspectedCount();
   ++sCleanupsSinceLastGC;
   PRTime delta = PR_Now() - startTime;
   if (sMinForgetSkippableTime > delta) {
     sMinForgetSkippableTime = delta;
   }
   if (sMaxForgetSkippableTime < delta) {
     sMaxForgetSkippableTime = delta;
   }
   sTotalForgetSkippableTime += delta;
   sRemovedPurples += (aSuspected - sPreviousSuspectedCount);
   ++sForgetSkippableBeforeCC;
 }
 
+MOZ_ALWAYS_INLINE
+static uint32_t
+TimeBetween(PRTime start, PRTime end)
+{
+  MOZ_ASSERT(end >= start);
+  return (uint32_t)(end - start) / PR_USEC_PER_MSEC;
+}
+
 //static
 void
 nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
                              int32_t aExtraForgetSkippableCalls,
                              bool aForced)
 {
   if (!NS_IsMainThread()) {
     return;
   }
 
-  if (sCCLockedOut) {
-    // We're in the middle of an incremental GC; finish it first
-    js::PrepareForIncrementalGC(nsJSRuntime::sRuntime);
-    js::FinishIncrementalGC(nsJSRuntime::sRuntime, js::gcreason::CC_FORCED);
-  }
-
-  SAMPLE_LABEL("GC", "CycleCollectNow");
+  SAMPLE_LABEL("CC", "CycleCollectNow");
+
+  PRTime start = PR_Now();
+
+  // Before we begin the cycle collection, make sure there is no active GC.
+  bool finishedIGC = sCCLockedOut;
+  FinishAnyIncrementalGC();
+  PRTime endGCTime = PR_Now();
+  uint32_t gcDuration = TimeBetween(start, endGCTime);
 
   KillCCTimer();
 
-  PRTime start = PR_Now();
-
   uint32_t suspected = nsCycleCollector_suspectedCount();
-
-  // nsCycleCollector_forgetSkippable may mark some gray js to black.
+  bool ranSyncForgetSkippable = false;
+
+  // Run forgetSkippable synchronously to reduce the size of the CC graph. This
+  // is particularly useful if we recently finished a GC.
   if (sCleanupsSinceLastGC < 2 && aExtraForgetSkippableCalls >= 0) {
     while (sCleanupsSinceLastGC < 2) {
       FireForgetSkippable(nsCycleCollector_suspectedCount(), false);
+      ranSyncForgetSkippable = true;
     }
   }
 
   for (int32_t i = 0; i < aExtraForgetSkippableCalls; ++i) {
     FireForgetSkippable(nsCycleCollector_suspectedCount(), false);
+    ranSyncForgetSkippable = true;
   }
 
+  PRTime endSkippableTime = PR_Now();
+  uint32_t skippableDuration = TimeBetween(endGCTime, endSkippableTime);
+
+  // Prepare to actually run the CC.
   bool mergingCC = DoMergingCC(aForced);
-
   nsCycleCollectorResults ccResults;
   nsCycleCollector_collect(mergingCC, &ccResults, aListener);
   sCCollectedWaitingForGC += ccResults.mFreedRefCounted + ccResults.mFreedGCed;
 
   // If we collected a substantial amount of cycles, poke the GC since more objects
   // might be unreachable now.
   if (sCCollectedWaitingForGC > 250) {
     PokeGC(js::gcreason::CC_WAITING);
   }
 
-  PRTime now = PR_Now();
+  PRTime endCCTime = PR_Now();
+
+  // Log information about the CC via telemetry, JSON and the console.
+  uint32_t ccNowDuration = TimeBetween(start, endCCTime);
+  Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_FINISH_IGC, finishedIGC);
+  Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_SYNC_SKIPPABLE, ranSyncForgetSkippable);
+  Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_FULL, ccNowDuration);
 
   if (sLastCCEndTime) {
     uint32_t timeBetween = (uint32_t)(start - sLastCCEndTime) / PR_USEC_PER_SEC;
     Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_TIME_BETWEEN, timeBetween);
   }
-  sLastCCEndTime = now;
+  sLastCCEndTime = endCCTime;
 
   Telemetry::Accumulate(Telemetry::FORGET_SKIPPABLE_MAX,
                         sMaxForgetSkippableTime / PR_USEC_PER_MSEC);
 
   PRTime delta = GetCollectionTimeDelta();
 
   uint32_t cleanups = sForgetSkippableBeforeCC ? sForgetSkippableBeforeCC : 1;
   uint32_t minForgetSkippableTime = (sMinForgetSkippableTime == UINT32_MAX)
@@ -3154,42 +3185,44 @@ nsJSContext::CycleCollectNow(nsICycleCol
     }
 
     nsCString gcMsg;
     if (ccResults.mForcedGC) {
       gcMsg.AssignLiteral(", forced a GC");
     }
 
     NS_NAMED_MULTILINE_LITERAL_STRING(kFmt,
-      NS_LL("CC(T+%.1f) duration: %llums, suspected: %lu, visited: %lu RCed and %lu%s GCed, collected: %lu RCed and %lu GCed (%lu waiting for GC)%s\n")
-      NS_LL("ForgetSkippable %lu times before CC, min: %lu ms, max: %lu ms, avg: %lu ms, total: %lu ms, removed: %lu"));
+      NS_LL("CC(T+%.1f) duration: %lums, suspected: %lu, visited: %lu RCed and %lu%s GCed, collected: %lu RCed and %lu GCed (%lu waiting for GC)%s\n")
+      NS_LL("ForgetSkippable %lu times before CC, min: %lu ms, max: %lu ms, avg: %lu ms, total: %lu ms, sync: %lu ms, removed: %lu"));
     nsString msg;
     msg.Adopt(nsTextFormatter::smprintf(kFmt.get(), double(delta) / PR_USEC_PER_SEC,
-                                        (now - start) / PR_USEC_PER_MSEC, suspected,
+                                        ccNowDuration, suspected,
                                         ccResults.mVisitedRefCounted, ccResults.mVisitedGCed, mergeMsg.get(),
                                         ccResults.mFreedRefCounted, ccResults.mFreedGCed,
                                         sCCollectedWaitingForGC, gcMsg.get(),
                                         sForgetSkippableBeforeCC,
                                         minForgetSkippableTime / PR_USEC_PER_MSEC,
                                         sMaxForgetSkippableTime / PR_USEC_PER_MSEC,
                                         (sTotalForgetSkippableTime / cleanups) /
                                           PR_USEC_PER_MSEC,
                                         sTotalForgetSkippableTime / PR_USEC_PER_MSEC,
-                                        sRemovedPurples));
+                                        skippableDuration, sRemovedPurples));
     nsCOMPtr<nsIConsoleService> cs =
       do_GetService(NS_CONSOLESERVICE_CONTRACTID);
     if (cs) {
       cs->LogStringMessage(msg.get());
     }
   }
 
   if (sPostGCEventsToObserver) {
     NS_NAMED_MULTILINE_LITERAL_STRING(kJSONFmt,
        NS_LL("{ \"timestamp\": %llu, ")
          NS_LL("\"duration\": %llu, ")
+         NS_LL("\"finish_gc_duration\": %llu, ")
+         NS_LL("\"sync_skippable_duration\": %llu, ")
          NS_LL("\"suspected\": %lu, ")
          NS_LL("\"visited\": { ")
              NS_LL("\"RCed\": %lu, ")
              NS_LL("\"GCed\": %lu }, ")
          NS_LL("\"collected\": { ")
              NS_LL("\"RCed\": %lu, ")
              NS_LL("\"GCed\": %lu }, ")
          NS_LL("\"waiting_for_gc\": %lu, ")
@@ -3198,34 +3231,37 @@ nsJSContext::CycleCollectNow(nsICycleCol
              NS_LL("\"times_before_cc\": %lu, ")
              NS_LL("\"min\": %lu, ")
              NS_LL("\"max\": %lu, ")
              NS_LL("\"avg\": %lu, ")
              NS_LL("\"total\": %lu, ")
              NS_LL("\"removed\": %lu } ")
        NS_LL("}"));
     nsString json;
-    json.Adopt(nsTextFormatter::smprintf(kJSONFmt.get(),
-                                         now, (now - start) / PR_USEC_PER_MSEC, suspected,
+    json.Adopt(nsTextFormatter::smprintf(kJSONFmt.get(), endCCTime,
+                                         ccNowDuration, gcDuration, skippableDuration,
+                                         suspected,
                                          ccResults.mVisitedRefCounted, ccResults.mVisitedGCed,
                                          ccResults.mFreedRefCounted, ccResults.mFreedGCed,
                                          sCCollectedWaitingForGC,
                                          ccResults.mForcedGC,
                                          sForgetSkippableBeforeCC,
                                          minForgetSkippableTime / PR_USEC_PER_MSEC,
                                          sMaxForgetSkippableTime / PR_USEC_PER_MSEC,
                                          (sTotalForgetSkippableTime / cleanups) /
                                            PR_USEC_PER_MSEC,
                                          sTotalForgetSkippableTime / PR_USEC_PER_MSEC,
                                          sRemovedPurples));
     nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
     if (observerService) {
       observerService->NotifyObservers(nullptr, "cycle-collection-statistics", json.get());
     }
   }
+
+  // Update global state to indicate we have just run a cycle collection.
   sMinForgetSkippableTime = UINT32_MAX;
   sMaxForgetSkippableTime = 0;
   sTotalForgetSkippableTime = 0;
   sRemovedPurples = 0;
   sForgetSkippableBeforeCC = 0;
   sNeedsFullCC = false;
 }
 
@@ -3284,20 +3320,16 @@ CCTimerFired(nsITimer *aTimer, void *aCl
     PRTime now = PR_Now();
     if (sCCLockedOutTime == 0) {
       sCCLockedOutTime = now;
       return;
     }
     if (now - sCCLockedOutTime < NS_MAX_CC_LOCKEDOUT_TIME) {
       return;
     }
-
-    // Finish the current incremental GC
-    js::PrepareForIncrementalGC(nsJSRuntime::sRuntime);
-    js::FinishIncrementalGC(nsJSRuntime::sRuntime, js::gcreason::CC_FORCED);
   }
 
   ++sCCTimerFireCount;
 
   // During early timer fires, we only run forgetSkippable. During the first
   // late timer fire, we decide if we are going to have a second and final
   // late timer fire, where we may run the CC.
   const uint32_t numEarlyTimerFires = ccDelay / NS_CC_SKIPPABLE_DELAY - 2;
@@ -3308,22 +3340,23 @@ CCTimerFired(nsITimer *aTimer, void *aCl
       FireForgetSkippable(suspected, true);
       if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
         // Our efforts to avoid a CC have failed, so we return to let the
         // timer fire once more to trigger a CC.
         return;
       }
     } else {
       // We are in the final timer fire and still meet the conditions for
-      // triggering a CC.
+      // triggering a CC. Let CycleCollectNow finish the current IGC, if any,
+      // because that will allow us to include the GC time in the CC pause.
       nsJSContext::CycleCollectNow(nullptr, 0, false);
     }
   } else if ((sPreviousSuspectedCount + 100) <= suspected) {
-    // Only do a forget skippable if there are more than a few new objects.
-    FireForgetSkippable(suspected, false);
+      // Only do a forget skippable if there are more than a few new objects.
+      FireForgetSkippable(suspected, false);
   }
 
   if (isLateTimerFire) {
     ccDelay = NS_CC_DELAY;
 
     // We have either just run the CC or decided we don't want to run the CC
     // next time, so kill the timer.
     sPreviousSuspectedCount = 0;
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -100,17 +100,17 @@ AppendWindowURI(nsGlobalWindow *aWindow,
     aStr += spec;
   } else {
     // If we're unable to find a URI, we're dealing with a chrome window with
     // no document in it (or somesuch), so we call this a "system window".
     aStr += NS_LITERAL_CSTRING("[system]");
   }
 }
 
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMStyleMallocSizeOf, "windows")
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WindowsMallocSizeOf)
 
 // The key is the window ID.
 typedef nsDataHashtable<nsUint64HashKey, nsCString> WindowPaths;
 
 static nsresult
 CollectWindowReports(nsGlobalWindow *aWindow,
                      nsWindowSizes *aWindowTotalSizes,
                      nsTHashtable<nsUint64HashKey> *aGhostWindowIDs,
@@ -161,17 +161,17 @@ CollectWindowReports(nsGlobalWindow *aWi
         nsresult rv;                                                          \
         rv = aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_HEAP,\
                       nsIMemoryReporter::UNITS_BYTES, _amount,                \
                       NS_LITERAL_CSTRING(_desc), aClosure);                   \
         NS_ENSURE_SUCCESS(rv, rv);                                            \
     }                                                                         \
   } while (0)
 
-  nsWindowSizes windowSizes(DOMStyleMallocSizeOf);
+  nsWindowSizes windowSizes(WindowsMallocSizeOf);
   aWindow->SizeOfIncludingThis(&windowSizes);
 
   REPORT("/dom/other", windowSizes.mDOMOther,
          "Memory used by a window's DOM, excluding element, text, CDATA, "
          "and comment nodes.");
   aWindowTotalSizes->mDOMOther += windowSizes.mDOMOther;
 
   REPORT("/dom/element-nodes", windowSizes.mDOMElementNodes,
--- a/dom/base/test/Makefile.in
+++ b/dom/base/test/Makefile.in
@@ -14,16 +14,17 @@ MOCHITEST_FILES = \
   test_document.all_unqualified.html \
   test_domrequest.html \
   test_e4x_for_each.html \
   test_gsp-standards.html \
   test_gsp-quirks.html \
   test_gsp-qualified.html \
   test_nondomexception.html \
   test_screen_orientation.html \
+  test_window_constructor.html \
   test_window_enumeration.html \
   test_writable-replaceable.html \
   $(NULL)
 
 MOCHITEST_CHROME_FILES = \
    test_bug715041.xul \
    test_bug715041_removal.xul \
    $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_window_constructor.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=824217
+-->
+<head>
+  <meta charset="UTF-8">
+  <title>Test for Bug 824217</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=622491">Mozilla Bug 824217</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<iframe name="constructor" src="about:blank"></iframe>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+function run()
+{
+  // Ideally we'd test that this property lives on the right place in the
+  // [[Prototype]] chain, with the right attributes there, but we don't
+  // implement this right yet, so just test the value's what's expected.
+  is(window.constructor, Window,
+     "should have gotten Window, not the constructor frame");
+  SimpleTest.finish();
+}
+
+window.addEventListener("load", run, false);
+</script>
+</pre>
+</body>
+</html>
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -363,25 +363,29 @@ CreateInterfaceObjects(JSContext* cx, JS
  */
 bool
 DefineUnforgeableAttributes(JSContext* cx, JSObject* obj,
                             Prefable<JSPropertySpec>* props);
 
 bool
 DefineWebIDLBindingPropertiesOnXPCProto(JSContext* cx, JSObject* proto, const NativeProperties* properties);
 
-// If *vp is an object and *vp and obj are not in the same compartment, wrap *vp
-// into the compartment of obj (typically by replacing it with an Xray or
+// If *vp is a gcthing and is not in the compartment of cx, wrap *vp
+// into the compartment of cx (typically by replacing it with an Xray or
 // cross-compartment wrapper around the original object).
 inline bool
-MaybeWrapValue(JSContext* cx, JSObject* obj, JS::Value* vp)
+MaybeWrapValue(JSContext* cx, JS::Value* vp)
 {
-  if (vp->isObject() &&
-      js::GetObjectCompartment(&vp->toObject()) != js::GetContextCompartment(cx)) {
-    return JS_WrapValue(cx, vp);
+  if (vp->isGCThing()) {
+    void* gcthing = vp->toGCThing();
+    // Might be null if vp.isNull() :(
+    if (gcthing &&
+        js::GetGCThingCompartment(gcthing) != js::GetContextCompartment(cx)) {
+      return JS_WrapValue(cx, vp);
+    }
   }
 
   return true;
 }
 
 #ifdef _MSC_VER
 #define HAS_MEMBER_CHECK(_name)                                           \
   template<typename V> static yes& Check(char (*)[(&V::_name == 0) + 1])
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -292,27 +292,35 @@ DOMInterfaces = {
     'nativeType': 'JSObject'
 }],
 
 'GainNode': [
 {
     'resultNotAddRefed': [ 'gain' ],
 }],
 
+'HTMLBodyElement': {
+  'hasInstanceInterface': 'nsIDOMHTMLBodyElement',
+},
+
 'HTMLCollection': {
     'nativeType': 'nsIHTMLCollection',
     'resultNotAddRefed': [ 'item' ]
 },
 
 'HTMLDataListElement': {
     'resultNotAddRefed': [
         'options'
     ]
 },
 
+'HTMLDivElement': {
+  'hasInstanceInterface': 'nsIDOMHTMLDivElement',
+},
+
 'HTMLDocument': {
     'nativeType': 'nsHTMLDocument',
     'register': False,
     'hasXPConnectImpls': True,
     'hasInstanceInterface': 'nsIDOMHTMLDocument',
     'resultNotAddRefed': [ 'body', 'head', 'images', 'embeds', 'plugins',
                            'links', 'forms', 'scripts', 'anchors', 'applets' ],
     'implicitJSContext': [ 'open', 'write', 'writeln' ]
@@ -323,20 +331,29 @@ DOMInterfaces = {
     'hasXPConnectImpls': True,
     'hasInstanceInterface': 'nsIDOMHTMLElement',
     'resultNotAddRefed': [
         'itemType', 'itemRef', 'itemProp', 'properties', 'contextMenu', 'style',
         'offsetParent'
     ]
 },
 
+'HTMLFrameSetElement': {
+  'hasInstanceInterface': 'nsIDOMHTMLFrameSetElement',
+},
+
+'HTMLHeadingElement': {
+  'hasInstanceInterface': 'nsIDOMHTMLHeadingElement',
+},
+
 'HTMLLabelElement': {
     'resultNotAddRefed': [
         'form', 'control'
-    ]
+    ],
+    'hasInstanceInterface': 'nsIDOMHTMLLabelElement',
 },
 
 'HTMLOptionsCollection': {
     'nativeType': 'nsHTMLOptionCollection',
     'headerFile': 'nsHTMLSelectElement.h',
     'resultNotAddRefed': [ 'item' ],
     'binaryNames': {
         '__indexedsettercreator': 'SetOption'
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3207,17 +3207,17 @@ def getWrapTemplateForType(type, descrip
     def setValue(value, callWrapValue=False):
         """
         Returns the code to set the jsval to value. If "callWrapValue" is true
         MaybeWrapValue will be called on the jsval.
         """
         if not callWrapValue:
             tail = successCode
         else:
-            tail = ("if (!MaybeWrapValue(cx, ${obj}, ${jsvalPtr})) {\n" +
+            tail = ("if (!MaybeWrapValue(cx, ${jsvalPtr})) {\n" +
                     ("%s\n" % exceptionCodeIndented.define()) +
                     "}\n" +
                     successCode)
         return ("${jsvalRef} = %s;\n" +
                 tail) % (value)
 
     def wrapAndSetPtr(wrapCall, failureCode=None):
         """
@@ -3894,17 +3894,17 @@ class CGMethodCall(CGThing):
             for sig in possibleSignatures:
                 # We should not have "any" args at distinguishingIndex,
                 # since we have multiple possible signatures remaining,
                 # but "any" is never distinguishable from anything else.
                 assert not distinguishingType(sig).isAny()
                 # We can't handle unions at the distinguishing index.
                 if distinguishingType(sig).isUnion():
                     raise TypeError("No support for unions as distinguishing "
-                                    "arguments yet: %s",
+                                    "arguments yet: %s" %
                                     distinguishingArgument(sig).location)
                 # We don't support variadics as the distinguishingArgument yet.
                 # If you want to add support, consider this case:
                 #
                 #   void(long... foo);
                 #   void(long bar, Int32Array baz);
                 #
                 # in which we have to convert argument 0 to long before picking
@@ -3912,17 +3912,17 @@ class CGMethodCall(CGThing):
                 # single array in case we pick that overload, so we have to have
                 # machinery for converting argument 0 to long and then either
                 # placing it in the variadic bit or not.  Or something.  We may
                 # be able to loosen this restriction if the variadic arg is in
                 # fact at distinguishingIndex, perhaps.  Would need to
                 # double-check.
                 if distinguishingArgument(sig).variadic:
                     raise TypeError("No support for variadics as distinguishing "
-                                    "arguments yet: %s",
+                                    "arguments yet: %s" %
                                     distinguishingArgument(sig).location)
 
             # Convert all our arguments up to the distinguishing index.
             # Doesn't matter which of the possible signatures we use, since
             # they all have the same types up to that point; just use
             # possibleSignatures[0]
             caseBody = [CGGeneric("JS::Value* argv_start = JS_ARGV(cx, vp);")]
             caseBody.extend([ CGArgumentConverter(possibleSignatures[0][1][i],
@@ -6806,17 +6806,17 @@ class CGBindingRoot(CGThing):
             except NoSuchDescriptorError:
                 # just move along
                 pass
 
         def declareNativeType(nativeType):
             components = nativeType.split('::')
             className = components[-1]
             # JSObject is a struct, not a class
-            declare = CGClassForwardDeclare(className, className is "JSObject")
+            declare = CGClassForwardDeclare(className, className == "JSObject")
             if len(components) > 1:
                 declare = CGNamespace.build(components[:-1],
                                             CGWrapper(declare, declarePre='\n',
                                                       declarePost='\n'),
                                             declareOnly=True)
             return CGWrapper(declare, declarePost='\n')
 
         for x in descriptorsForForwardDeclaration:
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -1996,16 +1996,24 @@ BluetoothDBusService::GetPairedDevicePro
 nsresult
 BluetoothDBusService::SetProperty(BluetoothObjectType aType,
                                   const nsAString& aPath,
                                   const BluetoothNamedValue& aValue,
                                   BluetoothReplyRunnable* aRunnable)
 {
   NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
 
+  if (!IsReady()) {
+    BluetoothValue v;
+    nsString errorStr;
+    errorStr.AssignLiteral("Bluetooth service is not ready yet!");
+    DispatchBluetoothReply(aRunnable, v, errorStr);
+    return NS_OK;
+  }
+
   MOZ_ASSERT(aType < ArrayLength(sBluetoothDBusIfaces));
   const char* interface = sBluetoothDBusIfaces[aType];
 
   /* Compose the command */
   DBusMessage* msg = dbus_message_new_method_call("org.bluez",
                                                   NS_ConvertUTF16toUTF8(aPath).get(),
                                                   interface,
                                                   "SetProperty");
new file mode 100644
--- /dev/null
+++ b/dom/contacts/tests/marionette/manifest.ini
@@ -0,0 +1,6 @@
+[DEFAULT]
+b2g = true
+browser = false
+qemu = true
+
+[test_sim_contacts.js]
new file mode 100644
--- /dev/null
+++ b/dom/contacts/tests/marionette/test_sim_contacts.js
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 30000;
+
+SpecialPowers.addPermission("contacts-read", true, document);
+
+let mozContacts = window.navigator.mozContacts;
+ok(mozContacts);
+
+function testImportSimContacts() {
+  let request = mozContacts.getSimContacts("ADN");
+  request.onsuccess = function onsuccess() {
+    let simContacts = request.result;
+
+    // These SIM contacts are harded in external/qemu/telephony/sim_card.c
+    is(simContacts.length, 4);
+
+    is(simContacts[0].name, "Mozilla");
+    is(simContacts[0].tel[0].value, "15555218201");
+
+    is(simContacts[1].name, "Saßê黃");
+    is(simContacts[1].tel[0].value, "15555218202");
+
+    is(simContacts[2].name, "Fire 火");
+    is(simContacts[2].tel[0].value, "15555218203");
+
+    is(simContacts[3].name, "Huang 黃");
+    is(simContacts[3].tel[0].value, "15555218204");
+
+    runNextTest();
+  };
+
+  request.onerror = function onerror() {
+    ok(false, "Cannot get Sim Contacts");
+    runNextTest();
+  };
+};
+
+let tests = [
+  testImportSimContacts,
+];
+
+function runNextTest() {
+  let test = tests.pop();
+  if (!test) {
+    cleanUp();
+    return;
+  }
+
+  test();
+}
+
+function cleanUp() {
+  SpecialPowers.removePermission("contacts-read", document);
+  finish();
+}
+
+runNextTest();
--- a/dom/devicestorage/Makefile.in
+++ b/dom/devicestorage/Makefile.in
@@ -9,17 +9,19 @@ VPATH            = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE           = dom
 LIBRARY_NAME     = domdevicestorage_s
 XPIDL_MODULE     = dom_devicestorage
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 include $(topsrcdir)/dom/dom-config.mk
 
 EXPORTS_NAMESPACES = mozilla/dom/devicestorage
 
 EXPORTS_mozilla/dom/devicestorage = \
   DeviceStorageRequestChild.h \
   DeviceStorageRequestParent.h \
--- a/dom/file/Makefile.in
+++ b/dom/file/Makefile.in
@@ -1,25 +1,27 @@
 # 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/.
 
 DEPTH            = @DEPTH@
 topsrcdir        = @top_srcdir@
 srcdir           = @srcdir@
 VPATH            = @srcdir@
-FAIL_ON_WARNINGS := 1
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE           = dom
 LIBRARY_NAME     = domfile_s
 XPIDL_MODULE     = dom_file
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
+ifndef _MSC_VER
+FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 include $(topsrcdir)/dom/dom-config.mk
 
 EXPORTS_NAMESPACES = mozilla/dom/file
 
 CPPSRCS = \
   AsyncHelper.cpp \
   DOMFileHandle.cpp \
--- a/dom/indexedDB/Makefile.in
+++ b/dom/indexedDB/Makefile.in
@@ -1,25 +1,27 @@
 # 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/.
 
 DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
-FAIL_ON_WARNINGS := 1
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = dom
 LIBRARY_NAME = dom_indexeddb_s
 XPIDL_MODULE = dom_indexeddb
 LIBXUL_LIBRARY = 1
 FORCE_STATIC_LIB = 1
+ifndef _MSC_VER
+FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 EXPORTS_NAMESPACES = mozilla/dom/indexedDB
 
 CPPSRCS = \
   AsyncConnectionHelper.cpp \
   CheckPermissionsHelper.cpp \
   DatabaseInfo.cpp \
   FileInfo.cpp \
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -75,16 +75,17 @@
 #include "nsSystemInfo.h"
 #include "nsThreadUtils.h"
 #include "nsToolkitCompsCID.h"
 #include "nsWidgetsCID.h"
 #include "SandboxHal.h"
 #include "StructuredCloneUtils.h"
 #include "TabParent.h"
 #include "URIUtils.h"
+#include "nsGeolocation.h"
 
 #ifdef ANDROID
 # include "gfxAndroidPlatform.h"
 #endif
 
 #ifdef MOZ_CRASHREPORTER
 # include "nsExceptionHandler.h"
 # include "nsICrashReporter.h"
@@ -1964,16 +1965,25 @@ ContentParent::RecvRemoveGeolocationList
       return true;
     }
     geo->ClearWatch(mGeolocationWatchID);
     mGeolocationWatchID = -1;
   }
   return true;
 }
 
+bool
+ContentParent::RecvSetGeolocationHigherAccuracy(const bool& aEnable)
+{
+    nsRefPtr<nsGeolocationService> geoSvc =
+        nsGeolocationService::GetGeolocationService();
+    geoSvc->SetHigherAccuracy(aEnable);
+    return true;
+}
+
 NS_IMETHODIMP
 ContentParent::HandleEvent(nsIDOMGeoPosition* postion)
 {
   unused << SendGeolocationUpdate(GeoPosition(postion));
   return NS_OK;
 }
 
 nsConsoleService *
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -297,16 +297,17 @@ private:
     virtual bool RecvSyncMessage(const nsString& aMsg,
                                  const ClonedMessageData& aData,
                                  InfallibleTArray<nsString>* aRetvals);
     virtual bool RecvAsyncMessage(const nsString& aMsg,
                                   const ClonedMessageData& aData);
 
     virtual bool RecvAddGeolocationListener();
     virtual bool RecvRemoveGeolocationListener();
+    virtual bool RecvSetGeolocationHigherAccuracy(const bool& aEnable);
 
     virtual bool RecvConsoleMessage(const nsString& aMessage);
     virtual bool RecvScriptError(const nsString& aMessage,
                                  const nsString& aSourceName,
                                  const nsString& aSourceLine,
                                  const uint32_t& aLineNumber,
                                  const uint32_t& aColNumber,
                                  const uint32_t& aFlags,
--- a/dom/ipc/Makefile.in
+++ b/dom/ipc/Makefile.in
@@ -9,17 +9,19 @@ VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = dom
 LIBRARY_NAME = domipc_s
 LIBXUL_LIBRARY = 1
 FORCE_STATIC_LIB = 1
 EXPORT_LIBRARY = 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 TEST_DIRS += tests
 endif
 
 EXPORTS = PCOMContentPermissionRequestChild.h
 
 EXPORTS_NAMESPACES = \
@@ -76,16 +78,17 @@ include $(topsrcdir)/config/rules.mk
 LOCAL_INCLUDES += \
 	-I$(srcdir)/../../content/base/src \
 	-I$(srcdir)/../../content/events/src \
 	-I$(srcdir)/../../docshell/base \
 	-I$(topsrcdir)/chrome/src \
 	-I$(topsrcdir)/uriloader/exthandler \
 	-I$(srcdir)/../../netwerk/base/src \
 	-I$(srcdir)/../src/base \
+	-I$(srcdir)/../src/geolocation \
 	-I$(srcdir)/../src/storage \
 	-I$(srcdir)/../../xpcom/base \
 	-I$(topsrcdir)/dom/indexedDB \
 	-I$(topsrcdir)/dom/indexedDB/ipc \
 	-I$(topsrcdir)/extensions/cookie \
 	-I$(topsrcdir)/dom/base \
 	-I$(topsrcdir)/toolkit/xre \
 	-I$(topsrcdir)/hal/sandbox \
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -392,16 +392,17 @@ parent:
                           nsString name);
 
     PExternalHelperApp(OptionalURIParams uri, nsCString aMimeContentType,
                        nsCString aContentDisposition, bool aForceSave,
                        int64_t aContentLength, OptionalURIParams aReferrer);
 
     AddGeolocationListener();
     RemoveGeolocationListener();
+    SetGeolocationHigherAccuracy(bool enable);
 
     ConsoleMessage(nsString message);
     ScriptError(nsString message, nsString sourceName, nsString sourceLine,
                 uint32_t lineNumber, uint32_t colNumber, uint32_t flags,
                 nsCString category); 
 
     // nsIPermissionManager messages
     sync ReadPermissions() returns (Permission[] permissions);
--- a/dom/media/Makefile.in
+++ b/dom/media/Makefile.in
@@ -10,17 +10,19 @@ relativesrcdir   = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE           = dom
 XPIDL_MODULE     = dom_media
 LIBRARY_NAME     = dom_media_s
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 include $(topsrcdir)/dom/dom-config.mk
 
 EXTRA_COMPONENTS = \
   PeerConnection.js \
   PeerConnection.manifest \
   $(NULL)
 
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -665,32 +665,28 @@ public:
     nsTArray<nsRefPtr<MediaEngineAudioSource> > audioSources;
     mManager->GetBackend()->EnumerateAudioDevices(&audioSources);
     audioCount = audioSources.Length();
 
     nsTArray<nsCOMPtr<nsIMediaDevice> > *devices =
       new nsTArray<nsCOMPtr<nsIMediaDevice> >;
 
     /**
-     * We only display available devices in the UI for now. We can easily
-     * change this later, when we implement a more sophisticated UI that
-     * lets the user revoke a device currently held by another tab (or
-     * we decide to provide a stream from a device already allocated).
+     * We're allowing multiple tabs to access the same camera for parity
+     * with Chrome.  See bug 811757 for some of the issues surrounding
+     * this decision.  To disallow, we'd filter by IsAvailable() as we used
+     * to.
      */
     for (i = 0; i < videoCount; i++) {
       MediaEngineVideoSource *vSource = videoSources[i];
-      if (vSource->IsAvailable()) {
-        devices->AppendElement(new MediaDevice(vSource));
-      }
+      devices->AppendElement(new MediaDevice(vSource));
     }
     for (i = 0; i < audioCount; i++) {
       MediaEngineAudioSource *aSource = audioSources[i];
-      if (aSource->IsAvailable()) {
-        devices->AppendElement(new MediaDevice(aSource));
-      }
+      devices->AppendElement(new MediaDevice(aSource));
     }
 
     NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(
       mSuccess, mError, *devices
     ));
     return NS_OK;
   }
 
@@ -1098,9 +1094,22 @@ MediaManager::GetActiveMediaCaptureWindo
     return rv;
 
   mActiveWindows.EnumerateRead(WindowsHashToArrayFunc, array);
 
   *aArray = array;
   return NS_OK;
 }
 
+void
+GetUserMediaCallbackMediaStreamListener::Invalidate()
+{
+  nsRefPtr<MediaOperationRunnable> runnable;
+  // We can't take a chance on blocking here, so proxy this to another
+  // thread.
+  // Pass a ref to us (which is threadsafe) so it can query us for the
+  // source stream info.
+  runnable = new MediaOperationRunnable(MEDIA_STOP,
+                                        this, mAudioSource, mVideoSource);
+  mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
+}
+
 } // namespace mozilla
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -22,22 +22,16 @@ namespace mozilla {
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* GetMediaManagerLog();
 #define MM_LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg)
 #else
 #define MM_LOG(msg)
 #endif
 
-// We only support 1 audio and 1 video track for now.
-enum {
-  kVideoTrack = 1,
-  kAudioTrack = 2
-};
-
 class GetUserMediaNotificationEvent: public nsRunnable
 {
   public:
     enum GetUserMediaStatus {
       STARTING,
       STOPPING
     };
     GetUserMediaNotificationEvent(GetUserMediaStatus aStatus)
@@ -62,23 +56,100 @@ class GetUserMediaNotificationEvent: pub
       }
       return NS_OK;
     }
 
   protected:
     GetUserMediaStatus mStatus;
 };
 
+/**
+ * This class is an implementation of MediaStreamListener. This is used
+ * to Start() and Stop() the underlying MediaEngineSource when MediaStreams
+ * are assigned and deassigned in content.
+ */
+class GetUserMediaCallbackMediaStreamListener : public MediaStreamListener
+{
+public:
+  GetUserMediaCallbackMediaStreamListener(nsIThread *aThread,
+    nsDOMMediaStream* aStream,
+    MediaEngineSource* aAudioSource,
+    MediaEngineSource* aVideoSource)
+    : mMediaThread(aThread)
+    , mAudioSource(aAudioSource)
+    , mVideoSource(aVideoSource)
+    , mStream(aStream)
+    , mSourceStream(aStream->GetStream()->AsSourceStream())
+    , mLastEndTimeAudio(0)
+    , mLastEndTimeVideo(0) { MOZ_ASSERT(mSourceStream); }
+
+  ~GetUserMediaCallbackMediaStreamListener()
+  {
+    // In theory this could be released from the MediaStreamGraph thread (RemoveListener)
+    if (mStream) {
+      nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
+      nsDOMMediaStream *stream;
+      mStream.forget(&stream);
+      // Releases directly if on MainThread already
+      NS_ProxyRelease(mainThread, stream, false);
+    }
+  }
+
+  SourceMediaStream *GetSourceStream()
+  {
+    return mStream->GetStream()->AsSourceStream();
+  }
+
+  void
+  Invalidate(); // implement in .cpp to avoid circular dependency with MediaOperationRunnable
+
+  void
+  Remove()
+  {
+    NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
+    // Caller holds strong reference to us, so no death grip required
+    mStream->GetStream()->RemoveListener(this);
+  }
+
+  // Proxy NotifyPull() to sources
+  void
+  NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime)
+  {
+    // Currently audio sources ignore NotifyPull, but they could
+    // watch it especially for fake audio.
+    if (mAudioSource) {
+      mAudioSource->NotifyPull(aGraph, mSourceStream, kAudioTrack, aDesiredTime, mLastEndTimeAudio);
+    }
+    if (mVideoSource) {
+      mVideoSource->NotifyPull(aGraph, mSourceStream, kVideoTrack, aDesiredTime, mLastEndTimeVideo);
+    }
+  }
+
+  void
+  NotifyFinished(MediaStreamGraph* aGraph)
+  {
+    Invalidate();
+    // XXX right now this calls Finish, which isn't ideal but doesn't hurt
+  }
+
+private:
+  nsCOMPtr<nsIThread> mMediaThread;
+  nsRefPtr<MediaEngineSource> mAudioSource;
+  nsRefPtr<MediaEngineSource> mVideoSource;
+  nsRefPtr<nsDOMMediaStream> mStream;
+  SourceMediaStream *mSourceStream; // mStream controls ownership
+  TrackTicks mLastEndTimeAudio;
+  TrackTicks mLastEndTimeVideo;
+};
+
 typedef enum {
   MEDIA_START,
   MEDIA_STOP
 } MediaOperation;
 
-class GetUserMediaCallbackMediaStreamListener;
-
 // Generic class for running long media operations like Start off the main
 // thread, and then (because nsDOMMediaStreams aren't threadsafe),
 // ProxyReleases mStream since it's cycle collected.
 class MediaOperationRunnable : public nsRunnable
 {
 public:
   MediaOperationRunnable(MediaOperation aType,
     nsDOMMediaStream* aStream,
@@ -86,24 +157,24 @@ public:
     MediaEngineSource* aVideoSource)
     : mType(aType)
     , mAudioSource(aAudioSource)
     , mVideoSource(aVideoSource)
     , mStream(aStream)
     {}
 
   MediaOperationRunnable(MediaOperation aType,
-    SourceMediaStream* aStream,
+    GetUserMediaCallbackMediaStreamListener* aListener,
     MediaEngineSource* aAudioSource,
     MediaEngineSource* aVideoSource)
     : mType(aType)
     , mAudioSource(aAudioSource)
     , mVideoSource(aVideoSource)
     , mStream(nullptr)
-    , mSourceStream(aStream)
+    , mListener(aListener)
     {}
 
   ~MediaOperationRunnable()
   {
     // nsDOMMediaStreams are cycle-collected and thus main-thread-only for
     // refcounting and releasing
     if (mStream) {
       nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
@@ -111,37 +182,44 @@ public:
       mStream.forget(&stream);
       NS_ProxyRelease(mainThread, stream, true);
     }
   }
 
   NS_IMETHOD
   Run()
   {
+    SourceMediaStream *source;
     // No locking between these is required as all the callbacks for the
     // same MediaStream will occur on the same thread.
     if (mStream) {
-      mSourceStream = mStream->GetStream()->AsSourceStream();
+      source = mStream->GetStream()->AsSourceStream();
+    } else {
+      source = mListener->GetSourceStream();
     }
+    MOZ_ASSERT(source);
+    if (!source)  // paranoia
+      return NS_ERROR_FAILURE;
+
     switch (mType) {
       case MEDIA_START:
         {
           NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
           nsresult rv;
 
-          mSourceStream->SetPullEnabled(true);
+          source->SetPullEnabled(true);
 
           if (mAudioSource) {
-            rv = mAudioSource->Start(mSourceStream, kAudioTrack);
+            rv = mAudioSource->Start(source, kAudioTrack);
             if (NS_FAILED(rv)) {
               MM_LOG(("Starting audio failed, rv=%d",rv));
             }
           }
           if (mVideoSource) {
-            rv = mVideoSource->Start(mSourceStream, kVideoTrack);
+            rv = mVideoSource->Start(source, kVideoTrack);
             if (NS_FAILED(rv)) {
               MM_LOG(("Starting video failed, rv=%d",rv));
             }
           }
 
           MM_LOG(("started all sources"));
           nsRefPtr<GetUserMediaNotificationEvent> event =
             new GetUserMediaNotificationEvent(GetUserMediaNotificationEvent::STARTING);
@@ -150,25 +228,25 @@ public:
           NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
         }
         break;
 
       case MEDIA_STOP:
         {
           NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
           if (mAudioSource) {
-            mAudioSource->Stop();
+            mAudioSource->Stop(source, kAudioTrack);
             mAudioSource->Deallocate();
           }
           if (mVideoSource) {
-            mVideoSource->Stop();
+            mVideoSource->Stop(source, kVideoTrack);
             mVideoSource->Deallocate();
           }
           // Do this after stopping all tracks with EndTrack()
-          mSourceStream->Finish();
+          source->Finish();
 
           nsRefPtr<GetUserMediaNotificationEvent> event =
             new GetUserMediaNotificationEvent(GetUserMediaNotificationEvent::STOPPING);
 
           NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
         }
         break;
 
@@ -179,104 +257,17 @@ public:
     return NS_OK;
   }
 
 private:
   MediaOperation mType;
   nsRefPtr<MediaEngineSource> mAudioSource; // threadsafe
   nsRefPtr<MediaEngineSource> mVideoSource; // threadsafe
   nsRefPtr<nsDOMMediaStream> mStream;       // not threadsafe
-  SourceMediaStream *mSourceStream;
-};
-
-/**
- * This class is an implementation of MediaStreamListener. This is used
- * to Start() and Stop() the underlying MediaEngineSource when MediaStreams
- * are assigned and deassigned in content.
- */
-class GetUserMediaCallbackMediaStreamListener : public MediaStreamListener
-{
-public:
-  GetUserMediaCallbackMediaStreamListener(nsIThread *aThread,
-    nsDOMMediaStream* aStream,
-    MediaEngineSource* aAudioSource,
-    MediaEngineSource* aVideoSource)
-    : mMediaThread(aThread)
-    , mAudioSource(aAudioSource)
-    , mVideoSource(aVideoSource)
-    , mStream(aStream) {}
-
-  ~GetUserMediaCallbackMediaStreamListener()
-  {
-    // In theory this could be released from the MediaStreamGraph thread (RemoveListener)
-    if (mStream) {
-      nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
-      nsDOMMediaStream *stream;
-      mStream.forget(&stream);
-      // Releases directly if on MainThread already
-      NS_ProxyRelease(mainThread, stream, false);
-    }
-  }
-
-  void
-  Invalidate()
-  {
-    nsRefPtr<MediaOperationRunnable> runnable;
-
-    // We can't take a chance on blocking here, so proxy this to another
-    // thread.
-    // XXX FIX! I'm cheating and passing a raw pointer to the sourcestream
-    // which is valid as long as the mStream pointer here is.
-    // Solutions (see bug 825235):
-    // a) if on MainThread, pass mStream and let it addref
-    //    (MediaOperation will need to ProxyRelease however)
-    // b) if on MediaStreamGraph thread, dispatch a runnable to MainThread
-    //    to call Invalidate() (with a strong ref to this listener)
-    runnable = new MediaOperationRunnable(MEDIA_STOP,
-                                          mStream->GetStream()->AsSourceStream(),
-                                          mAudioSource, mVideoSource);
-    mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
-
-    return;
-  }
-
-  void
-  Remove()
-  {
-    NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
-    // Caller holds strong reference to us, so no death grip required
-    mStream->GetStream()->RemoveListener(this);
-  }
-
-  // Proxy NotifyPull() to sources
-  void
-  NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime)
-  {
-    // Currently audio sources ignore NotifyPull, but they could
-    // watch it especially for fake audio.
-    if (mAudioSource) {
-      mAudioSource->NotifyPull(aGraph, aDesiredTime);
-    }
-    if (mVideoSource) {
-      mVideoSource->NotifyPull(aGraph, aDesiredTime);
-    }
-  }
-
-  void
-  NotifyFinished(MediaStreamGraph* aGraph)
-  {
-    Invalidate();
-    // XXX right now this calls Finish, which isn't ideal but doesn't hurt
-  }
-
-private:
-  nsCOMPtr<nsIThread> mMediaThread;
-  nsRefPtr<MediaEngineSource> mAudioSource;
-  nsRefPtr<MediaEngineSource> mVideoSource;
-  nsRefPtr<nsDOMMediaStream> mStream;
+  nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener; // threadsafe
 };
 
 typedef nsTArray<nsRefPtr<GetUserMediaCallbackMediaStreamListener> > StreamListeners;
 typedef nsClassHashtable<nsUint64HashKey, StreamListeners> WindowTable;
 
 class MediaDevice : public nsIMediaDevice
 {
 public:
--- a/dom/media/tests/mochitest/mediaStreamPlayback.js
+++ b/dom/media/tests/mochitest/mediaStreamPlayback.js
@@ -48,40 +48,30 @@ function MediaStreamPlayback(mediaElemen
     var canPlayThroughCallback = function() {
       // Disable the canplaythrough event listener to prevent multiple calls
       canPlayThroughFired = true;
       self.mediaElement.removeEventListener('canplaythrough',
         canPlayThroughCallback, false);
 
       is(self.mediaElement.paused, false,
         "Media element should be playing");
-      is(self.mediaElement.ended, false,
-        "Media element should not have ended");
       is(self.mediaElement.duration, Number.POSITIVE_INFINITY,
         "Duration should be infinity");
 
       // When the media element is playing with a real-time stream, we
       // constantly switch between having data to play vs. queuing up data,
       // so we can only check that the ready state is one of those two values
       ok(self.mediaElement.readyState === HTMLMediaElement.HAVE_ENOUGH_DATA ||
          self.mediaElement.readyState === HTMLMediaElement.HAVE_CURRENT_DATA,
          "Ready state shall be HAVE_ENOUGH_DATA or HAVE_CURRENT_DATA");
 
       is(self.mediaElement.seekable.length, 0,
          "Seekable length shall be zero");
       is(self.mediaElement.buffered.length, 0,
          "Buffered length shall be zero");
-      is(self.mediaElement.played.length, 1, "Played length shall be one");
-
-      if(self.mediaElement.played.length > 0) {
-        is(self.mediaElement.played.start(0), 0,
-          "Played start shall be zero");
-        is(self.mediaElement.played.end(0), self.mediaElement.currentTime,
-          "End shall be current time");
-      }
 
       is(self.mediaElement.seeking, false,
          "MediaElement is not seekable with MediaStream");
       ok(isNaN(self.mediaElement.startOffsetTime),
          "Start offset time shall not be a number");
       is(self.mediaElement.loop, false, "Loop shall be false");
       is(self.mediaElement.preload, "", "Preload should not exist");
       is(self.mediaElement.src, "", "No src should be defined");
--- a/dom/network/src/Makefile.in
+++ b/dom/network/src/Makefile.in
@@ -7,17 +7,19 @@ topsrcdir        = @top_srcdir@
 srcdir           = @srcdir@
 VPATH            = $(srcdir)
 
 include $(DEPTH)/config/autoconf.mk
 
 LIBRARY_NAME     = dom_network_s
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 EXTRA_COMPONENTS = \
 	TCPSocket.js \
 	TCPSocketParentIntermediary.js \
 	TCPSocket.manifest \
 	$(NULL)
 
 ifdef MOZ_B2G_RIL
--- a/dom/plugins/base/Makefile.in
+++ b/dom/plugins/base/Makefile.in
@@ -66,17 +66,19 @@ CPPSRCS		= \
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),android)
 DIRS += android
 LOCAL_INCLUDES += -I$(topsrcdir)/dom/plugins/base/android
 else
 # android_npapi.h extends the NPNVariable and NPPVariable enums
 # using #defines, which results in Wswitch warnings in gcc-4.6.
 # Therefore, enable FAIL_ON_WARNINGS only on non-Android platforms.
+ifndef _MSC_VER
 FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 endif
 
 ifeq ($(OS_ARCH),WINNT)
 	CPPSRCS += nsPluginsDirWin.cpp
 	CPPSRCS += nsPluginNativeWindowWin.cpp
 	CPPSRCS += nsPluginDirServiceProvider.cpp
 	LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/base
 else
--- a/dom/plugins/ipc/Makefile.in
+++ b/dom/plugins/ipc/Makefile.in
@@ -1,21 +1,23 @@
 # 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/.
 
 DEPTH = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
-FAIL_ON_WARNINGS := 1
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = dom
+ifndef _MSC_VER
+FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 EXPORTS_NAMESPACES = mozilla
 
 EXPORTS_mozilla = \
   PluginLibrary.h \
   $(NULL)
 
 EXPORTS_NAMESPACES = mozilla mozilla/plugins
--- a/dom/plugins/test/testplugin/Makefile.in
+++ b/dom/plugins/test/testplugin/Makefile.in
@@ -2,21 +2,23 @@
 # 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/.
 
 DEPTH     = @DEPTH@
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
-FAIL_ON_WARNINGS = 1
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE       = nptest
 LIBRARY_NAME = nptest
 MODULE_NAME  = TestPlugin
+ifndef _MSC_VER
+FAIL_ON_WARNINGS = 1
+endif # !_MSC_VER
 
 DIRS = secondplugin
 
 RELATIVE_PATH=.
 COCOA_NAME=Test
 include @srcdir@/testplugin.mk
--- a/dom/power/Makefile.in
+++ b/dom/power/Makefile.in
@@ -8,17 +8,19 @@ srcdir           = @srcdir@
 VPATH            = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 LIBRARY_NAME     = dom_power_s
 XPIDL_MODULE     = dom_power
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 include $(topsrcdir)/dom/dom-config.mk
 
 EXPORTS_NAMESPACES = mozilla/dom/power
 
 EXPORTS_mozilla/dom/power = \
   PowerManagerService.h \
   Types.h \
--- a/dom/sms/src/Makefile.in
+++ b/dom/sms/src/Makefile.in
@@ -18,17 +18,19 @@ else ifdef MOZ_B2G_RIL
 VPATH += $(srcdir)/ril
 else
 VPATH += $(srcdir)/fallback
 endif
 
 LIBRARY_NAME     = dom_sms_s
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 include $(topsrcdir)/dom/dom-config.mk
 
 EXPORTS_NAMESPACES = mozilla/dom/sms
 
 EXPORTS_mozilla/dom/sms = \
   SmsChild.h \
   SmsParent.h \
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -998,16 +998,22 @@ nsGeolocationService::SetDisconnectTimer
   mDisconnectTimer->Init(this,
                          sProviderTimeout,
                          nsITimer::TYPE_ONE_SHOT);
 }
 
 void
 nsGeolocationService::SetHigherAccuracy(bool aEnable)
 {
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    ContentChild* cpc = ContentChild::GetSingleton();
+    cpc->SendSetGeolocationHigherAccuracy(aEnable);
+    return;
+  }
+
   if (!mHigherAccuracy && aEnable) {
     for (int32_t i = 0; i < mProviders.Count(); i++) {
       mProviders[i]->SetHighAccuracy(true);
     }
   }
 
   if (mHigherAccuracy && !aEnable) {
     for (int32_t i = 0; i < mProviders.Count(); i++) {
--- a/dom/system/NetworkGeolocationProvider.js
+++ b/dom/system/NetworkGeolocationProvider.js
@@ -10,16 +10,17 @@
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 const Ci = Components.interfaces;
 const Cc = Components.classes;
 
 let gLoggingEnabled = false;
 let gTestingEnabled = false;
+let gDesist = false;
 
 let gPrivateAccessToken = '';
 let gPrivateAccessTime = 0;
 
 function LOG(aMsg) {
   if (gLoggingEnabled)
   {
     aMsg = "*** WIFI GEO: " + aMsg + "\n";
@@ -104,17 +105,23 @@ WifiGeoPositionProvider.prototype = {
     if (!gTestingEnabled)
       this.timer.initWithCallback(this, 5000, this.timer.TYPE_ONE_SHOT);
     else
       this.timer.initWithCallback(this, 200, this.timer.TYPE_REPEATING_SLACK);
   },
 
   watch: function(c, requestPrivate) {
     LOG("watch called");
-    if (!this.wifiService) {
+
+    let useScanning = true;
+    try {
+      useScanning = Services.prefs.getBoolPref("geo.wifi.scan");
+    } catch (e) {}
+
+    if (!this.wifiService && useScanning) {
       this.wifiService = Cc["@mozilla.org/wifi/monitor;1"].getService(Components.interfaces.nsIWifiMonitor);
       this.wifiService.startWatching(this);
       this.lastRequestPrivate = requestPrivate;
     }
     if (this.hasSeenWiFi) {
       this.hasSeenWiFi = false;
       this.wifiService.stopWatching(this);
       this.wifiService.startWatching(this);
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -920,17 +920,17 @@ let RIL = {
    * @param [optional] aid
    *        AID value.
    */
   enterICCPIN: function enterICCPIN(options) {
     Buf.newParcel(REQUEST_ENTER_SIM_PIN, options);
     Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 1 : 2);
     Buf.writeString(options.pin);
     if (!RILQUIRKS_V5_LEGACY) {
-      Buf.writeString(options.aid ? options.aid : this.aid);
+      Buf.writeString(options.aid || this.aid);
     }
     Buf.sendParcel();
   },
 
   /**
    * Enter a PIN2 to unlock the ICC.
    *
    * @param pin
@@ -938,17 +938,17 @@ let RIL = {
    * @param [optional] aid
    *        AID value.
    */
   enterICCPIN2: function enterICCPIN2(options) {
     Buf.newParcel(REQUEST_ENTER_SIM_PIN2, options);
     Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 1 : 2);
     Buf.writeString(options.pin);
     if (!RILQUIRKS_V5_LEGACY) {
-      Buf.writeString(options.aid ? options.aid : this.aid);
+      Buf.writeString(options.aid || this.aid);
     }
     Buf.sendParcel();
   },
 
   /**
    * Requests a network personalization be deactivated.
    *
    * @param type
@@ -1002,17 +1002,17 @@ let RIL = {
    *        AID value.
    */
   changeICCPIN: function changeICCPIN(options) {
     Buf.newParcel(REQUEST_CHANGE_SIM_PIN, options);
     Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 2 : 3);
     Buf.writeString(options.pin);
     Buf.writeString(options.newPin);
     if (!RILQUIRKS_V5_LEGACY) {
-      Buf.writeString(options.aid ? options.aid : this.aid);
+      Buf.writeString(options.aid || this.aid);
     }
     Buf.sendParcel();
   },
 
   /**
    * Change the current ICC PIN2 number.
    *
    * @param pin
@@ -1023,17 +1023,17 @@ let RIL = {
    *        AID value.
    */
   changeICCPIN2: function changeICCPIN2(options) {
     Buf.newParcel(REQUEST_CHANGE_SIM_PIN2, options);
     Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 2 : 3);
     Buf.writeString(options.pin);
     Buf.writeString(options.newPin);
     if (!RILQUIRKS_V5_LEGACY) {
-      Buf.writeString(options.aid ? options.aid : this.aid);
+      Buf.writeString(options.aid || this.aid);
     }
     Buf.sendParcel();
   },
   /**
    * Supplies ICC PUK and a new PIN to unlock the ICC.
    *
    * @param puk
    *        String containing the PUK value.
@@ -1043,17 +1043,17 @@ let RIL = {
    *        AID value.
    */
    enterICCPUK: function enterICCPUK(options) {
      Buf.newParcel(REQUEST_ENTER_SIM_PUK, options);
      Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 2 : 3);
      Buf.writeString(options.puk);
      Buf.writeString(options.newPin);
      if (!RILQUIRKS_V5_LEGACY) {
-       Buf.writeString(options.aid ? options.aid : this.aid);
+       Buf.writeString(options.aid || this.aid);
      }
      Buf.sendParcel();
    },
 
   /**
    * Supplies ICC PUK2 and a new PIN2 to unlock the ICC.
    *
    * @param puk
@@ -1064,17 +1064,17 @@ let RIL = {
    *        AID value.
    */
    enterICCPUK2: function enterICCPUK2(options) {
      Buf.newParcel(REQUEST_ENTER_SIM_PUK2, options);
      Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 2 : 3);
      Buf.writeString(options.puk);
      Buf.writeString(options.newPin);
      if (!RILQUIRKS_V5_LEGACY) {
-       Buf.writeString(options.aid ? options.aid : this.aid);
+       Buf.writeString(options.aid || this.aid);
      }
      Buf.sendParcel();
    },
 
   /**
    * Helper function for fetching the state of ICC locks.
    */
   iccGetCardLock: function iccGetCardLock(options) {
@@ -1118,17 +1118,17 @@ let RIL = {
    */
   queryICCFacilityLock: function queryICCFacilityLock(options) {
     Buf.newParcel(REQUEST_QUERY_FACILITY_LOCK, options);
     Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 3 : 4);
     Buf.writeString(options.facility);
     Buf.writeString(options.password);
     Buf.writeString(options.serviceClass.toString());
     if (!RILQUIRKS_V5_LEGACY) {
-      Buf.writeString(options.aid ? options.aid : this.aid);
+      Buf.writeString(options.aid || this.aid);
     }
     Buf.sendParcel();
   },
 
   /**
    * Set ICC Pin lock. A wrapper call to setICCFacilityLock.
    *
    * @param enabled
@@ -1165,17 +1165,17 @@ let RIL = {
   setICCFacilityLock: function setICCFacilityLock(options) {
     Buf.newParcel(REQUEST_SET_FACILITY_LOCK, options);
     Buf.writeUint32(RILQUIRKS_V5_LEGACY ? 3 : 4);
     Buf.writeString(options.facility);
     Buf.writeString(options.enabled ? "1" : "0");
     Buf.writeString(options.password);
     Buf.writeString(options.serviceClass.toString());
     if (!RILQUIRKS_V5_LEGACY) {
-      Buf.writeString(options.aid ? options.aid : this.aid);
+      Buf.writeString(options.aid || this.aid);
     }
     Buf.sendParcel();
   },
 
   /**
    *  Request an ICC I/O operation.
    *
    *  See TS 27.007 "restricted SIM" operation, "AT Command +CRSM".
@@ -1200,480 +1200,42 @@ let RIL = {
   iccIO: function iccIO(options) {
     let token = Buf.newParcel(REQUEST_SIM_IO, options);
     Buf.writeUint32(options.command);
     Buf.writeUint32(options.fileId);
     Buf.writeString(options.pathId);
     Buf.writeUint32(options.p1);
     Buf.writeUint32(options.p2);
     Buf.writeUint32(options.p3);
-    Buf.writeString(options.data);
-    Buf.writeString(options.pin2 ? options.pin2 : null);
+    Buf.writeString(options.data || null);
+    Buf.writeString(options.pin2 || null);
     if (!RILQUIRKS_V5_LEGACY) {
-      Buf.writeString(options.aid ? options.aid : this.aid);
+      Buf.writeString(options.aid || this.aid);
     }
     Buf.sendParcel();
   },
 
   /**
-   * Fetch ICC records.
-   */
-  fetchICCRecords: function fetchICCRecords() {
-    this.getICCID();
-    this.getIMSI();
-    this.getMSISDN();
-    this.getAD();
-    this.getSST();
-    this.getMBDN();
-  },
-
-  /**
-   * Update the ICC information to RadioInterfaceLayer.
-   */
-  _handleICCInfoChange: function _handleICCInfoChange() {
-    this.iccInfo.rilMessageType = "iccinfochange";
-    this.sendDOMMessage(this.iccInfo);
-  },
-
-  /**
-   * This will compute the spnDisplay field of the network.
-   * See TS 22.101 Annex A and TS 51.011 10.3.11 for details.
-   *
-   * @return True if some of iccInfo is changed in by this function.
-   */
-  updateDisplayCondition: function updateDisplayCondition() {
-    // If EFspn isn't existed in SIM or it haven't been read yet, we should
-    // just set isDisplayNetworkNameRequired = true and
-    // isDisplaySpnRequired = false
-    let iccInfo = this.iccInfo;
-    let iccInfoPriv = this.iccInfoPrivate;
-    let iccSpn = iccInfoPriv.SPN;
-    let origIsDisplayNetworkNameRequired = iccInfo.isDisplayNetworkNameRequired;
-    let origIsDisplaySPNRequired = iccInfo.isDisplaySpnRequired;
-
-    if (!iccSpn) {
-      iccInfo.isDisplayNetworkNameRequired = true;
-      iccInfo.isDisplaySpnRequired = false;
-    } else {
-      let operatorMnc = this.operator.mnc;
-      let operatorMcc = this.operator.mcc;
-
-      // First detect if we are on HPLMN or one of the PLMN
-      // specified by the SIM card.
-      let isOnMatchingPlmn = false;
-
-      // If the current network is the one defined as mcc/mnc
-      // in SIM card, it's okay.
-      if (iccInfo.mcc == operatorMcc && iccInfo.mnc == operatorMnc) {
-        isOnMatchingPlmn = true;
-      }
-
-      // Test to see if operator's mcc/mnc match mcc/mnc of PLMN.
-      if (!isOnMatchingPlmn && iccInfoPriv.SPDI) {
-        let iccSpdi = iccInfoPriv.SPDI; // PLMN list
-        for (let plmn in iccSpdi) {
-          let plmnMcc = iccSpdi[plmn].mcc;
-          let plmnMnc = iccSpdi[plmn].mnc;
-          isOnMatchingPlmn = (plmnMcc == operatorMcc) && (plmnMnc == operatorMnc);
-          if (isOnMatchingPlmn) {
-            break;
-          }
-        }
-      }
-
-      if (isOnMatchingPlmn) {
-        // The first bit of display condition tells us if we should display
-        // registered PLMN.
-        if (DEBUG) debug("updateDisplayCondition: PLMN is HPLMN or PLMN is in PLMN list");
-
-        // TS 31.102 Sec. 4.2.66 and TS 51.011 Sec. 10.3.50
-        // EF_SPDI contains a list of PLMNs in which the Service Provider Name
-        // shall be displayed.
-        iccInfo.isDisplaySpnRequired = true;
-        if (iccSpn.spnDisplayCondition & 0x01) {
-          iccInfo.isDisplayNetworkNameRequired = true;
-        } else {
-          iccInfo.isDisplayNetworkNameRequired = false;
-        }
-      } else {
-        // The second bit of display condition tells us if we should display
-        // registered PLMN.
-        if (DEBUG) debug("updateICCDisplayName: PLMN isn't HPLMN and PLMN isn't in PLMN list");
-
-        // We didn't found the requirement of displaying network name if
-        // current PLMN isn't HPLMN nor one of PLMN in SPDI. So we keep
-        // isDisplayNetworkNameRequired false.
-        if (iccSpn.spnDisplayCondition & 0x02) {
-          iccInfo.isDisplayNetworkNameRequired = false;
-          iccInfo.isDisplaySpnRequired = false;
-        } else {
-          iccInfo.isDisplayNetworkNameRequired = false;
-          iccInfo.isDisplaySpnRequired = true;
-        }
-      }
-    }
-
-    if (DEBUG) {
-      debug("updateDisplayCondition: isDisplayNetworkNameRequired = " + iccInfo.isDisplayNetworkNameRequired);
-      debug("updateDisplayCondition: isDisplaySpnRequired = " + iccInfo.isDisplaySpnRequired);
-    }
-
-    return ((origIsDisplayNetworkNameRequired !== iccInfo.isDisplayNetworkNameRequired) ||
-            (origIsDisplaySPNRequired !== iccInfo.isDisplaySpnRequired));
-  },
-
-  /**
-   * Get EF_phase.
-   * This EF is only available in SIM.
-   */
-  getICCPhase: function getICCPhase() {
-    function callback() {
-      let length = Buf.readUint32();
-
-      let phase = GsmPDUHelper.readHexOctet();
-      // If EF_phase is coded '03' or greater, an ME supporting STK shall
-      // perform the PROFILE DOWNLOAD procedure.
-      if (phase >= ICC_PHASE_2_PROFILE_DOWNLOAD_REQUIRED) {
-        this.sendStkTerminalProfile(STK_SUPPORTED_TERMINAL_PROFILE);
-      }
-
-      Buf.readStringDelimiter(length);
-    }
-
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_PHASE,
-      pathId:    EF_PATH_MF_SIM + EF_PATH_DF_GSM,
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_TRANSPARENT,
-      callback:  callback,
-    });
-  },
-
-  /**
    * Get IMSI.
    *
    * @param [optional] aid
    *        AID value.
    */
   getIMSI: function getIMSI(aid) {
     if (RILQUIRKS_V5_LEGACY) {
       Buf.simpleRequest(REQUEST_GET_IMSI);
       return;
     }
     let token = Buf.newParcel(REQUEST_GET_IMSI);
     Buf.writeUint32(1);
-    Buf.writeString(aid ? aid : this.aid);
+    Buf.writeString(aid || this.aid);
     Buf.sendParcel();
   },
 
   /**
-   * Read the ICCD from the ICC card.
-   */
-  getICCID: function getICCID() {
-    function callback() {
-      let length = Buf.readUint32();
-      this.iccInfo.iccid = GsmPDUHelper.readSwappedNibbleBcdString(length / 2);
-      Buf.readStringDelimiter(length);
-
-      if (DEBUG) debug("ICCID: " + this.iccInfo.iccid);
-      if (this.iccInfo.iccid) {
-        this._handleICCInfoChange();
-      }
-    }
-
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_ICCID,
-      pathId:    this._getPathIdForICCRecord(ICC_EF_ICCID),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_TRANSPARENT,
-      callback:  callback,
-    });
-  },
-
-  /**
-   * Read the MSISDN from the ICC.
-   */
-  getMSISDN: function getMSISDN() {
-    function callback(options) {
-      let parseCallback = function parseCallback(msisdn) {
-        if (this.iccInfo.msisdn === msisdn.number) {
-          return;
-        }
-        this.iccInfo.msisdn = msisdn.number;
-        if (DEBUG) debug("MSISDN: " + this.iccInfo.msisdn);
-        this._handleICCInfoChange();
-      }
-      this.parseDiallingNumber(options, parseCallback);
-    }
-
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_MSISDN,
-      pathId:    this._getPathIdForICCRecord(ICC_EF_MSISDN),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_LINEAR_FIXED,
-      callback:  callback,
-    });
-  },
-
-  /**
-   * Read the AD (Administrative Data) from the ICC.
-   */
-  getAD: function getAD() {
-    function callback() {
-      let length = Buf.readUint32();
-      // Each octet is encoded into two chars.
-      let len = length / 2;
-      this.iccInfo.ad = GsmPDUHelper.readHexOctetArray(len);
-      Buf.readStringDelimiter(length);
-
-      if (DEBUG) {
-        let str = "";
-        for (let i = 0; i < this.iccInfo.ad.length; i++) {
-          str += this.iccInfo.ad[i] + ", ";
-        }
-        debug("AD: " + str);
-      }
-
-      if (this.iccInfo.imsi) {
-        // MCC is the first 3 digits of IMSI
-        this.iccInfo.mcc = parseInt(this.iccInfo.imsi.substr(0,3));
-        // The 4th byte of the response is the length of MNC
-        this.iccInfo.mnc = parseInt(this.iccInfo.imsi.substr(3, this.iccInfo.ad[3]));
-        if (DEBUG) debug("MCC: " + this.iccInfo.mcc + " MNC: " + this.iccInfo.mnc);
-        this._handleICCInfoChange();
-      }
-    }
-
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_AD,
-      pathId:    this._getPathIdForICCRecord(ICC_EF_AD),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_TRANSPARENT,
-      callback:  callback,
-    });
-  },
-
-  /**
-   * Read the SPN (Service Provider Name) from the ICC.
-   */
-  getSPN: function getSPN() {
-    function callback() {
-      let length = Buf.readUint32();
-      // Each octet is encoded into two chars.
-      // Minus 1 because first is used to store display condition
-      let len = (length / 2) - 1;
-      let spnDisplayCondition = GsmPDUHelper.readHexOctet();
-      let spn = GsmPDUHelper.readAlphaIdentifier(len);
-      Buf.readStringDelimiter(length);
-
-      if (DEBUG) {
-        debug("SPN: spn = " + spn +
-              ", spnDisplayCondition = " + spnDisplayCondition);
-      }
-
-      this.iccInfoPrivate.SPN = {
-        spn : spn,
-        spnDisplayCondition : spnDisplayCondition,
-      };
-      this.iccInfo.spn = spn;
-      this.updateDisplayCondition();
-      this._handleICCInfoChange();
-    }
-
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_SPN,
-      pathId:    this._getPathIdForICCRecord(ICC_EF_SPN),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_TRANSPARENT,
-      callback:  callback,
-    });
-  },
-
-  /**
-   * Read the PLMNsel (Public Land Mobile Network) from the ICC.
-   *
-   * See ETSI TS 100.977 section 10.3.4 EF_PLMNsel
-   */
-  getPLMNSelector: function getPLMNSelector() {
-    function callback() {
-      if (DEBUG) debug("PLMN Selector: Process PLMN Selector");
-
-      let length = Buf.readUint32();
-      this.iccInfoPrivate.PLMN = this.readPLMNEntries(length/3);
-      Buf.readStringDelimiter(length);
-
-      if (DEBUG) debug("PLMN Selector: " + JSON.stringify(this.iccInfoPrivate.PLMN));
-
-      if (this.updateDisplayCondition()) {
-        this._handleICCInfoChange();
-      }
-    }
-
-    // PLMN List is Service 7 in SIM, EF_PLMNsel
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_PLMNsel,
-      pathId:    this._getPathIdForICCRecord(ICC_EF_PLMNsel),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_TRANSPARENT,
-      callback:  callback,
-    });
-  },
-
-  /**
-   * Read the SPDI (Service Provider Display Information) from the ICC.
-   *
-   * See TS 131.102 section 4.2.66 for USIM and TS 51.011 section 10.3.50
-   * for SIM.
-   */
-  getSPDI: function getSPDI() {
-    function callback() {
-      let length = Buf.readUint32();
-      let readLen = 0;
-      let endLoop = false;
-      this.iccInfoPrivate.SPDI = null;
-      while ((readLen < length / 2) && !endLoop) {
-        let tlvTag = GsmPDUHelper.readHexOctet();
-        let tlvLen = GsmPDUHelper.readHexOctet();
-        readLen += 2; // For tag and length fields.
-        switch (tlvTag) {
-        case SPDI_TAG_SPDI:
-          // The value part itself is a TLV.
-          continue;
-        case SPDI_TAG_PLMN_LIST:
-          // This PLMN list is what we want.
-          this.iccInfoPrivate.SPDI = this.readPLMNEntries(tlvLen / 3);
-          readLen += tlvLen;
-          endLoop = true;
-          break;
-        default:
-          // We don't care about its content if its tag is not SPDI nor
-          // PLMN_LIST.
-          endLoop = true;
-          break;
-        }
-      }
-
-      // Consume unread octets.
-      Buf.seekIncoming((length / 2 - readLen) * PDU_HEX_OCTET_SIZE);
-      Buf.readStringDelimiter(length);
-
-      if (DEBUG) debug("SPDI: " + JSON.stringify(this.iccInfoPrivate.SPDI));
-      if (this.updateDisplayCondition()) {
-        this._handleICCInfoChange();
-      }
-    }
-
-    // PLMN List is Service 51 in USIM, EF_SPDI
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_SPDI,
-      pathId:    this._getPathIdForICCRecord(ICC_EF_SPDI),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_TRANSPARENT,
-      callback:  callback,
-    });
-  },
-
-  /**
-   * Get whether specificed (U)SIM service is available.
-   *
-   * @param geckoService
-   *        Service name like "ADN", "BDN", etc.
-   *
-   * @return true if the service is enabled, false otherwise.
-   */
-  isICCServiceAvailable: function isICCServiceAvailable(geckoService) {
-    let serviceTable = this.iccInfo.sst;
-    let index, bitmask;
-    if (this.appType == CARD_APPTYPE_SIM) {
-      /**
-       * Service id is valid in 1..N, and 2 bits are used to code each service.
-       *
-       * +----+--  --+----+----+
-       * | b8 | ...  | b2 | b1 |
-       * +----+--  --+----+----+
-       *
-       * b1 = 0, service not allocated.
-       *      1, service allocated.
-       * b2 = 0, service not activatd.
-       *      1, service allocated.
-       *
-       * @see 3GPP TS 51.011 10.3.7.
-       */
-      let simService = GECKO_ICC_SERVICES.sim[geckoService];
-      if (!simService) {
-        return false;
-      }
-      simService -= 1;
-      index = Math.floor(simService / 4);
-      bitmask = 2 << ((simService % 4) << 1);
-    } else {
-      /**
-       * Service id is valid in 1..N, and 1 bit is used to code each service.
-       *
-       * +----+--  --+----+----+
-       * | b8 | ...  | b2 | b1 |
-       * +----+--  --+----+----+
-       *
-       * b1 = 0, service not avaiable.
-       *      1, service available.
-       * b2 = 0, service not avaiable.
-       *      1, service available.
-       *
-       * @see 3GPP TS 31.102 4.2.8.
-       */
-      let usimService = GECKO_ICC_SERVICES.usim[geckoService];
-      if (!usimService) {
-        return false;
-      }
-      usimService -= 1;
-      index = Math.floor(usimService / 8);
-      bitmask = 1 << ((usimService % 8) << 0);
-    }
-
-    return (serviceTable &&
-           (index < serviceTable.length) &&
-           (serviceTable[index] & bitmask)) != 0;
-  },
-
-  /**
    * Choose network names using EF_OPL and EF_PNN
    * See 3GPP TS 31.102 sec. 4.2.58 and sec. 4.2.59 for USIM,
    *     3GPP TS 51.011 sec. 10.3.41 and sec. 10.3.42 for SIM.
    */
   updateNetworkName: function updateNetworkName() {
     let iccInfoPriv = this.iccInfoPrivate;
     let iccInfo = this.iccInfo;
 
@@ -1738,628 +1300,16 @@ let RIL = {
 
     if (pnnEntry) {
       return [pnnEntry.fullName, pnnEntry.shortName];
     }
     return null;
   },
 
   /**
-   * Read OPL (Operator PLMN List) from USIM.
-   *
-   * See 3GPP TS 31.102 Sec. 4.2.59 for USIM
-   *     3GPP TS 51.011 Sec. 10.3.42 for SIM.
-   */
-  getOPL: function getOPL() {
-    let opl = [];
-    function callback(options) {
-      let len = Buf.readUint32();
-      // The first 7 bytes are LAI (for UMTS) and the format of LAI is defined
-      // in 3GPP TS 23.003, Sec 4.1
-      //    +-------------+---------+
-      //    | Octet 1 - 3 | MCC/MNC |
-      //    +-------------+---------+
-      //    | Octet 4 - 7 |   LAC   |
-      //    +-------------+---------+
-      let mccMnc = [GsmPDUHelper.readHexOctet(),
-                    GsmPDUHelper.readHexOctet(),
-                    GsmPDUHelper.readHexOctet()];
-      if (mccMnc[0] != 0xFF || mccMnc[1] != 0xFF || mccMnc[2] != 0xFF) {
-        let oplElement = {};
-        let semiOctets = [];
-        for (let i = 0; i < mccMnc.length; i++) {
-          semiOctets.push((mccMnc[i] & 0xf0) >> 4);
-          semiOctets.push(mccMnc[i] & 0x0f);
-        }
-        let reformat = [semiOctets[1], semiOctets[0], semiOctets[3],
-                        semiOctets[5], semiOctets[4], semiOctets[2]];
-        let buf = "";
-        for (let i = 0; i < reformat.length; i++) {
-          if (reformat[i] != 0xF) {
-            buf += GsmPDUHelper.semiOctetToBcdChar(reformat[i]);
-          }
-          if (i === 2) {
-            // 0-2: MCC
-            oplElement.mcc = parseInt(buf);
-            buf = "";
-          } else if (i === 5) {
-            // 3-5: MNC
-            oplElement.mnc = parseInt(buf);
-          }
-        }
-        // LAC/TAC
-        oplElement.lacTacStart =
-          (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
-        oplElement.lacTacEnd =
-          (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
-        // PLMN Network Name Record Identifier
-        oplElement.pnnRecordId = GsmPDUHelper.readHexOctet();
-        if (DEBUG) {
-          debug("OPL: [" + (opl.length + 1) + "]: " + JSON.stringify(oplElement));
-        }
-        opl.push(oplElement);
-      }
-      Buf.readStringDelimiter(len);
-      if (options.p1 < options.totalRecords) {
-        options.p1++;
-        this.iccIO(options);
-      } else {
-        this.iccInfoPrivate.OPL = opl;
-      }
-    }
-
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_OPL,
-      pathId:    this._getPathIdForICCRecord(ICC_EF_OPL),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_LINEAR_FIXED,
-      callback:  callback,
-    });
-  },
-
-  /**
-   * Read PNN (PLMN Network Name) from USIM.
-   *
-   * See 3GPP TS 31.102 Sec. 4.2.58 for USIM
-   *     3GPP TS 51.011 Sec. 10.3.41 for SIM.
-   */
-  getPNN: function getPNN() {
-    let pnn = [];
-    function callback(options) {
-      let pnnElement = this.iccInfoPrivate.PNN = {};
-      let len = Buf.readUint32();
-      let readLen = 0;
-      while (len > readLen) {
-        let tlvTag = GsmPDUHelper.readHexOctet();
-        readLen = readLen + 2; // 1 Hex octet
-        if (tlvTag == 0xFF) {
-          // Unused byte
-          continue;
-        }
-        let tlvLen = GsmPDUHelper.readHexOctet();
-        let name;
-        switch (tlvTag) {
-        case PNN_IEI_FULL_NETWORK_NAME:
-          pnnElement.fullName = GsmPDUHelper.readNetworkName(tlvLen);
-          break;
-        case PNN_IEI_SHORT_NETWORK_NAME:
-          pnnElement.shortName = GsmPDUHelper.readNetworkName(tlvLen);
-          break;
-        default:
-          Buf.seekIncoming(PDU_HEX_OCTET_SIZE * tlvLen);
-        }
-        readLen += (tlvLen * 2 + 2);
-      }
-      if (DEBUG) {
-        debug("PNN: [" + (pnn.length + 1) + "]: " + JSON.stringify(pnnElement));
-      }
-      Buf.readStringDelimiter(len);
-      pnn.push(pnnElement);
-
-      if (options.p1 < options.totalRecords) {
-        options.p1++;
-        this.iccIO(options);
-      } else {
-        this.iccInfoPrivate.PNN = pnn;
-      }
-    }
-
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_PNN,
-      pathId:    this._getPathIdForICCRecord(ICC_EF_PNN),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_LINEAR_FIXED,
-      callback:  callback,
-    });
-  },
-
-  /**
-   * Read the (U)SIM Service Table from the ICC.
-   */
-  getSST: function getSST() {
-    function callback() {
-      let length = Buf.readUint32();
-      // Each octet is encoded into two chars.
-      let len = length / 2;
-      this.iccInfo.sst = GsmPDUHelper.readHexOctetArray(len);
-      Buf.readStringDelimiter(length);
-
-      if (DEBUG) {
-        let str = "";
-        for (let i = 0; i < this.iccInfo.sst.length; i++) {
-          str += this.iccInfo.sst[i] + ", ";
-        }
-        debug("SST: " + str);
-      }
-
-      // Fetch SPN and PLMN list, if some of them are available.
-      if (this.isICCServiceAvailable("SPN")) {
-        if (DEBUG) debug("SPN: SPN is available");
-        this.getSPN();
-      } else {
-        if (DEBUG) debug("SPN: SPN service is not available");
-      }
-
-      if (this.isICCServiceAvailable("SPDI")) {
-        if (DEBUG) debug("SPDI: SPDI available.");
-        this.getSPDI();
-      } else {
-        if (DEBUG) debug("SPDI: SPDI service is not available");
-      }
-
-      if (this.isICCServiceAvailable("PNN")) {
-        if (DEBUG) debug("PNN: PNN is available");
-        this.getPNN();
-      } else {
-        if (DEBUG) debug("PNN: PNN is not available");
-      }
-
-      if (this.isICCServiceAvailable("OPL")) {
-        if (DEBUG) debug("OPL: OPL is available");
-        this.getOPL();
-      } else {
-        if (DEBUG) debug("OPL: OPL is not available");
-      }
-
-      if (this.isICCServiceAvailable("CBMI")) {
-        this.getCBMI();
-      } else {
-        this.cellBroadcastConfigs.CBMI = null;
-      }
-      if (this.isICCServiceAvailable("CBMIR")) {
-        this.getCBMIR();
-      } else {
-        this.cellBroadcastConfigs.CBMIR = null;
-      }
-      this._mergeAllCellBroadcastConfigs();
-    }
-
-    // ICC_EF_UST has the same value with ICC_EF_SST.
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_SST,
-      pathId:    this._getPathIdForICCRecord(ICC_EF_SST),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_TRANSPARENT,
-      callback:  callback,
-    });
-  },
-
-  /**
-   * Read EFcbmi (Cell Broadcast Message Identifier selection)
-   *
-   * @see 3GPP TS 31.102 v110.02.0 section 4.2.14 EFcbmi
-   */
-  getCBMI: function getCBMI() {
-    function callback() {
-      let strLength = Buf.readUint32();
-
-      // Each Message Identifier takes two octets and each octet is encoded
-      // into two chars.
-      let numIds = strLength / 4, list = null;
-      if (numIds) {
-        list = [];
-        for (let i = 0, id; i < numIds; i++) {
-          id = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
-          // `Unused entries shall be set to 'FF FF'.`
-          if (id != 0xFFFF) {
-            list.push(id);
-            list.push(id + 1);
-          }
-        }
-      }
-      if (DEBUG) {
-        debug("CBMI: " + JSON.stringify(list));
-      }
-
-      Buf.readStringDelimiter(strLength);
-
-      this.cellBroadcastConfigs.CBMI = list;
-      this._mergeAllCellBroadcastConfigs();
-    }
-
-    function onerror() {
-      this.cellBroadcastConfigs.CBMI = null;
-      this._mergeAllCellBroadcastConfigs();
-    }
-
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_CBMI,
-      pathId:    this._getPathIdForICCRecord(ICC_EF_CBMI),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_TRANSPARENT,
-      callback:  callback,
-      onerror:   onerror
-    });
-  },
-
-  /**
-   * Read EFcbmir (Cell Broadcast Message Identifier Range selection)
-   *
-   * @see 3GPP TS 31.102 v110.02.0 section 4.2.22 EFcbmir
-   */
-  getCBMIR: function getCBMIR() {
-    function callback() {
-      let strLength = Buf.readUint32();
-
-      // Each Message Identifier range takes four octets and each octet is
-      // encoded into two chars.
-      let numIds = strLength / 8, list = null;
-      if (numIds) {
-        list = [];
-        for (let i = 0, from, to; i < numIds; i++) {
-          // `Bytes one and two of each range identifier equal the lower value
-          // of a cell broadcast range, bytes three and four equal the upper
-          // value of a cell broadcast range.`
-          from = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
-          to = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
-          // `Unused entries shall be set to 'FF FF'.`
-          if ((from != 0xFFFF) && (to != 0xFFFF)) {
-            list.push(from);
-            list.push(to + 1);
-          }
-        }
-      }
-      if (DEBUG) {
-        debug("CBMIR: " + JSON.stringify(list));
-      }
-
-      Buf.readStringDelimiter(strLength);
-
-      this.cellBroadcastConfigs.CBMIR = list;
-      this._mergeAllCellBroadcastConfigs();
-    }
-
-    function onerror() {
-      this.cellBroadcastConfigs.CBMIR = null;
-      this._mergeAllCellBroadcastConfigs();
-    }
-
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_CBMIR,
-      pathId:    this._getPathIdForICCRecord(ICC_EF_CBMIR),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_TRANSPARENT,
-      callback:  callback,
-      onerror:   onerror
-    });
-  },
-
-  /**
-   *  Helper to parse Dialling number from TS 131.102
-   *
-   *  @param options
-   *         The 'options' object passed from RIL.iccIO
-   *  @param addCallback
-   *         The function should be invoked when the ICC record is processed 
-   *         succesfully.
-   *  @param finishCallback
-   *         The function should be invoked when the final ICC record is 
-   *         processed.
-   *
-   */
-  parseDiallingNumber: function parseDiallingNumber(options,
-                                                    addCallback,
-                                                    finishCallback) {
-    let ffLen; // The length of trailing 0xff to be read.
-    let length = Buf.readUint32();
-
-    let alphaLen = options.recordSize - MSISDN_FOOTER_SIZE_BYTES;
-    let alphaId = GsmPDUHelper.readAlphaIdentifier(alphaLen);
-
-    let numLen = GsmPDUHelper.readHexOctet();
-    if (numLen != 0xff) {
-      if (numLen > MSISDN_MAX_NUMBER_SIZE_BYTES) {
-        debug("invalid length of BCD number/SSC contents - " + numLen);
-        return;
-      }
-
-      if (addCallback) {
-        addCallback.call(this, {alphaId: alphaId,
-                                number: GsmPDUHelper.readDiallingNumber(numLen)});
-      }
-
-      ffLen = length / 2 - alphaLen - numLen - 1; // Minus 1 for the numLen field.
-    } else {
-      ffLen = MSISDN_FOOTER_SIZE_BYTES - 1; // Minus 1 for the numLen field.
-    }
-
-    // Consumes the remaining 0xff
-    for (let i = 0; i < ffLen; i++) {
-      GsmPDUHelper.readHexOctet();
-    }
-    
-    Buf.readStringDelimiter(length);
-    
-    if (options.loadAll &&
-        options.p1 < options.totalRecords) {
-      options.p1++;
-      this.iccIO(options);
-    } else {
-      if (finishCallback) {
-        finishCallback.call(this);
-      }
-    }
-  },
-  
-  /**
-   *  Get ICC FDN.
-   *
-   *  @paran requestId
-   *         Request id from RadioInterfaceLayer.
-   */
-  getFDN: function getFDN(options) {
-    function callback(options) {
-      function add(contact) {
-        this.iccInfo.fdn.push(contact);
-      };
-      function finish() {
-        if (DEBUG) {
-          for (let i = 0; i < this.iccInfo.fdn.length; i++) {
-            debug("FDN[" + i + "] alphaId = " + this.iccInfo.fdn[i].alphaId +
-                                " number = " + this.iccInfo.fdn[i].number);
-          }
-        }
-        delete options.callback;
-        delete options.onerror;
-        options.rilMessageType = "icccontacts";
-        options.contacts = this.iccInfo.fdn;
-        this.sendDOMMessage(options);
-      };
-      this.parseDiallingNumber(options, add, finish);
-    }
-
-    this.iccInfo.fdn = [];
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_FDN,
-      pathId:    this._getPathIdForICCRecord(ICC_EF_FDN),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_LINEAR_FIXED,
-      callback:  callback,
-      loadAll:   true,
-      requestId: options.requestId
-    });
-  },
-
-  /**
-   *  Get ICC ADN.
-   *
-   *  @param fileId
-   *         EF id of the ADN.
-   *  @paran requestId
-   *         Request id from RadioInterfaceLayer.
-   */
-  getADN: function getADN(options) {
-    function callback(options) {
-      function add(contact) {
-        this.iccInfo.adn.push(contact);
-      };
-
-      function finish() {
-        if (DEBUG) {
-          for (let i = 0; i < this.iccInfo.adn.length; i++) {
-            debug("ADN[" + i + "] alphaId = " + this.iccInfo.adn[i].alphaId +
-                                " number  = " + this.iccInfo.adn[i].number);
-          }
-        }
-        // To prevent DataCloneError when sending parcels,
-        // We need to delete those properties which are not
-        // 'Structured Clone Data',
-        // in this case, those callback functions.
-        delete options.callback;
-        delete options.onerror;
-        options.rilMessageType = "icccontacts";
-        options.contacts = this.iccInfo.adn;
-        this.sendDOMMessage(options);
-      };
-      this.parseDiallingNumber(options, add, finish);
-    }
-
-    function error(options) {
-      delete options.callback;
-      delete options.onerror;
-      options.rilMessageType = "icccontacts";
-      options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
-      this.sendDOMMessage(options);
-    }
-
-    this.iccInfo.adn = [];
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    options.fileId,
-      pathId:    this._getPathIdForICCRecord(options.fileId),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_LINEAR_FIXED,
-      callback:  callback,
-      onerror:   error,
-      loadAll:   true,
-      requestId: options.requestId,
-    });
-  },
-
-   /**
-   * Get ICC MBDN. (Mailbox Dialling Number)
-   *
-   * @see TS 131.102, clause 4.2.60
-   */
-  getMBDN: function getMBDN() {
-    function callback(options) {
-      let parseCallback = function parseCallback(contact) {
-        if (DEBUG) {
-          debug("MBDN, alphaId="+contact.alphaId+" number="+contact.number);
-        }
-        if (this.iccInfo.mbdn != contact.number) {
-          this.iccInfo.mbdn = contact.number;
-          contact.rilMessageType = "iccmbdn";
-          this.sendDOMMessage(contact);
-        }
-      };
-
-      this.parseDiallingNumber(options, parseCallback);
-    }
-
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_MBDN,
-      pathId:    this._getPathIdForICCRecord(ICC_EF_MBDN),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_LINEAR_FIXED,
-      callback:  callback,
-    });
-  },
-
-  decodeSimTlvs: function decodeSimTlvs(tlvsLen) {
-    let index = 0;
-    let tlvs = [];
-    while (index < tlvsLen) {
-      let simTlv = {
-        tag : GsmPDUHelper.readHexOctet(),
-        length : GsmPDUHelper.readHexOctet(),
-      };
-      simTlv.value = GsmPDUHelper.readHexOctetArray(simTlv.length)
-      tlvs.push(simTlv);
-      index += simTlv.length + 2 /* The length of 'tag' and 'length' field */;
-    }
-    return tlvs;
-  },
-
-  _searchForIccUsimTag: function _searchForIccUsimTag(tlvs, tag) {
-    for (let i = 0; i < tlvs.length; i++) {
-      if (tlvs[i].tag == tag) {
-        return tlvs[i];
-      }
-    }
-    return null;
-  },
-
-  /**
-   *  Read the list of PLMN (Public Land Mobile Network) entries
-   *  We cannot directly rely on readSwappedNibbleBcdToString(),
-   *  since it will no correctly handle some corner-cases that are
-   *  not a problem in our case (0xFF 0xFF 0xFF).
-   *
-   *  @param length The number of PLMN records.
-   *  @return An array of string corresponding to the PLMNs.
-   */
-  readPLMNEntries: function readPLMNEntries(length) {
-    let plmnList = [];
-    // each PLMN entry has 3 byte
-    debug("readPLMNEntries: PLMN entries length = " + length);
-    let index = 0;
-    while (index < length) {
-      // Unused entries will be 0xFFFFFF, according to EF_SPDI
-      // specs (TS 131 102, section 4.2.66)
-      try {
-        let plmn = [GsmPDUHelper.readHexOctet(),
-                    GsmPDUHelper.readHexOctet(),
-                    GsmPDUHelper.readHexOctet()];
-        if (DEBUG) debug("readPLMNEntries: Reading PLMN entry: [" + index +
-                         "]: '" + plmn + "'");
-        if (plmn[0] != 0xFF &&
-            plmn[1] != 0xFF &&
-            plmn[2] != 0xFF) {
-          let semiOctets = [];
-          for (let idx = 0; idx < plmn.length; idx++) {
-            semiOctets.push((plmn[idx] & 0xF0) >> 4);
-            semiOctets.push(plmn[idx] & 0x0F);
-          }
-
-          // According to TS 24.301, 9.9.3.12, the semi octets is arranged
-          // in format:
-          // Byte 1: MCC[2] | MCC[1]
-          // Byte 2: MNC[3] | MCC[3]
-          // Byte 3: MNC[2] | MNC[1]
-          // Therefore, we need to rearrage them.
-          let reformat = [semiOctets[1], semiOctets[0], semiOctets[3],
-                          semiOctets[5], semiOctets[4], semiOctets[2]];
-          let buf = "";
-          let plmnEntry = {};
-          for (let i = 0; i < reformat.length; i++) {
-            if (reformat[i] != 0xF) {
-              buf += GsmPDUHelper.semiOctetToBcdChar(reformat[i]);
-            }
-            if (i === 2) {
-              // 0-2: MCC
-              plmnEntry.mcc = parseInt(buf);
-              buf = "";
-            } else if (i === 5) {
-              // 3-5: MNC
-              plmnEntry.mnc = parseInt(buf);
-            }
-          }
-          if (DEBUG) debug("readPLMNEntries: PLMN = " + plmnEntry.mcc + ", " + plmnEntry.mnc);
-          plmnList.push(plmnEntry);
-        }
-      } catch (e) {
-        if (DEBUG) debug("readPLMNEntries: PLMN entry " + index + " is invalid.");
-        break;
-      }
-      index ++;
-    }
-    return plmnList;
-  },
-
-  /**
    * Get UICC Phonebook.
    *
    * @params contactType
    *         "ADN" or "FDN".
    */
   getICCContacts: function getICCContacts(options) {
     if (!this.appType) {
       options.rilMessageType = "icccontacts";
@@ -2368,76 +1318,30 @@ let RIL = {
     }
 
     let type = options.contactType;
     switch (type) {
       case "ADN":
         switch (this.appType) {
           case CARD_APPTYPE_SIM:
             options.fileId = ICC_EF_ADN;
-            this.getADN(options);
+            ICCRecordHelper.getADN(options);
             break;
           case CARD_APPTYPE_USIM:
-            this.getPBR(options);
+            ICCRecordHelper.getPBR(options);
             break;
         }
         break;
       case "FDN":
-        this.getFDN(options);
+        ICCRecordHelper.getFDN(options);
         break;
     }
   },
 
   /**
-   * Get USIM Phonebook.
-   *
-   * @params requestId
-   *         Request id from RadioInterfaceLayer.
-   */
-  getPBR: function getPBR(options) {
-    function callback(options) {
-      let bufLen = Buf.readUint32();
-
-      let tag = GsmPDUHelper.readHexOctet();
-      let length = GsmPDUHelper.readHexOctet();
-      let value = this.decodeSimTlvs(length);
-
-      let adn = this._searchForIccUsimTag(value, ICC_USIM_EFADN_TAG);
-      let adnEfid = (adn.value[0] << 8) | adn.value[1];
-      this.getADN({fileId: adnEfid,
-                   requestId: options.requestId});
-
-      Buf.readStringDelimiter(bufLen);
-    }
-
-    function error(options) {
-      delete options.callback;
-      delete options.onerror;
-      options.rilMessageType = "icccontacts";
-      options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
-      this.sendDOMMessage(options);
-    }
-
-    this.iccIO({
-      command:   ICC_COMMAND_GET_RESPONSE,
-      fileId:    ICC_EF_PBR,
-      pathId:    this._getPathIdForICCRecord(ICC_EF_PBR),
-      p1:        0, // For GET_RESPONSE, p1 = 0
-      p2:        0, // For GET_RESPONSE, p2 = 0
-      p3:        GET_RESPONSE_EF_SIZE_BYTES,
-      data:      null,
-      pin2:      null,
-      type:      EF_TYPE_LINEAR_FIXED,
-      callback:  callback,
-      onerror:   error,
-      requestId: options.requestId,
-    });
-  },
-
-  /**
    * Request the phone's radio power to be switched on or off.
    *
    * @param on
    *        Boolean indicating the desired power state.
    */
   setRadioPower: function setRadioPower(options) {
     Buf.newParcel(REQUEST_RADIO_POWER);
     Buf.writeUint32(1);
@@ -3846,223 +2750,41 @@ let RIL = {
 
     // This was moved down from CARD_APPSTATE_READY
     this.requestNetworkInfo();
     this.getSignalStrength();
     if (newCardState == GECKO_CARDSTATE_READY) {
       // For type SIM, we need to check EF_phase first.
       // Other types of ICC we can send Terminal_Profile immediately.
       if (this.appType == CARD_APPTYPE_SIM) {
-        this.getICCPhase();
+        ICCRecordHelper.getICCPhase();
       } else {
         this.sendStkTerminalProfile(STK_SUPPORTED_TERMINAL_PROFILE);
       }
-      this.fetchICCRecords();
+      ICCRecordHelper.fetchICCRecords();
       this.reportStkServiceIsRunning();
     }
 
     this.cardState = newCardState;
     this.sendDOMMessage({rilMessageType: "cardstatechange",
                          cardState: this.cardState});
   },
 
-  /** 
-   * Helper function for getting the pathId for the specific ICC record
-   * depeding on which type of ICC card we are using.
-   * 
-   * @param fileId
-   *        File id.
-   * @return The pathId or null in case of an error or invalid input.
-   */
-  _getPathIdForICCRecord: function _getPathIdForICCRecord(fileId) {
-    let index = this.iccStatus.gsmUmtsSubscriptionAppIndex;
-    if (index == -1) {
-      return null;
-    }
-    let app = this.iccStatus.apps[index];
-    if (!app) {
-      return null;
-    }
-
-    // Here we handle only file ids that are common to RUIM, SIM, USIM
-    // and other types of ICC cards.
-    switch (fileId) {
-      case ICC_EF_ICCID:
-        return EF_PATH_MF_SIM;
-      case ICC_EF_ADN:
-        return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM;
-      case ICC_EF_PBR:
-        return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK;
-    }
-
-    switch (app.app_type) {
-      case CARD_APPTYPE_SIM:
-        switch (fileId) {
-          case ICC_EF_FDN:
-          case ICC_EF_MSISDN:
-            return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM;
-
-          case ICC_EF_AD:
-          case ICC_EF_MBDN:
-          case ICC_EF_PLMNsel:
-          case ICC_EF_SPN:
-          case ICC_EF_SPDI:
-          case ICC_EF_SST:
-          case ICC_EF_CBMI:
-          case ICC_EF_CBMIR:
-            return EF_PATH_MF_SIM + EF_PATH_DF_GSM;
-        }
-      case CARD_APPTYPE_USIM:
-        switch (fileId) {
-          case ICC_EF_AD:
-          case ICC_EF_FDN:
-          case ICC_EF_MBDN:
-          case ICC_EF_UST:
-          case ICC_EF_MSISDN:
-          case ICC_EF_SPN:
-          case ICC_EF_SPDI:
-          case ICC_EF_CBMI:
-          case ICC_EF_CBMIR:
-          case ICC_EF_OPL:
-          case ICC_EF_PNN:
-            return EF_PATH_MF_SIM + EF_PATH_ADF_USIM;
-
-          default:
-            // The file ids in USIM phone book entries are decided by the
-	    // card manufacturer. So if we don't match any of the cases
-	    // above and if its a USIM return the phone book path.
-            return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK;
-        }
-    }
-    return null;
-  },
-
    /**
    * Helper for processing responses of functions such as enterICC* and changeICC*.
    */
   _processEnterAndChangeICCResponses: function _processEnterAndChangeICCResponses(length, options) {
     options.success = options.rilRequestError == 0;
     if (!options.success) {
       options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     }
     options.retryCount = length ? Buf.readUint32List()[0] : -1;
     this.sendDOMMessage(options);
   },
 
-  /**
-   * Process a ICC_COMMAND_GET_RESPONSE type command for REQUEST_SIM_IO.
-   */
-  _processICCIOGetResponse: function _processICCIOGetResponse(options) {
-    let length = Buf.readUint32();
-
-    // The format is from TS 51.011, clause 9.2.1
-
-    // Skip RFU, data[0] data[1]
-    Buf.seekIncoming(2 * PDU_HEX_OCTET_SIZE);
-
-    // File size, data[2], data[3]
-    let fileSize = (GsmPDUHelper.readHexOctet() << 8) |
-                    GsmPDUHelper.readHexOctet();
-
-    // 2 bytes File id. data[4], data[5]
-    let fileId = (GsmPDUHelper.readHexOctet() << 8) |
-                  GsmPDUHelper.readHexOctet();
-    if (fileId != options.fileId) {
-      if (DEBUG) {
-        debug("Expected file ID " + options.fileId + " but read " + fileId);
-      }
-      return;
-    }
-
-    // Type of file, data[6]
-    let fileType = GsmPDUHelper.readHexOctet();
-    if (fileType != TYPE_EF) {
-      if (DEBUG) {
-        debug("Unexpected file type " + fileType);
-      }
-      return;
-    }
-
-    // Skip 1 byte RFU, data[7],
-    //      3 bytes Access conditions, data[8] data[9] data[10],
-    //      1 byte File status, data[11],
-    //      1 byte Length of the following data, data[12].
-    Buf.seekIncoming(((RESPONSE_DATA_STRUCTURE - RESPONSE_DATA_FILE_TYPE - 1) *
-        PDU_HEX_OCTET_SIZE));
-
-    // Read Structure of EF, data[13]
-    let efType = GsmPDUHelper.readHexOctet();
-    if (efType != options.type) {
-      if (DEBUG) {
-        debug("Expected EF type " + options.type + " but read " + efType);
-      }
-      return;
-    }
-
-    // Length of a record, data[14]
-    options.recordSize = GsmPDUHelper.readHexOctet();
-    options.totalRecords = fileSize / options.recordSize;
-
-    Buf.readStringDelimiter(length);
-
-    switch (options.type) {
-      case EF_TYPE_LINEAR_FIXED:
-        // Reuse the options object and update some properties.
-        options.command = ICC_COMMAND_READ_RECORD;
-        options.p1 = 1; // Record number, always use the 1st record
-        options.p2 = READ_RECORD_ABSOLUTE_MODE;
-        options.p3 = options.recordSize;
-        this.iccIO(options);
-        break;
-      case EF_TYPE_TRANSPARENT:
-        // Reuse the options object and update some properties.
-        options.command = ICC_COMMAND_READ_BINARY;
-        options.p3 = fileSize;
-        this.iccIO(options);
-        break;
-    }
-  },
-
-  /**
-   * Process a ICC_COMMAND_READ_RECORD type command for REQUEST_SIM_IO.
-   */
-  _processICCIOReadRecord: function _processICCIOReadRecord(options) {
-    if (options.callback) {
-      options.callback.call(this, options);
-    }
-  },
-
-  /**
-   * Process a ICC_COMMAND_READ_BINARY type command for REQUEST_SIM_IO.
-   */
-  _processICCIOReadBinary: function _processICCIOReadBinary(options) {
-    if (options.callback) {
-      options.callback.call(this);
-    }
-  },
-
-  /**
-   * Process ICC I/O response.
-   */
-  _processICCIO: function _processICCIO(options) {
-    switch (options.command) {
-      case ICC_COMMAND_GET_RESPONSE:
-        this._processICCIOGetResponse(options);
-        break;
-
-      case ICC_COMMAND_READ_RECORD:
-        this._processICCIOReadRecord(options);
-        break;
-
-      case ICC_COMMAND_READ_BINARY:
-        this._processICCIOReadBinary(options);
-        break;
-    } 
-  },
-
   // We combine all of the NETWORK_INFO_MESSAGE_TYPES into one "networkinfochange"
   // message to the RadioInterfaceLayer, so we can avoid sending multiple
   // VoiceInfoChanged events for both operator / voice_data_registration
   //
   // State management here is a little tricky. We need to know both:
   // 1. Whether or not a response was received for each of the
   //    NETWORK_INFO_MESSAGE_TYPES
   // 2. The outbound message that corresponds with that response -- but this
@@ -4269,18 +2991,18 @@ let RIL = {
 
       if (networkTuple) {
         try {
           this._processNetworkTuple(networkTuple, this.operator);
         } catch (e) {
           debug("Error processing operator tuple: " + e);
         }
       }
-      if (this.updateDisplayCondition()) {
-        this._handleICCInfoChange();
+      if (ICCUtilsHelper.updateDisplayCondition()) {
+        ICCUtilsHelper.handleICCInfoChange();
       }
       this._sendNetworkInfoMessage(NETWORK_INFO_OPERATOR, this.operator);
     }
   },
 
   /**
    * Helpers for processing call state and handle the active call.
    */
@@ -4756,17 +3478,17 @@ let RIL = {
       // 9.2.3.9
       return PDU_FCS_OK;
     }
 
     if (message.messageClass == GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]) {
       switch (message.epid) {
         case PDU_PID_ANSI_136_R_DATA:
         case PDU_PID_USIM_DATA_DOWNLOAD:
-          if (this.isICCServiceAvailable("DATA_DOWNLOAD_SMS_PP")) {
+          if (ICCUtilsHelper.isICCServiceAvailable("DATA_DOWNLOAD_SMS_PP")) {
             // `If the service "data download via SMS Point-to-Point" is
             // allocated and activated in the (U)SIM Service Table, ... then the
             // ME shall pass the message transparently to the UICC using the
             // ENVELOPE (SMS-PP DOWNLOAD).` ~ 3GPP TS 31.111 7.1.1.1
             this.dataDownloadViaSMSPP(message);
 
             // `the ME shall not display the message, or alert the user of a
             // short message waiting.` ~ 3GPP TS 31.111 7.1.1.1
@@ -5736,39 +4458,42 @@ RIL[REQUEST_SETUP_DATA_CALL] = function 
   }
   // Pass `options` along. That way we retain the APN and other info about
   // how the data call was set up.
   this[REQUEST_DATA_CALL_LIST](length, options);
 };
 RIL[REQUEST_SIM_IO] = function REQUEST_SIM_IO(length, options) {
   if (!length) {
     if (options.onerror) {
-      options.onerror.call(this, options);
+      options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
+      options.onerror(options);
     }
     return;
   }
 
   // Don't need to read rilRequestError since we can know error status from
   // sw1 and sw2.
-  let sw1 = Buf.readUint32();
-  let sw2 = Buf.readUint32();
-  if (sw1 != ICC_STATUS_NORMAL_ENDING) {
+  options.sw1 = Buf.readUint32();
+  options.sw2 = Buf.readUint32();
+  if (options.sw1 != ICC_STATUS_NORMAL_ENDING) {
     // See GSM11.11, TS 51.011 clause 9.4, and ISO 7816-4 for the error
     // description.
+    let msg = "ICC I/O Error EF id = " + options.fileId.toString(16) +
+              " command = " + options.command.toString(16) +
+              "(" + options.sw1.toString(16) + "/" + options.sw2.toString(16) + ")"
     if (DEBUG) {
-      debug("ICC I/O Error EF id = " + options.fileId.toString(16) +
-            " command = " + options.command.toString(16) +
-            "(" + sw1.toString(16) + "/" + sw2.toString(16) + ")");
+      debug(msg);
     }
     if (options.onerror) {
-      options.onerror.call(this, options);
+      options.errorMsg = msg;
+      options.onerror(options);
     }
     return;
   }
-  this._processICCIO(options);
+  ICCIOHelper.processICCIO(options);
 };
 RIL[REQUEST_SEND_USSD] = function REQUEST_SEND_USSD(length, options) {
   if (DEBUG) {
     debug("REQUEST_SEND_USSD " + JSON.stringify(options));
   }
   options.success = this._ussdSession = options.rilRequestError == 0;
   options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   this.sendDOMMessage(options);
@@ -7169,16 +5894,52 @@ let GsmPDUHelper = {
     if ((toa & 0xF0) == (PDU_TOA_INTERNATIONAL)) {
       addr = '+' + addr;
     }
 
     return addr;
   },
 
   /**
+   *  Read Alpha Id and Dialling number from TS 131.102
+   *
+   *  @param options
+   *         The 'options' object passed from RIL.iccIO
+   */
+  readAlphaIdDiallingNumber: function readAlphaIdDiallingNumber(options) {
+    let contact = null;
+    let ffLen; // The length of trailing 0xff to be read.
+    let length = Buf.readUint32();
+
+    let alphaLen = options.recordSize - MSISDN_FOOTER_SIZE_BYTES;
+    let alphaId = this.readAlphaIdentifier(alphaLen);
+
+    let numLen = this.readHexOctet();
+    if (numLen != 0xff) {
+      // +1 for TON/NPI
+      if (numLen > MSISDN_MAX_NUMBER_SIZE_BYTES + 1) {
+        throw new Error("invalid length of BCD number/SSC contents - " + numLen);
+      }
+
+      contact = {alphaId: alphaId,
+                 number: this.readDiallingNumber(numLen)};
+
+      ffLen = length / 2 - alphaLen - numLen - 1; // Minus 1 for the numLen field.
+    } else {
+      ffLen = MSISDN_FOOTER_SIZE_BYTES - 1; // Minus 1 for the numLen field.
+    }
+
+    // Consumes the remaining 0xff
+    Buf.seekIncoming(ffLen * PDU_HEX_OCTET_SIZE);
+    Buf.readStringDelimiter(length);
+
+    return contact;
+  },
+
+  /**
    * Read Alpha Identifier.
    *
    * @see TS 131.102
    *
    * @param numOctets
    *        Number of octets to be read.
    *
    * It uses either
@@ -8275,17 +7036,17 @@ let StkCommandParamsFactory = {
       case STK_REFRESH_NAA_INIT_AND_FILE_CHANGE:
         let ctlv = StkProactiveCmdHelper.searchForTag(
           COMPREHENSIONTLV_TAG_FILE_LIST, ctlvs);
         if (ctlv) {
           let list = ctlv.value.fileList;
           if (DEBUG) {
             debug("Refresh, list = " + list);
           }
-          RIL.fetchICCRecords();
+          ICCRecordHelper.fetchICCRecords();
         }
         break;
     }
     return null;
   },
 
   /**
    * Construct a param for Poll Interval.
@@ -9342,16 +8103,1176 @@ let BerTlvHelper = {
       length: length,
       value: ctlvs
     };
     return berTlv;
   }
 };
 
 /**
+ * ICC Helper for getting EF path.
+ */
+let ICCFileHelper = {
+  /**
+   * This function handles only EFs that are common to RUIM, SIM, USIM
+   * and other types of ICC cards.
+   */
+  getCommonEFPath: function getCommonEFPath(fileId) {
+    switch (fileId) {
+      case ICC_EF_ICCID:
+        return EF_PATH_MF_SIM;
+      case ICC_EF_ADN:
+        return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM;
+      case ICC_EF_PBR:
+        return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK;
+    }
+    return null;
+  },
+
+  /**
+   * This function handles EFs for SIM.
+   */
+  getSimEFPath: function getSimEFPath(fileId) {
+    switch (fileId) {
+      case ICC_EF_FDN:
+      case ICC_EF_MSISDN:
+        return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM;
+      case ICC_EF_AD:
+      case ICC_EF_MBDN:
+      case ICC_EF_PLMNsel:
+      case ICC_EF_SPN:
+      case ICC_EF_SPDI:
+      case ICC_EF_SST:
+      case ICC_EF_PHASE:
+      case ICC_EF_CBMI:
+      case ICC_EF_CBMIR:
+      case ICC_EF_OPL:
+      case ICC_EF_PNN:
+        return EF_PATH_MF_SIM + EF_PATH_DF_GSM;
+      default:
+        return null
+    }
+  },
+
+  /**
+   * This function handles EFs for USIM.
+   */
+  getUSimEFPath: function getUSimEFPath(fileId) {
+    switch (fileId) {
+      case ICC_EF_AD:
+      case ICC_EF_FDN:
+      case ICC_EF_MBDN:
+      case ICC_EF_UST:
+      case ICC_EF_MSISDN:
+      case ICC_EF_SPN:
+      case ICC_EF_SPDI:
+      case ICC_EF_CBMI:
+      case ICC_EF_CBMIR:
+      case ICC_EF_OPL:
+      case ICC_EF_PNN:
+        return EF_PATH_MF_SIM + EF_PATH_ADF_USIM;
+      default:
+        // The file ids in USIM phone book entries are decided by the
+        // card manufacturer. So if we don't match any of the cases
+        // above and if its a USIM return the phone book path.
+        return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK;
+    }
+  },
+
+  /**
+   * Helper function for getting the pathId for the specific ICC record
+   * depeding on which type of ICC card we are using.
+   *
+   * @param fileId
+   *        File id.
+   * @return The pathId or null in case of an error or invalid input.
+   */
+  getEFPath: function getEFPath(fileId) {
+    // TODO: Bug 726098, change to use cdmaSubscriptionAppIndex when in CDMA.
+    let index = RIL.iccStatus.gsmUmtsSubscriptionAppIndex;
+    if (index == -1) {
+      return null;
+    }
+    let app = RIL.iccStatus.apps[index];
+    if (!app) {
+      return null;
+    }
+
+    let path = this.getCommonEFPath(fileId);
+    if (path) {
+      return path;
+    }
+
+    switch (app.app_type) {
+      case CARD_APPTYPE_SIM:
+        return this.getSimEFPath(fileId);
+      case CARD_APPTYPE_USIM:
+        return this.getUSimEFPath(fileId);
+      default:
+        return null;
+    }
+  },
+};
+
+/**
+ * Helper for ICC IO functionalities.
+ */
+let ICCIOHelper = {
+  /**
+   * Load EF with type 'Linear Fixed'.
+   *
+   * @param fileId
+   *        The file to operate on, one of the ICC_EF_* constants.
+   * @param recordNumber [optional]
+   *        The number of the record shall be loaded.
+   * @param callback [optional]
+   *        The callback function shall be called when the record(s) is read.
+   * @param this [optional]
+   *        The 'this' object when the callback is called.
+   * @param onerror [optional]
+   *        The callback function shall be called when failure.
+   */
+  loadLinearFixedEF: function loadLinearFixedEF(options) {
+    options.type = EF_TYPE_LINEAR_FIXED;
+    let cb = options.callback;
+    options.callback = function callback(options) {
+      options.callback = cb;
+      options.command = ICC_COMMAND_READ_RECORD;
+      options.p1 = options.recordNumber || 1; // Record number
+      options.p2 = READ_RECORD_ABSOLUTE_MODE;
+      options.p3 = options.recordSize;
+      RIL.iccIO(options);
+    }.bind(this);
+    this.getResponse(options);
+  },
+
+  /**
+   * Load next record from current record Id.
+   */
+  loadNextRecord: function loadNextRecord(options) {
+    options.p1++;
+    RIL.iccIO(options);
+  },
+
+  /**
+   * Load EF with type 'Transparent'.
+   *
+   * @param fileId
+   *        The file to operate on, one of the ICC_EF_* constants.
+   * @param callback [optional]
+   *        The callback function shall be called when the record(s) is read.
+   * @param onerror [optional]
+   *        The callback function shall be called when failure.
+   */
+  loadTransparentEF: function loadTransparentEF(options) {
+    options.type = EF_TYPE_TRANSPARENT;
+    let cb = options.callback;
+    options.callback = function callback(options) {
+      options.callback = cb;
+      options.command = ICC_COMMAND_READ_BINARY;
+      options.p3 = options.fileSize;
+      RIL.iccIO(options);
+    }.bind(this);
+    this.getResponse(options);
+  },
+
+  /**
+   * Use ICC_COMMAND_GET_RESPONSE to query the EF.
+   *
+   * @param fileId
+   *        The file to operate on, one of the ICC_EF_* constants.
+   */
+  getResponse: function getResponse(options) {
+    options.command = ICC_COMMAND_GET_RESPONSE;
+    options.pathId = ICCFileHelper.getEFPath(options.fileId);
+    if (!options.pathId) {
+      throw new Error("Unknown pathId for " + options.fileId.toString(16));
+    }
+    options.p1 = 0; // For GET_RESPONSE, p1 = 0
+    options.p2 = 0; // For GET_RESPONSE, p2 = 0
+    options.p3 = GET_RESPONSE_EF_SIZE_BYTES;
+    RIL.iccIO(options);
+  },
+
+  /**
+   * Process ICC I/O response.
+   */
+  processICCIO: function processICCIO(options) {
+    let func = this[options.command];
+    func.call(this, options);
+  },
+
+  /**
+   * Process a ICC_COMMAND_GET_RESPONSE type command for REQUEST_SIM_IO.
+   */
+  processICCIOGetResponse: function processICCIOGetResponse(options) {
+    let length = Buf.readUint32();
+
+    // The format is from TS 51.011, clause 9.2.1
+
+    // Skip RFU, data[0] data[1]
+    Buf.seekIncoming(2 * PDU_HEX_OCTET_SIZE);
+
+    // File size, data[2], data[3]
+    options.fileSize = (GsmPDUHelper.readHexOctet() << 8) |
+                        GsmPDUHelper.readHexOctet();
+
+    // 2 bytes File id. data[4], data[5]
+    let fileId = (GsmPDUHelper.readHexOctet() << 8) |
+                  GsmPDUHelper.readHexOctet();
+    if (fileId != options.fileId) {
+      throw new Error("Expected file ID " + options.fileId.toString(16) +
+                      " but read " + fileId.toString(16));
+    }
+
+    // Type of file, data[6]
+    let fileType = GsmPDUHelper.readHexOctet();
+    if (fileType != TYPE_EF) {
+      throw new Error("Unexpected file type " + fileType);
+    }
+
+    // Skip 1 byte RFU, data[7],
+    //      3 bytes Access conditions, data[8] data[9] data[10],
+    //      1 byte File status, data[11],
+    //      1 byte Length of the following data, data[12].
+    Buf.seekIncoming(((RESPONSE_DATA_STRUCTURE - RESPONSE_DATA_FILE_TYPE - 1) *
+        PDU_HEX_OCTET_SIZE));
+
+    // Read Structure of EF, data[13]
+    let efType = GsmPDUHelper.readHexOctet();
+    if (efType != options.type) {
+      throw new Error("Expected EF type " + options.type + " but read " + efType);
+    }
+
+    // Length of a record, data[14]
+    options.recordSize = GsmPDUHelper.readHexOctet();
+    options.totalRecords = options.fileSize / options.recordSize;
+
+    Buf.readStringDelimiter(length);
+
+    if (options.callback) {
+      options.callback(options);
+    }
+  },
+
+  /**
+   * Process a ICC_COMMAND_READ_RECORD type command for REQUEST_SIM_IO.
+   */
+  processICCIOReadRecord: function processICCIOReadRecord(options) {
+    if (options.callback) {
+      options.callback(options);
+    }
+  },
+
+  /**
+   * Process a ICC_COMMAND_READ_BINARY type command for REQUEST_SIM_IO.
+   */
+  processICCIOReadBinary: function processICCIOReadBinary(options) {
+    if (options.callback) {
+      options.callback(options);
+    }
+  },
+};
+ICCIOHelper[ICC_COMMAND_SEEK] = null;
+ICCIOHelper[ICC_COMMAND_READ_BINARY] = function ICC_COMMAND_READ_BINARY(options) {
+  this.processICCIOReadBinary(options);
+};
+ICCIOHelper[ICC_COMMAND_READ_RECORD] = function ICC_COMMAND_READ_RECORD(options) {
+  this.processICCIOReadRecord(options);
+};
+ICCIOHelper[ICC_COMMAND_GET_RESPONSE] = function ICC_COMMAND_GET_RESPONSE(options) {
+  this.processICCIOGetResponse(options);
+};
+ICCIOHelper[ICC_COMMAND_UPDATE_BINARY] = null;
+ICCIOHelper[ICC_COMMAND_UPDATE_RECORD] = null;
+
+/**
+ * Helper for ICC records.
+ */
+let ICCRecordHelper = {
+  /**
+   * Fetch ICC records.
+   */
+  fetchICCRecords: function fetchICCRecords() {
+    this.getICCID();
+    RIL.getIMSI();
+    this.getMSISDN();
+    this.getAD();
+    this.getSST();
+    this.getMBDN();
+  },
+
+  /**
+   * Get EF_phase.
+   * This EF is only available in SIM.
+   */
+  getICCPhase: function getICCPhase() {
+    function callback() {
+      let length = Buf.readUint32();
+
+      let phase = GsmPDUHelper.readHexOctet();
+      // If EF_phase is coded '03' or greater, an ME supporting STK shall
+      // perform the PROFILE DOWNLOAD procedure.
+      if (phase >= ICC_PHASE_2_PROFILE_DOWNLOAD_REQUIRED) {
+        RIL.sendStkTerminalProfile(STK_SUPPORTED_TERMINAL_PROFILE);
+      }
+
+      Buf.readStringDelimiter(length);
+    }
+
+    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_PHASE,
+                                   callback: callback.bind(this)});
+  },
+
+  /**
+   * Read the ICCID.
+   */
+  getICCID: function getICCID() {
+    function callback() {
+      let length = Buf.readUint32();
+      RIL.iccInfo.iccid = GsmPDUHelper.readSwappedNibbleBcdString(length / 2);
+      Buf.readStringDelimiter(length);
+
+      if (DEBUG) debug("ICCID: " + RIL.iccInfo.iccid);
+      if (RIL.iccInfo.iccid) {
+        ICCUtilsHelper.handleICCInfoChange();
+      }
+    }
+
+    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_ICCID,
+                                   callback: callback.bind(this)});
+  },
+
+  /**
+   * Read the MSISDN from the ICC.
+   */
+  getMSISDN: function getMSISDN() {
+    function callback(options) {
+      let contact = GsmPDUHelper.readAlphaIdDiallingNumber(options);
+      if (!contact || RIL.iccInfo.msisdn === contact.number) {
+        return;
+      }
+      RIL.iccInfo.msisdn = contact.number;
+      if (DEBUG) debug("MSISDN: " + RIL.iccInfo.msisdn);
+      ICCUtilsHelper.handleICCInfoChange();
+    }
+
+    ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_MSISDN,
+                                   callback: callback.bind(this)});
+  },
+
+  /**
+   * Read the AD (Administrative Data) from the ICC.
+   */
+  getAD: function getAD() {
+    function callback() {
+      let length = Buf.readUint32();
+      // Each octet is encoded into two chars.
+      let len = length / 2;
+      RIL.iccInfo.ad = GsmPDUHelper.readHexOctetArray(len);
+      Buf.readStringDelimiter(length);
+
+      if (DEBUG) {
+        let str = "";
+        for (let i = 0; i < RIL.iccInfo.ad.length; i++) {
+          str += RIL.iccInfo.ad[i] + ", ";
+        }
+        debug("AD: " + str);
+      }
+
+      if (RIL.iccInfo.imsi) {
+        // MCC is the first 3 digits of IMSI.
+        RIL.iccInfo.mcc = parseInt(RIL.iccInfo.imsi.substr(0,3));
+        // The 4th byte of the response is the length of MNC.
+        RIL.iccInfo.mnc = parseInt(RIL.iccInfo.imsi.substr(3, RIL.iccInfo.ad[3]));
+        if (DEBUG) debug("MCC: " + RIL.iccInfo.mcc + " MNC: " + RIL.iccInfo.mnc);
+        ICCUtilsHelper.handleICCInfoChange();
+      }
+    }
+
+    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_AD,
+                                   callback: callback.bind(this)});
+  },
+
+  /**
+   * Read the SPN (Service Provider Name) from the ICC.
+   */
+  getSPN: function getSPN() {
+    function callback() {
+      let length = Buf.readUint32();
+      // Each octet is encoded into two chars.
+      // Minus 1 because the first octet is used to store display condition.
+      let len = (length / 2) - 1;
+      let spnDisplayCondition = GsmPDUHelper.readHexOctet();
+      let spn = GsmPDUHelper.readAlphaIdentifier(len);
+      Buf.readStringDelimiter(length);
+
+      if (DEBUG) {
+        debug("SPN: spn = " + spn +
+              ", spnDisplayCondition = " + spnDisplayCondition);
+      }
+
+      RIL.iccInfoPrivate.SPN = {
+        spn : spn,
+        spnDisplayCondition : spnDisplayCondition,
+      };
+      RIL.iccInfo.spn = spn;
+      ICCUtilsHelper.updateDisplayCondition();
+      ICCUtilsHelper.handleICCInfoChange();
+    }
+
+    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_SPN,
+                                   callback: callback.bind(this)});
+  },
+
+  /**
+   * Read the (U)SIM Service Table from the ICC.
+   */
+  getSST: function getSST() {
+    function callback() {
+      let length = Buf.readUint32();
+      // Each octet is encoded into two chars.
+      let len = length / 2;
+      RIL.iccInfo.sst = GsmPDUHelper.readHexOctetArray(len);
+      Buf.readStringDelimiter(length);
+
+      if (DEBUG) {
+        let str = "";
+        for (let i = 0; i < RIL.iccInfo.sst.length; i++) {
+          str += RIL.iccInfo.sst[i] + ", ";
+        }
+        debug("SST: " + str);
+      }
+
+      // Fetch SPN and PLMN list, if some of them are available.
+      if (ICCUtilsHelper.isICCServiceAvailable("SPN")) {
+        if (DEBUG) debug("SPN: SPN is available");
+        this.getSPN();
+      } else {
+        if (DEBUG) debug("SPN: SPN service is not available");
+      }
+
+      if (ICCUtilsHelper.isICCServiceAvailable("SPDI")) {
+        if (DEBUG) debug("SPDI: SPDI available.");
+        this.getSPDI();
+      } else {
+        if (DEBUG) debug("SPDI: SPDI service is not available");
+      }
+
+      if (ICCUtilsHelper.isICCServiceAvailable("PNN")) {
+        if (DEBUG) debug("PNN: PNN is available");
+        this.getPNN();
+      } else {
+        if (DEBUG) debug("PNN: PNN is not available");
+      }
+
+      if (ICCUtilsHelper.isICCServiceAvailable("OPL")) {
+        if (DEBUG) debug("OPL: OPL is available");
+        this.getOPL();
+      } else {
+        if (DEBUG) debug("OPL: OPL is not available");
+      }
+
+      if (ICCUtilsHelper.isICCServiceAvailable("CBMI")) {
+        this.getCBMI();
+      } else {
+        RIL.cellBroadcastConfigs.CBMI = null;
+      }
+      if (ICCUtilsHelper.isICCServiceAvailable("CBMIR")) {
+        this.getCBMIR();
+      } else {
+        RIL.cellBroadcastConfigs.CBMIR = null;
+      }
+      RIL._mergeAllCellBroadcastConfigs();
+    }
+
+    // ICC_EF_UST has the same value with ICC_EF_SST.
+    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_SST,
+                                   callback: callback.bind(this)});
+  },
+
+  /**
+   *  Get ICC FDN.
+   *
+   *  @param requestId
+   *         Request id from RadioInterfaceLayer.
+   */
+  getFDN: function getFDN(options) {
+    function callback(options) {
+      let contact = GsmPDUHelper.readAlphaIdDiallingNumber(options);
+      if (contact) {
+        RIL.iccInfo.fdn.push(contact);
+      }
+
+      if (options.p1 < options.totalRecords) {
+        ICCIOHelper.loadNextRecord(options);
+      } else {
+        if (DEBUG) {
+          for (let i = 0; i < RIL.iccInfo.fdn.length; i++) {
+            debug("FDN[" + i + "] alphaId = " + RIL.iccInfo.fdn[i].alphaId +
+                                " number  = " + RIL.iccInfo.fdn[i].number);
+          }
+        }
+        // To prevent DataCloneError when sending parcels, we need to delete
+        // those properties which are not 'Structured Clone Data', in this case,
+        // those callback functions.
+        delete options.callback;
+        delete options.onerror;
+        options.rilMessageType = "icccontacts";
+        options.contacts = RIL.iccInfo.fdn;
+        RIL.sendDOMMessage(options);
+      }
+    }
+
+    RIL.iccInfo.fdn = [];
+    options.fileId = ICC_EF_FDN;
+    options.callback = callback.bind(this);
+    ICCIOHelper.loadLinearFixedEF(options);
+  },
+
+  /**
+   *  Get ICC ADN.
+   *
+   *  @param fileId
+   *         EF id of the ADN.
+   *  @param requestId
+   *         Request id from RadioInterfaceLayer.
+   */
+  getADN: function getADN(options) {
+    function callback(options) {
+      let contact = GsmPDUHelper.readAlphaIdDiallingNumber(options);
+      if (contact) {
+        RIL.iccInfo.adn.push(contact);
+      }
+
+      if (options.p1 < options.totalRecords) {
+        ICCIOHelper.loadNextRecord(options);
+      } else {
+        if (DEBUG) {
+          for (let i = 0; i < RIL.iccInfo.adn.length; i++) {
+            debug("ADN[" + i + "] " + JSON.stringify(RIL.iccInfo.adn[i]));
+          }
+        }
+        // To prevent DataCloneError when sending parcels, we need to delete
+        // those properties which are not 'Structured Clone Data', in this case,
+        // those callback functions.
+        delete options.callback;
+        delete options.onerror;
+        options.rilMessageType = "icccontacts";
+        options.contacts = RIL.iccInfo.adn;
+        RIL.sendDOMMessage(options);
+      }
+    }
+
+    function error(options) {
+      delete options.callback;
+      delete options.onerror;
+      options.rilMessageType = "icccontacts";
+      RIL.sendDOMMessage(options);
+    }
+
+    RIL.iccInfo.adn = [];
+    options.callback = callback.bind(this);
+    options.onerror = error.bind(this);
+    ICCIOHelper.loadLinearFixedEF(options);
+  },
+
+  /**
+   * Get ICC MBDN. (Mailbox Dialling Number)
+   *
+   * @see TS 131.102, clause 4.2.60
+   */
+  getMBDN: function getMBDN() {
+    function callback(options) {
+      let contact = GsmPDUHelper.readAlphaIdDiallingNumber(options);
+      if (!contact || RIL.iccInfo.mbdn === contact.number){
+        return;
+      }
+      RIL.iccInfo.mbdn = contact.number;
+      if (DEBUG) {
+        debug("MBDN, alphaId="+contact.alphaId+" number="+contact.number);
+      }
+      contact.rilMessageType = "iccmbdn";
+      RIL.sendDOMMessage(contact);
+    }
+
+    ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_MBDN,
+                                   callback: callback.bind(this)});
+  },
+
+  /**
+   * Get USIM Phonebook.
+   *
+   * @param requestId
+   *         Request id from RadioInterfaceLayer.
+   */
+  getPBR: function getPBR(options) {
+    function callback(options) {
+      let bufLen = Buf.readUint32();
+
+      let tag = GsmPDUHelper.readHexOctet();
+      let length = GsmPDUHelper.readHexOctet();
+      let value = ICCUtilsHelper.decodeSimTlvs(length);
+
+      let adn = ICCUtilsHelper.searchForIccUsimTag(value, ICC_USIM_EFADN_TAG);
+      options.fileId = (adn.value[0] << 8) | adn.value[1];
+      Buf.readStringDelimiter(bufLen);
+
+      this.getADN(options);
+    }
+
+    function error(options) {
+      delete options.callback;
+      delete options.onerror;
+      options.rilMessageType = "icccontacts";
+      RIL.sendDOMMessage(options);
+    }
+
+    options.fileId = ICC_EF_PBR;
+    options.callback = callback.bind(this);
+    options.onerror = error.bind(this);
+    ICCIOHelper.loadLinearFixedEF(options);
+  },
+
+  /**
+   * Read the PLMNsel (Public Land Mobile Network) from the ICC.
+   *
+   * See ETSI TS 100.977 section 10.3.4 EF_PLMNsel
+   */
+  getPLMNSelector: function getPLMNSelector() {
+    function callback() {
+      if (DEBUG) debug("PLMN Selector: Process PLMN Selector");
+
+      let length = Buf.readUint32();
+      RIL.iccInfoPrivate.PLMN = this.readPLMNEntries(length/3);
+      Buf.readStringDelimiter(length);
+
+      if (DEBUG) debug("PLMN Selector: " + JSON.stringify(RIL.iccInfoPrivate.PLMN));
+
+      if (RIL.updateDisplayCondition()) {
+        this.handleICCInfoChange();
+      }
+    }
+
+    // PLMN List is Service 7 in SIM, EF_PLMNsel
+    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_PLMNsel,
+                                   callback: callback.bind(this)});
+  },
+
+  /**
+   * Read the SPDI (Service Provider Display Information) from the ICC.
+   *
+   * See TS 131.102 section 4.2.66 for USIM and TS 51.011 section 10.3.50
+   * for SIM.
+   */
+  getSPDI: function getSPDI() {
+    function callback() {
+      let length = Buf.readUint32();
+      let readLen = 0;
+      let endLoop = false;
+      RIL.iccInfoPrivate.SPDI = null;
+      while ((readLen < length / 2) && !endLoop) {
+        let tlvTag = GsmPDUHelper.readHexOctet();
+        let tlvLen = GsmPDUHelper.readHexOctet();
+        readLen += 2; // For tag and length fields.
+        switch (tlvTag) {
+        case SPDI_TAG_SPDI:
+          // The value part itself is a TLV.
+          continue;
+        case SPDI_TAG_PLMN_LIST:
+          // This PLMN list is what we want.
+          RIL.iccInfoPrivate.SPDI = this.readPLMNEntries(tlvLen / 3);
+          readLen += tlvLen;
+          endLoop = true;
+          break;
+        default:
+          // We don't care about its content if its tag is not SPDI nor
+          // PLMN_LIST.
+          endLoop = true;
+          break;
+        }
+      }
+
+      // Consume unread octets.
+      Buf.seekIncoming((length / 2 - readLen) * PDU_HEX_OCTET_SIZE);
+      Buf.readStringDelimiter(length);
+
+      if (DEBUG) debug("SPDI: " + JSON.stringify(RIL.iccInfoPrivate.SPDI));
+      if (ICCUtilsHelper.updateDisplayCondition()) {
+        ICCUtilsHelper.handleICCInfoChange();
+      }
+    }
+
+    // PLMN List is Servive 51 in USIM, EF_SPDI
+    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_SPDI,
+                                   callback: callback.bind(this)});
+  },
+
+  /**
+   * Read EFcbmi (Cell Broadcast Message Identifier selection)
+   *
+   * @see 3GPP TS 31.102 v110.02.0 section 4.2.14 EFcbmi
+   */
+  getCBMI: function getCBMI() {
+    function callback() {
+      let strLength = Buf.readUint32();
+
+      // Each Message Identifier takes two octets and each octet is encoded
+      // into two chars.
+      let numIds = strLength / 4, list = null;
+      if (numIds) {
+        list = [];
+        for (let i = 0, id; i < numIds; i++) {
+          id = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
+          // `Unused entries shall be set to 'FF FF'.`
+          if (id != 0xFFFF) {
+            list.push(id);
+            list.push(id + 1);
+          }
+        }
+      }
+      if (DEBUG) {
+        debug("CBMI: " + JSON.stringify(list));
+      }
+
+      Buf.readStringDelimiter(strLength);
+
+      RIL.cellBroadcastConfigs.CBMI = list;
+      RIL._mergeAllCellBroadcastConfigs();
+    }
+
+    function onerror() {
+      RIL.cellBroadcastConfigs.CBMI = null;
+      RIL._mergeAllCellBroadcastConfigs();
+    }
+
+    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_CBMI,
+                                   callback: callback.bind(this),
+                                   onerror: onerror.bind(this)});
+  },
+
+  /**
+   * Read EFcbmir (Cell Broadcast Message Identifier Range selection)
+   *
+   * @see 3GPP TS 31.102 v110.02.0 section 4.2.22 EFcbmir
+   */
+  getCBMIR: function getCBMIR() {
+    function callback() {
+      let strLength = Buf.readUint32();
+
+      // Each Message Identifier range takes four octets and each octet is
+      // encoded into two chars.
+      let numIds = strLength / 8, list = null;
+      if (numIds) {
+        list = [];
+        for (let i = 0, from, to; i < numIds; i++) {
+          // `Bytes one and two of each range identifier equal the lower value
+          // of a cell broadcast range, bytes three and four equal the upper
+          // value of a cell broadcast range.`
+          from = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
+          to = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
+          // `Unused entries shall be set to 'FF FF'.`
+          if ((from != 0xFFFF) && (to != 0xFFFF)) {
+            list.push(from);
+            list.push(to + 1);
+          }
+        }
+      }
+      if (DEBUG) {
+        debug("CBMIR: " + JSON.stringify(list));
+      }
+
+      Buf.readStringDelimiter(strLength);
+
+      RIL.cellBroadcastConfigs.CBMIR = list;
+      RIL._mergeAllCellBroadcastConfigs();
+    }
+
+    function onerror() {
+      RIL.cellBroadcastConfigs.CBMIR = null;
+      RIL._mergeAllCellBroadcastConfigs();
+    }
+
+    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_CBMIR,
+                                   callback: callback.bind(this),
+                                   onerror: onerror.bind(this)});
+  },
+
+  /**
+   * Read OPL (Operator PLMN List) from USIM.
+   *
+   * See 3GPP TS 31.102 Sec. 4.2.59 for USIM
+   *     3GPP TS 51.011 Sec. 10.3.42 for SIM.
+   */
+  getOPL: function getOPL() {
+    let opl = [];
+    function callback(options) {
+      let len = Buf.readUint32();
+      // The first 7 bytes are LAI (for UMTS) and the format of LAI is defined
+      // in 3GPP TS 23.003, Sec 4.1
+      //    +-------------+---------+
+      //    | Octet 1 - 3 | MCC/MNC |
+      //    +-------------+---------+
+      //    | Octet 4 - 7 |   LAC   |
+      //    +-------------+---------+
+      let mccMnc = [GsmPDUHelper.readHexOctet(),
+                    GsmPDUHelper.readHexOctet(),
+                    GsmPDUHelper.readHexOctet()];
+      if (mccMnc[0] != 0xFF || mccMnc[1] != 0xFF || mccMnc[2] != 0xFF) {
+        let oplElement = {};
+        let semiOctets = [];
+        for (let i = 0; i < mccMnc.length; i++) {
+          semiOctets.push((mccMnc[i] & 0xf0) >> 4);
+          semiOctets.push(mccMnc[i] & 0x0f);
+        }
+        let reformat = [semiOctets[1], semiOctets[0], semiOctets[3],
+                        semiOctets[5], semiOctets[4], semiOctets[2]];
+        let buf = "";
+        for (let i = 0; i < reformat.length; i++) {
+          if (reformat[i] != 0xF) {
+            buf += GsmPDUHelper.semiOctetToBcdChar(reformat[i]);
+          }
+          if (i === 2) {
+            // 0-2: MCC
+            oplElement.mcc = parseInt(buf);
+            buf = "";
+          } else if (i === 5) {
+            // 3-5: MNC
+            oplElement.mnc = parseInt(buf);
+          }
+        }
+        // LAC/TAC
+        oplElement.lacTacStart =
+          (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
+        oplElement.lacTacEnd =
+          (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
+        // PLMN Network Name Record Identifier
+        oplElement.pnnRecordId = GsmPDUHelper.readHexOctet();
+        if (DEBUG) {
+          debug("OPL: [" + (opl.length + 1) + "]: " + JSON.stringify(oplElement));
+        }
+        opl.push(oplElement);
+      }
+      Buf.readStringDelimiter(len);
+      if (options.p1 < options.totalRecords) {
+        ICCIOHelper.loadNextRecord(options);
+      } else {
+        RIL.iccInfoPrivate.OPL = opl;
+      }
+    }
+
+    ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_OPL,
+                                   callback: callback.bind(this)});
+  },
+
+  /**
+   * Read PNN (PLMN Network Name) from USIM.
+   *
+   * See 3GPP TS 31.102 Sec. 4.2.58 for USIM
+   *     3GPP TS 51.011 Sec. 10.3.41 for SIM.
+   */
+  getPNN: function getPNN() {
+    let pnn = [];
+    function callback(options) {
+      let pnnElement = RIL.iccInfoPrivate.PNN = {};
+      let len = Buf.readUint32();
+      let readLen = 0;
+      while (len > readLen) {
+        let tlvTag = GsmPDUHelper.readHexOctet();
+        readLen = readLen + 2; // 1 Hex octet
+        if (tlvTag == 0xFF) {
+          // Unused byte
+          continue;
+        }
+        let tlvLen = GsmPDUHelper.readHexOctet();
+        let name;
+        switch (tlvTag) {
+        case PNN_IEI_FULL_NETWORK_NAME:
+          pnnElement.fullName = GsmPDUHelper.readNetworkName(tlvLen);
+          break;
+        case PNN_IEI_SHORT_NETWORK_NAME:
+          pnnElement.shortName = GsmPDUHelper.readNetworkName(tlvLen);
+          break;
+        default:
+          Buf.seekIncoming(PDU_HEX_OCTET_SIZE * tlvLen);
+        }
+        readLen += (tlvLen * 2 + 2);
+      }
+      if (DEBUG) {
+        debug("PNN: [" + (pnn.length + 1) + "]: " + JSON.stringify(pnnElement));
+      }
+      Buf.readStringDelimiter(len);
+      pnn.push(pnnElement);
+
+      if (options.p1 < options.totalRecords) {
+        ICCIOHelper.loadNextRecord(options);
+      } else {
+        RIL.iccInfoPrivate.PNN = pnn;
+      }
+    }
+
+    ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_PNN,
+                                   callback: callback.bind(this)});
+  },
+
+  /**
+   *  Read the list of PLMN (Public Land Mobile Network) entries
+   *  We cannot directly rely on readSwappedNibbleBcdToString(),
+   *  since it will no correctly handle some corner-cases that are
+   *  not a problem in our case (0xFF 0xFF 0xFF).
+   *
+   *  @param length The number of PLMN records.
+   *  @return An array of string corresponding to the PLMNs.
+   */
+  readPLMNEntries: function readPLMNEntries(length) {
+    let plmnList = [];
+    // Each PLMN entry has 3 bytes.
+    debug("readPLMNEntries: PLMN entries length = " + length);
+    let index = 0;
+    while (index < length) {
+      // Unused entries will be 0xFFFFFF, according to EF_SPDI
+      // specs (TS 131 102, section 4.2.66)
+      try {
+        let plmn = [GsmPDUHelper.readHexOctet(),
+                    GsmPDUHelper.readHexOctet(),
+                    GsmPDUHelper.readHexOctet()];
+        if (DEBUG) debug("readPLMNEntries: Reading PLMN entry: [" + index +
+                         "]: '" + plmn + "'");
+        if (plmn[0] != 0xFF &&
+            plmn[1] != 0xFF &&
+            plmn[2] != 0xFF) {
+          let semiOctets = [];
+          for (let idx = 0; idx < plmn.length; idx++) {
+            semiOctets.push((plmn[idx] & 0xF0) >> 4);
+            semiOctets.push(plmn[idx] & 0x0F);
+          }
+
+          // According to TS 24.301, 9.9.3.12, the semi octets is arranged
+          // in format:
+          // Byte 1: MCC[2] | MCC[1]
+          // Byte 2: MNC[3] | MCC[3]
+          // Byte 3: MNC[2] | MNC[1]
+          // Therefore, we need to rearrange them.
+          let reformat = [semiOctets[1], semiOctets[0], semiOctets[3],
+                          semiOctets[5], semiOctets[4], semiOctets[2]];
+          let buf = "";
+          let plmnEntry = {};
+          for (let i = 0; i < reformat.length; i++) {
+            if (reformat[i] != 0xF) {
+              buf += GsmPDUHelper.semiOctetToBcdChar(reformat[i]);
+            }
+            if (i === 2) {
+              // 0-2: MCC
+              plmnEntry.mcc = parseInt(buf);
+              buf = "";
+            } else if (i === 5) {
+              // 3-5: MNC
+              plmnEntry.mnc = parseInt(buf);
+            }
+          }
+          if (DEBUG) debug("readPLMNEntries: PLMN = " + plmnEntry.mcc + ", " + plmnEntry.mnc);
+          plmnList.push(plmnEntry);
+        }
+      } catch (e) {
+        if (DEBUG) debug("readPLMNEntries: PLMN entry " + index + " is invalid.");
+        break;
+      }
+      index ++;
+    }
+    return plmnList;
+  },
+};
+
+/**
+ * Helper functions for ICC utilities.
+ */
+let ICCUtilsHelper = {
+  /**
+   * This will compute the spnDisplay field of the network.
+   * See TS 22.101 Annex A and TS 51.011 10.3.11 for details.
+   *
+   * @return True if some of iccInfo is changed in by this function.
+   */
+  updateDisplayCondition: function updateDisplayCondition() {
+    // If EFspn isn't existed in SIM or it haven't been read yet, we should
+    // just set isDisplayNetworkNameRequired = true and
+    // isDisplaySpnRequired = false
+    let iccInfo = RIL.iccInfo;
+    let iccInfoPriv = RIL.iccInfoPrivate;
+    let iccSpn = iccInfoPriv.SPN;
+    let origIsDisplayNetworkNameRequired = iccInfo.isDisplayNetworkNameRequired;
+    let origIsDisplaySPNRequired = iccInfo.isDisplaySpnRequired;
+
+    if (!iccSpn) {
+      iccInfo.isDisplayNetworkNameRequired = true;
+      iccInfo.isDisplaySpnRequired = false;
+    } else {
+      let operatorMnc = RIL.operator.mnc;
+      let operatorMcc = RIL.operator.mcc;
+
+      // First detect if we are on HPLMN or one of the PLMN
+      // specified by the SIM card.
+      let isOnMatchingPlmn = false;
+
+      // If the current network is the one defined as mcc/mnc
+      // in SIM card, it's okay.
+      if (iccInfo.mcc == operatorMcc && iccInfo.mnc == operatorMnc) {
+        isOnMatchingPlmn = true;
+      }
+
+      // Test to see if operator's mcc/mnc match mcc/mnc of PLMN.
+      if (!isOnMatchingPlmn && iccInfoPriv.SPDI) {
+        let iccSpdi = iccInfoPriv.SPDI; // PLMN list
+        for (let plmn in iccSpdi) {
+          let plmnMcc = iccSpdi[plmn].mcc;
+          let plmnMnc = iccSpdi[plmn].mnc;
+          isOnMatchingPlmn = (plmnMcc == operatorMcc) && (plmnMnc == operatorMnc);
+          if (isOnMatchingPlmn) {
+            break;
+          }
+        }
+      }
+
+      if (isOnMatchingPlmn) {
+        // The first bit of display condition tells us if we should display
+        // registered PLMN.
+        if (DEBUG) debug("updateDisplayCondition: PLMN is HPLMN or PLMN is in PLMN list");
+
+        // TS 31.102 Sec. 4.2.66 and TS 51.011 Sec. 10.3.50
+        // EF_SPDI contains a list of PLMNs in which the Service Provider Name
+        // shall be displayed.
+        iccInfo.isDisplaySpnRequired = true;
+        if (iccSpn.spnDisplayCondition & 0x01) {
+          iccInfo.isDisplayNetworkNameRequired = true;
+        } else {
+          iccInfo.isDisplayNetworkNameRequired = false;
+        }
+      } else {
+        // The second bit of display condition tells us if we should display
+        // registered PLMN.
+        if (DEBUG) debug("updateICCDisplayName: PLMN isn't HPLMN and PLMN isn't in PLMN list");
+
+        // We didn't found the requirement of displaying network name if
+        // current PLMN isn't HPLMN nor one of PLMN in SPDI. So we keep
+        // isDisplayNetworkNameRequired false.
+        if (iccSpn.spnDisplayCondition & 0x02) {
+          iccInfo.isDisplayNetworkNameRequired = false;
+          iccInfo.isDisplaySpnRequired = false;
+        } else {
+          iccInfo.isDisplayNetworkNameRequired = false;
+          iccInfo.isDisplaySpnRequired = true;
+        }
+      }
+    }
+
+    if (DEBUG) {
+      debug("updateDisplayCondition: isDisplayNetworkNameRequired = " + iccInfo.isDisplayNetworkNameRequired);
+      debug("updateDisplayCondition: isDisplaySpnRequired = " + iccInfo.isDisplaySpnRequired);
+    }
+
+    return ((origIsDisplayNetworkNameRequired !== iccInfo.isDisplayNetworkNameRequired) ||
+            (origIsDisplaySPNRequired !== iccInfo.isDisplaySpnRequired));
+  },
+
+  decodeSimTlvs: function decodeSimTlvs(tlvsLen) {
+    let index = 0;
+    let tlvs = [];
+    while (index < tlvsLen) {
+      let simTlv = {
+        tag : GsmPDUHelper.readHexOctet(),
+        length : GsmPDUHelper.readHexOctet(),
+      };
+      simTlv.value = GsmPDUHelper.readHexOctetArray(simTlv.length)
+      tlvs.push(simTlv);
+      index += simTlv.length + 2 /* The length of 'tag' and 'length' field */;
+    }
+    return tlvs;
+  },
+
+  searchForIccUsimTag: function searchForIccUsimTag(tlvs, tag) {
+    for (let i = 0; i < tlvs.length; i++) {
+      if (tlvs[i].tag == tag) {
+        return tlvs[i];
+      }
+    }
+    return null;
+  },
+
+  /**
+   * Update the ICC information to RadioInterfaceLayer.
+   */
+  handleICCInfoChange: function handleICCInfoChange() {
+    RIL.iccInfo.rilMessageType = "iccinfochange";
+    RIL.sendDOMMessage(RIL.iccInfo);
+  },
+
+  /**
+   * Get whether specificed (U)SIM service is available.
+   *
+   * @param geckoService
+   *        Service name like "ADN", "BDN", etc.
+   *
+   * @return true if the service is enabled, false otherwise.
+   */
+  isICCServiceAvailable: function isICCServiceAvailable(geckoService) {
+    let serviceTable = RIL.iccInfo.sst;
+    let index, bitmask;
+    if (RIL.appType == CARD_APPTYPE_SIM) {
+      /**
+       * Service id is valid in 1..N, and 2 bits are used to code each service.
+       *
+       * +----+--  --+----+----+
+       * | b8 | ...  | b2 | b1 |
+       * +----+--  --+----+----+
+       *
+       * b1 = 0, service not allocated.
+       *      1, service allocated.
+       * b2 = 0, service not activatd.
+       *      1, service allocated.
+       *
+       * @see 3GPP TS 51.011 10.3.7.
+       */
+      let simService = GECKO_ICC_SERVICES.sim[geckoService];
+      if (!simService) {
+        return false;
+      }
+      simService -= 1;
+      index = Math.floor(simService / 4);
+      bitmask = 2 << ((simService % 4) << 1);
+    } else {
+      /**
+       * Service id is valid in 1..N, and 1 bit is used to code each service.
+       *
+       * +----+--  --+----+----+
+       * | b8 | ...  | b2 | b1 |
+       * +----+--  --+----+----+
+       *
+       * b1 = 0, service not avaiable.
+       *      1, service available.
+       * b2 = 0, service not avaiable.
+       *      1, service available.
+       *
+       * @see 3GPP TS 31.102 4.2.8.
+       */
+      let usimService = GECKO_ICC_SERVICES.usim[geckoService];
+      if (!usimService) {
+        return false;
+      }
+      usimService -= 1;
+      index = Math.floor(usimService / 8);
+      bitmask = 1 << ((usimService % 8) << 0);
+    }
+
+    return (serviceTable &&
+           (index < serviceTable.length) &&
+           (serviceTable[index] & bitmask)) != 0;
+  },
+};
+
+/**
  * Global stuff.
  */
 
 if (!this.debug) {
   // Debugging stub that goes nowhere.
   this.debug = function debug(message) {
     dump("RIL Worker: " + message + "\n");
   };
--- a/dom/system/gonk/tests/test_ril_worker_icc.js
+++ b/dom/system/gonk/tests/test_ril_worker_icc.js
@@ -186,27 +186,28 @@ add_test(function test_octect_BCD() {
   octet = 0x56;
   number = helper.octetToBCD(octet);
   do_check_eq(helper.BCDToOctet(number), octet);
 
   run_next_test();
 });
 
 /**
- * Verify RIL.isICCServiceAvailable.
+ * Verify ICCUtilsHelper.isICCServiceAvailable.
  */
 add_test(function test_is_icc_service_available() {
   let worker = newUint8Worker();
+  let ICCUtilsHelper = worker.ICCUtilsHelper;
 
   function test_table(sst, geckoService, simEnabled, usimEnabled) {
     worker.RIL.iccInfo.sst = sst;
     worker.RIL.appType = CARD_APPTYPE_SIM;
-    do_check_eq(worker.RIL.isICCServiceAvailable(geckoService), simEnabled);
+    do_check_eq(ICCUtilsHelper.isICCServiceAvailable(geckoService), simEnabled);
     worker.RIL.appType = CARD_APPTYPE_USIM;
-    do_check_eq(worker.RIL.isICCServiceAvailable(geckoService), usimEnabled);
+    do_check_eq(ICCUtilsHelper.isICCServiceAvailable(geckoService), usimEnabled);
   }
 
   test_table([0x08], "ADN", true, false);
   test_table([0x08], "FDN", false, false);
   test_table([0x08], "SDN", false, true);
 
   run_next_test();
 });
@@ -565,27 +566,29 @@ add_test(function test_stk_proactive_com
   for (let i = 0; i < tlv.value.eventList.length; i++) {
     do_check_eq(tlv.value.eventList[i], i);
   }
 
   run_next_test();
 });
 
 add_test(function test_spn_display_condition() {
-  let RIL = newWorker({
+  let worker = newWorker({
     postRILMessage: function fakePostRILMessage(data) {
       // Do nothing
     },
     postMessage: function fakePostMessage(message) {
       // Do nothing
     }
-  }).RIL;
+  });
+  let RIL = worker.RIL;
+  let ICCUtilsHelper = worker.ICCUtilsHelper;
 
   // Test updateDisplayCondition runs before any of SIM file is ready.
-  do_check_eq(RIL.updateDisplayCondition(), true);
+  do_check_eq(ICCUtilsHelper.updateDisplayCondition(), true);
   do_check_eq(RIL.iccInfo.isDisplayNetworkNameRequired, true);
   do_check_eq(RIL.iccInfo.isDisplaySpnRequired, false);
 
   // Test with value.
   function testDisplayCondition(iccDisplayCondition,
                                 iccMcc, iccMnc, plmnMcc, plmnMnc,
                                 expectedIsDisplayNetworkNameRequired,
                                 expectedIsDisplaySPNRequired,
@@ -597,17 +600,17 @@ add_test(function test_spn_display_condi
       mcc: iccMcc,
       mnc: iccMnc
     };
     RIL.operator = {
       mcc: plmnMcc,
       mnc: plmnMnc
     };
 
-    do_check_eq(RIL.updateDisplayCondition(), true);
+    do_check_eq(ICCUtilsHelper.updateDisplayCondition(), true);
     do_check_eq(RIL.iccInfo.isDisplayNetworkNameRequired, expectedIsDisplayNetworkNameRequired);
     do_check_eq(RIL.iccInfo.isDisplaySpnRequired, expectedIsDisplaySPNRequired);
     do_timeout(0, callback);
   };
 
   function testDisplayConditions(func, caseArray, oncomplete) {
     (function do_call(index) {
       let next = index < (caseArray.length - 1) ? do_call.bind(null, index + 1) : oncomplete;
@@ -896,41 +899,42 @@ add_test(function test_stk_proactive_com
   do_check_eq(tlv.value.commandNumber, 0x01);
   do_check_eq(tlv.value.typeOfCommand, STK_CMD_PROVIDE_LOCAL_INFO);
   do_check_eq(tlv.value.commandQualifier, STK_LOCAL_INFO_DATE_TIME_ZONE);
 
   run_next_test();
 });
 
 add_test(function test_path_id_for_spid_and_spn() {
-  let RIL = newWorker({
+  let worker = newWorker({
     postRILMessage: function fakePostRILMessage(data) {
       // Do nothing
     },
     postMessage: function fakePostMessage(message) {
       // Do nothing
-    }
-  }).RIL;
+    }});
+  let RIL = worker.RIL;
+  let ICCFileHelper = worker.ICCFileHelper;
 
   // Test SIM
   RIL.iccStatus = {
     gsmUmtsSubscriptionAppIndex: 0,
     apps: [
       {
         app_type: CARD_APPTYPE_SIM
       }, {
         app_type: CARD_APPTYPE_USIM
       }
     ]
   }
-  do_check_eq(RIL._getPathIdForICCRecord(ICC_EF_SPDI),
+  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
               EF_PATH_MF_SIM + EF_PATH_DF_GSM);
-  do_check_eq(RIL._getPathIdForICCRecord(ICC_EF_SPN),
+  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPN),
               EF_PATH_MF_SIM + EF_PATH_DF_GSM);
 
   // Test USIM
   RIL.iccStatus.gsmUmtsSubscriptionAppIndex = 1;
-  do_check_eq(RIL._getPathIdForICCRecord(ICC_EF_SPDI),
+  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
               EF_PATH_MF_SIM + EF_PATH_ADF_USIM);
-  do_check_eq(RIL._getPathIdForICCRecord(ICC_EF_SPDI),
+  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
               EF_PATH_MF_SIM + EF_PATH_ADF_USIM);
   run_next_test();
-});
\ No newline at end of file
+});
--- a/dom/tests/mochitest/chrome/Makefile.in
+++ b/dom/tests/mochitest/chrome/Makefile.in
@@ -49,16 +49,18 @@ MOCHITEST_CHROME_FILES = \
 		selectAtPoint.html \
 		test_bug799299.xul \
 		file_bug799299.xul \
 		test_bug800817.xul \
 		file_bug800817.xul \
 		test_subscript_bindings.xul \
 		file_subscript_bindings.js \
 		test_sandbox_eventhandler.xul \
+		test_DOM_element_instanceof.xul \
+		file_DOM_element_instanceof.xul \
 		$(NULL)
 
 ifeq (WINNT,$(OS_ARCH))
 MOCHITEST_CHROME_FILES += \
 		test_sizemode_attribute.xul \
 		sizemode_attribute.xul \
 		$(NULL)
 endif
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/chrome/file_DOM_element_instanceof.xul
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<window title="Mozilla Bug 824917"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <iframe type="content"></iframe>
+
+  <script type="application/javascript">
+  <![CDATA[
+  /** Test for Bug 799299 **/
+  var SimpleTest = opener.wrappedJSObject.SimpleTest;
+  var ok = opener.wrappedJSObject.ok;
+
+  var doc = frames[0].document;
+  ok(doc.createElement("body") instanceof HTMLBodyElement,
+     "Should be instance of HTMLBodyElement");
+  ok(doc.createElement("div") instanceof HTMLDivElement,
+     "Should be instance of HTMLDivElement");
+  ok(doc.createElement("frameset") instanceof HTMLFrameSetElement,
+     "Should be instance of HTMLFrameSetElement");
+  ok(doc.createElement("h1") instanceof HTMLHeadingElement,
+     "Should be instance of HTMLHeadingElement");
+  ok(doc.createElement("label") instanceof HTMLLabelElement,
+     "Should be instance of HTMLLabelElement");
+
+  window.close();
+  opener.wrappedJSObject.SimpleTest.finish();
+  ]]>
+  </script>
+</window>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_DOM_element_instanceof.xul
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=824917
+-->
+<window title="Mozilla Bug 824917"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=824917"
+     target="_blank">Mozilla Bug 824917</a>
+  </body>
+
+  <iframe type="content"></iframe>
+
+  <!-- test code goes here -->
+  <script type="application/javascript">
+  <![CDATA[
+  /** Test for Bug 824917 **/
+
+  function runTests() {
+    window.open("file_DOM_element_instanceof.xul", "_blank", "chrome,width=600,height=550");
+  }
+
+  addLoadEvent(runTests);
+
+  SimpleTest.waitForExplicitFinish();
+
+  ]]>
+  </script>
+</window>
new file mode 100644
--- /dev/null
+++ b/dom/tests/unit/test_geolocation_timeout.js
@@ -0,0 +1,61 @@
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+const Cr = Components.results;
+
+Cu.import("resource://testing-common/httpd.js");
+
+var httpserver = null;
+var geolocation = null;
+var success = false;
+var watchId = -1;
+
+function geoHandler(metadata, response)
+{
+    var georesponse = {
+        status: "OK",
+        location: {
+            lat: 42,
+            lng: 42,
+        },
+        accuracy: 42,
+    };
+  var position = JSON.stringify(georesponse);
+  response.processAsync();
+  response.setStatusLine("1.0", 200, "OK");
+  response.setHeader("Cache-Control", "no-cache", false);
+  response.setHeader("Content-Type", "aplication/x-javascript", false);
+  do_timeout(5000, function() {
+    response.write(position);
+    response.finish();
+  });
+}
+
+function successCallback() {
+  do_check_true(false);
+  do_test_finished();
+}
+
+function errorCallback() {
+  do_check_true(true);
+  do_test_finished();
+}
+
+function run_test()
+{
+  do_test_pending();
+
+  httpserver = new HttpServer();
+  httpserver.registerPathHandler("/geo", geoHandler);
+  httpserver.start(4444);
+
+  if (Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
+        .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) {
+    var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+    prefs.setBoolPref("geo.wifi.scan", false);
+    prefs.setCharPref("geo.wifi.uri", "http://localhost:4444/geo");  
+  }
+
+  geolocation = Cc["@mozilla.org/geolocation;1"].getService(Ci.nsIDOMGeoGeolocation);
+  geolocation.getCurrentPosition(successCallback, errorCallback, {timeout: 2000});
+}
new file mode 100644
--- /dev/null
+++ b/dom/tests/unit/test_geolocation_timeout_wrap.js
@@ -0,0 +1,9 @@
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+function run_test() {
+  var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+  prefs.setBoolPref("geo.wifi.scan", false);
+  prefs.setCharPref("geo.wifi.uri", "http://localhost:4444/geo");  
+  run_test_in_child("./test_geolocation_timeout.js");
+}
\ No newline at end of file
--- a/dom/tests/unit/xpcshell.ini
+++ b/dom/tests/unit/xpcshell.ini
@@ -1,9 +1,12 @@
 [DEFAULT]
 head = 
 tail = 
 
 [test_bug319968.js]
 [test_bug465752.js]
 [test_geolocation_provider.js]
+[test_geolocation_timeout.js]
+[test_geolocation_timeout_wrap.js]
+skip-if = os == "mac"
 # Bug 684962: test hangs consistently on Android
 skip-if = os == "android"
--- a/dom/time/Makefile.in
+++ b/dom/time/Makefile.in
@@ -9,17 +9,19 @@ VPATH            = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE           = dom
 LIBRARY_NAME     = dom_time_s
 XPIDL_MODULE     = dom_time
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 include $(topsrcdir)/dom/dom-config.mk
 
 EXPORTS_NAMESPACES = mozilla/dom/time
 
 CPPSRCS = \
   TimeManager.cpp \
   TimeService.cpp \
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -438,16 +438,25 @@ partial interface Document {
                     optional long screenX = 0,
                     optional long screenY = 0,
                     optional long clientX = 0,
                     optional long clientY = 0,
                     optional long radiusX = 0,
                     optional long radiusY = 0,
                     optional float rotationAngle = 0,
                     optional float force = 0);
+  // XXXbz a hack to get around the fact that we don't support variadics as
+  // distinguishing arguments yet.  Once this hack is removed. we can also
+  // remove the corresponding overload on nsIDocument, since Touch... and
+  // sequence<Touch> look the same in the C++.
   [Creator, Pref="dom.w3c_touch_events.expose"]
-  TouchList createTouchList(Touch touch);
+  TouchList createTouchList(Touch touch, Touch... touches);
+  // XXXbz and another hack for the fact that we can't usefully have optional
+  // distinguishing arguments but need a working zero-arg form of
+  // createTouchList().
+  [Creator, Pref="dom.w3c_touch_events.expose"]
+  TouchList createTouchList();
   [Creator, Pref="dom.w3c_touch_events.expose"]
   TouchList createTouchList(sequence<Touch> touches);
   */
 };
 
 Document implements XPathEvaluator;
new file mode 100644
--- /dev/null
+++ b/dom/webidl/HTMLTitleElement.webidl
@@ -0,0 +1,13 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * http://www.whatwg.org/specs/web-apps/current-work/#the-title-element
+ */
+
+interface HTMLTitleElement : HTMLElement {
+           [SetterThrows]
+           attribute DOMString text;
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -56,16 +56,17 @@ webidl_files = \
   HTMLDocument.webidl \
   HTMLElement.webidl \
   HTMLFontElement.webidl \
   HTMLFrameSetElement.webidl \
   HTMLHeadingElement.webidl \
   HTMLLabelElement.webidl \
   HTMLOptionsCollection.webidl \
   HTMLPropertiesCollection.webidl \
+  HTMLTitleElement.webidl \
   ImageData.webidl \
   Location.webidl \
   MutationObserver.webidl \
   Node.webidl \
   NodeFilter.webidl \
   NodeList.webidl \
   PaintRequest.webidl \
   PaintRequestList.webidl \
--- a/dom/workers/Makefile.in
+++ b/dom/workers/Makefile.in
@@ -1,24 +1,26 @@
 # 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/.
 
 DEPTH            = @DEPTH@
 topsrcdir        = @top_srcdir@
 srcdir           = @srcdir@
 VPATH            = @srcdir@
-FAIL_ON_WARNINGS := 1
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE           = dom
 LIBRARY_NAME     = domworkers_s
 LIBXUL_LIBRARY   = 1
 FORCE_STATIC_LIB = 1
+ifndef _MSC_VER
+FAIL_ON_WARNINGS := 1
+endif # !_MSC_VER
 
 CPPSRCS = \
   ChromeWorkerScope.cpp \
   DOMBindingBase.cpp \
   Events.cpp \
   EventListenerManager.cpp \
   EventTarget.cpp \
   Exceptions.cpp \
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -504,22 +504,16 @@ BEGIN_WORKERS_NAMESPACE
 
 // Entry point for the DOM.
 JSBool
 ResolveWorkerClasses(JSContext* aCx, JSHandleObject aObj, JSHandleId aId, unsigned aFlags,
                      JSMutableHandleObject aObjp)
 {
   AssertIsOnMainThread();
 
-  // Don't care about assignments, bail now.
-  if (aFlags & JSRESOLVE_ASSIGNING) {
-    aObjp.set(nullptr);
-    return true;
-  }
-
   // Make sure our strings are interned.
   if (JSID_IS_VOID(gStringIDs[0])) {
     for (uint32_t i = 0; i < ID_COUNT; i++) {
       JSString* str = JS_InternString(aCx, gStringChars[i]);
       if (!str) {
         while (i) {
           gStringIDs[--i] = JSID_VOID;
         }
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -75,17 +75,17 @@ using mozilla::MutexAutoLock;
 using mozilla::TimeDuration;
 using mozilla::TimeStamp;
 using mozilla::dom::workers::exceptions::ThrowDOMExceptionForNSResult;
 
 USING_WORKERS_NAMESPACE
 using namespace mozilla::dom::workers::events;
 using namespace mozilla::dom;
 
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsWorkerMallocSizeOf, "js-worker")
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsWorkerMallocSizeOf)
 
 namespace {
 
 const char gErrorChars[] = "error";
 const char gMessageChars[] = "message";
 
 template <class T>
 class AutoPtrComparator
@@ -932,19 +932,23 @@ public:
 
     // Dispatch may fail if the worker was canceled, no need to report that as
     // an error, so don't call base class PostDispatch.
   }
 
   bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
   {
-    JSObject* target = aWorkerPrivate->IsAcceptingEvents() ?
-                       aWorkerPrivate->GetJSObject() :
-                       nullptr;
+    // Don't fire this event if the JS object has been disconnected from the
+    // private object.
+    if (!aWorkerPrivate->IsAcceptingEvents()) {
+      return true;
+    }
+
+    JSObject* target = aWorkerPrivate->GetJSObject();
 
     uint64_t innerWindowId;
 
     WorkerPrivate* parent = aWorkerPrivate->GetParent();
     if (parent) {
       innerWindowId = 0;
     }
     else {
--- a/dom/workers/test/Makefile.in
+++ b/dom/workers/test/Makefile.in
@@ -36,16 +36,18 @@ MOCHITEST_FILES = \
   test_importScripts.html \
   importScripts_worker.js \
   importScripts_worker_imported1.js \
   importScripts_worker_imported2.js \
   importScripts_worker_imported3.js \
   importScripts_worker_imported4.js \
   test_instanceof.html \
   instanceof_worker.js \
+  test_resolveWorker.html \
+  test_resolveWorker-assignment.html \
   test_json.html \
   json_worker.js \
   test_location.html \
   location_worker.js \
   test_longThread.html \
   longThread_worker.js \
   test_navigator.html \
   navigator_worker.js \
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/test_resolveWorker-assignment.html
@@ -0,0 +1,32 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+  <head>
+    <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  </head>
+  <body>
+    <script type="application/javascript">
+      window.Worker = 17; // resolve through assignment
+
+      var desc = Object.getOwnPropertyDescriptor(window, "Worker");
+      ok(typeof desc === "object" && desc !== null, "Worker property must exist");
+
+      is(desc.value, 17, "Overwrite didn't work correctly");
+      // The JSRESOLVE_ASSIGNING flag-check around the "Resolve special classes"
+      // block in nsWindowSH::NewResolve needs to die to enable this.
+      todo_is(desc.enumerable, false,
+              "Initial descriptor was non-enumerable, and [[Put]] changes the " +
+              "property value but not its enumerability");
+      is(desc.configurable, true,
+         "Initial descriptor was configurable, and [[Put]] changes the " +
+         "property value but not its configurability");
+      is(desc.writable, true,
+         "Initial descriptor was writable, and [[Put]] changes the " +
+         "property value but not its writability");
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/test_resolveWorker.html
@@ -0,0 +1,31 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+  <head>
+    <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  </head>
+  <body>
+    <script type="application/javascript">
+      window.Worker; // resolve not through assignment
+      Worker = 17;
+
+      var desc = Object.getOwnPropertyDescriptor(window, "Worker");
+      ok(typeof desc === "object" && desc !== null, "Worker property must exist");
+
+      is(desc.value, 17, "Overwrite didn't work correctly");
+      is(desc.enumerable, false,
+         "Initial descriptor was non-enumerable, and [[Put]] changes the " +
+         "property value but not its enumerability");
+      is(desc.configurable, true,
+         "Initial descriptor was configurable, and [[Put]] changes the " +
+         "property value but not its configurability");
+      is(desc.writable, true,
+         "Initial descriptor was writable, and [[Put]] changes the " +
+         "property value but not its writability");
+    </script>
+  </body>
+</html>
--- a/editor/composer/src/Makefile.in
+++ b/editor/composer/src/Makefile.in
@@ -2,26 +2,28 @@
 # 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/.
 
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
-FAIL_ON_WARNINGS = 1
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= editor
 LIBRARY_NAME	= composer
 EXPORT_LIBRARY = 1
 IS_COMPONENT	= 1
 MODULE_NAME	= nsComposerModule
 LIBXUL_LIBRARY	= 1
+ifndef _MSC_VER
+FAIL_ON_WARNINGS = 1
+endif # !_MSC_VER
 
 
 CPPSRCS  = \
            nsComposeTxtSrvFilter.cpp            \
            nsComposerController.cpp       \
            nsComposerCommands.cpp         \
            nsComposerDocumentCommands.cpp \
            nsComposerRegistration.cpp     \
--- a/editor/libeditor/base/Makefile.in
+++ b/editor/libeditor/base/Makefile.in
@@ -2,25 +2,27 @@
 # 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/.
 
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
-FAIL_ON_WARNINGS = 1
 
 include $(DEPTH)/config/autoconf.mk
 
 TEST_DIRS += tests
 
 MODULE		= editor
 LIBRARY_NAME	= editorbase_s
 LIBXUL_LIBRARY	= 1
+ifndef _MSC_VER
+FAIL_ON_WARNINGS = 1
+endif # !_MSC_VER
 
 
 # Internal header files, needed by other editor sublibs:
 INTERNAL_HDR_DIR = ../internal
 
 CPPSRCS		=                           \
 		nsEditor.cpp                \
 		nsEditorCommands.cpp        \
--- a/editor/libeditor/html/nsHTMLEditorStyle.cpp
+++ b/editor/libeditor/html/nsHTMLEditorStyle.cpp
@@ -1778,19 +1778,23 @@ nsHTMLEditor::RelativeFontChangeHelper(i
   // If this is a font node with size, put big/small inside it.
   if (aNode->IsElement() && aNode->AsElement()->IsHTML(nsGkAtoms::font) &&
       aNode->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::size)) {
     // Cycle through children and adjust relative font size.
     for (uint32_t i = aNode->GetChildCount(); i--; ) {
       nsresult rv = RelativeFontChangeOnNode(aSizeChange, aNode->GetChildAt(i));
       NS_ENSURE_SUCCESS(rv, rv);
     }
+
+    // RelativeFontChangeOnNode already calls us recursively,
+    // so we don't need to check our children again.
+    return NS_OK;
   }
 
-  // Now cycle through the children.
+  // Otherwise cycle through the children.
   for (uint32_t i = aNode->GetChildCount(); i--; ) {
     nsresult rv = RelativeFontChangeHelper(aSizeChange, aNode->GetChildAt(i));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
--- a/embedding/components/printingui/src/mac/nsPrintProgress.cpp
+++ b/embedding/components/printingui/src/mac/nsPrintProgress.cpp
@@ -117,180 +117,115 @@ NS_IMETHODIMP nsPrintProgress::SetProces
   m_processCanceled = aProcessCanceledByUser;
   OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, NS_OK);
   return NS_OK;
 }
 
 /* void RegisterListener (in nsIWebProgressListener listener); */
 NS_IMETHODIMP nsPrintProgress::RegisterListener(nsIWebProgressListener * listener)
 {
-  nsresult rv = NS_OK;
-  
   if (!listener) //Nothing to do with a null listener!
     return NS_OK;
   
-  if (!m_listenerList)
-    rv = NS_NewISupportsArray(getter_AddRefs(m_listenerList));
-  
-  if (NS_SUCCEEDED(rv) && m_listenerList)
+  m_listenerList.AppendObject(listener);
+  if (m_closeProgress || m_processCanceled)
+    listener->OnStateChange(nullptr, nullptr,
+                            nsIWebProgressListener::STATE_STOP, NS_OK);
+  else
   {
-    m_listenerList->AppendElement(listener);
-    if (m_closeProgress || m_processCanceled)
-      listener->OnStateChange(nullptr, nullptr,
-                              nsIWebProgressListener::STATE_STOP, NS_OK);
-    else
-    {
-      listener->OnStatusChange(nullptr, nullptr, NS_OK, m_pendingStatus.get());
-      if (m_pendingStateFlags != -1)
-        listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags, m_pendingStateValue);
-    }
+    listener->OnStatusChange(nullptr, nullptr, NS_OK, m_pendingStatus.get());
+    if (m_pendingStateFlags != -1)
+      listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags, m_pendingStateValue);
   }
     
   return NS_OK;
 }
 
 /* void UnregisterListener (in nsIWebProgressListener listener); */
 NS_IMETHODIMP nsPrintProgress::UnregisterListener(nsIWebProgressListener *listener)
 {
-  if (m_listenerList && listener)
-    m_listenerList->RemoveElement(listener);
+  if (listener)
+    m_listenerList.RemoveObject(listener);
   
   return NS_OK;
 }
 
 /* void doneIniting (); */
 NS_IMETHODIMP nsPrintProgress::DoneIniting()
 {
   if (m_observer) {
     m_observer->Observe(nullptr, nullptr, nullptr);
   }
   return NS_OK;
 }
 
 /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in nsresult aStatus); */
 NS_IMETHODIMP nsPrintProgress::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus)
 {
-  nsresult rv = NS_OK;
-
   m_pendingStateFlags = aStateFlags;
   m_pendingStateValue = aStatus;
   
-  if (m_listenerList)
+  uint32_t count = m_listenerList.Count();
+  for (uint32_t i = count - 1; i < count; i --)
   {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_FAILED(rv))
-      return rv;
-  
-    nsCOMPtr<nsISupports> aSupports;
-    nsCOMPtr<nsIWebProgressListener> aProgressListener;
-    for (i = count - 1; i >= 0; i --)
-    {
-      m_listenerList->GetElementAt(i, getter_AddRefs(aSupports));
-      aProgressListener = do_QueryInterface(aSupports);
-      if (aProgressListener)
-        aProgressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
-    }
+    nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
+    if (progressListener)
+      progressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
   }
   
-  return rv;
+  return NS_OK;
 }
 
 /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
 NS_IMETHODIMP nsPrintProgress::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, int32_t aCurSelfProgress, int32_t aMaxSelfProgress, int32_t aCurTotalProgress, int32_t aMaxTotalProgress)
 {
-  nsresult rv = NS_OK;
-
-  if (m_listenerList)
+  uint32_t count = m_listenerList.Count();
+  for (uint32_t i = count - 1; i < count; i --)
   {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_FAILED(rv))
-      return rv;
-  
-    nsCOMPtr<nsISupports> aSupports;
-    nsCOMPtr<nsIWebProgressListener> aProgressListener;
-    for (i = count - 1; i >= 0; i --)
-    {
-      m_listenerList->GetElementAt(i, getter_AddRefs(aSupports));
-      aProgressListener = do_QueryInterface(aSupports);
-      if (aProgressListener)
-        aProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
-    }
+    nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
+    if (progressListener)
+      progressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
   }
   
-  return rv;
+  return NS_OK;
 }
 
 /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */
 NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, uint32_t aFlags)
 {
     return NS_OK;
 }
 
 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
 NS_IMETHODIMP nsPrintProgress::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
 {
-  nsresult rv = NS_OK;
-
   if (aMessage && *aMessage)
   m_pendingStatus = aMessage;
-  if (m_listenerList)
+
+  uint32_t count = m_listenerList.Count();
+  for (uint32_t i = count - 1; i < count; i --)
   {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_FAILED(rv))
-      return rv;
-  
-    nsCOMPtr<nsISupports> aSupports;
-    nsCOMPtr<nsIWebProgressListener> aProgressListener;
-    for (i = count - 1; i >= 0; i --)
-    {
-      m_listenerList->GetElementAt(i, getter_AddRefs(aSupports));
-      aProgressListener = do_QueryInterface(aSupports);
-      if (aProgressListener)
-        aProgressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
-    }
+    nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
+    if (progressListener)
+      progressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
   }
   
-  return rv;
+  return NS_OK;
 }
 
 /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
 NS_IMETHODIMP nsPrintProgress::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t state)
 {
     return NS_OK;
 }
 
 nsresult nsPrintProgress::ReleaseListeners()
 {
-  nsresult rv = NS_OK;
-
-  if (m_listenerList)
-  {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_SUCCEEDED(rv))    
-      for (i = count - 1; i >= 0; i --)
-        m_listenerList->RemoveElementAt(i);
-  }
-  
-  return rv;
+  m_listenerList.Clear();
+  return NS_OK;
 }
 
 NS_IMETHODIMP nsPrintProgress::ShowStatusString(const PRUnichar *status)
 {
   return OnStatusChange(nullptr, nullptr, NS_OK, status);
 }
 
 /* void startMeteors (); */
--- a/embedding/components/printingui/src/mac/nsPrintProgress.h
+++ b/embedding/components/printingui/src/mac/nsPrintProgress.h
@@ -3,18 +3,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __nsPrintProgress_h
 #define __nsPrintProgress_h
 
 #include "nsIPrintProgress.h"
 
+#include "nsCOMArray.h"
 #include "nsCOMPtr.h"
-#include "nsISupportsArray.h"
 #include "nsIDOMWindow.h"
 #include "nsIPrintStatusFeedback.h"
 #include "nsIObserver.h"
 #include "nsString.h"
 
 class nsPrintProgress : public nsIPrintProgress, public nsIPrintStatusFeedback
 {
 public: 
@@ -30,13 +30,13 @@ private:
   nsresult ReleaseListeners();
 
   bool                              m_closeProgress;
   bool                              m_processCanceled;
   nsString                          m_pendingStatus;
   int32_t                           m_pendingStateFlags;
   nsresult                          m_pendingStateValue;
   nsCOMPtr<nsIDOMWindow>            m_dialog;
-  nsCOMPtr<nsISupportsArray>        m_listenerList;
+  nsCOMArray<nsIWebProgressListener>        m_listenerList;
   nsCOMPtr<nsIObserver>             m_observer;
 };
 
 #endif
--- a/embedding/components/printingui/src/os2/nsPrintProgress.cpp
+++ b/embedding/components/printingui/src/os2/nsPrintProgress.cpp
@@ -112,179 +112,114 @@ NS_IMETHODIMP nsPrintProgress::SetProces
   m_processCanceled = aProcessCanceledByUser;
   OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, false);
   return NS_OK;
 }
 
 /* void RegisterListener (in nsIWebProgressListener listener); */
 NS_IMETHODIMP nsPrintProgress::RegisterListener(nsIWebProgressListener * listener)
 {
-  nsresult rv = NS_OK;
-  
   if (!listener) //Nothing to do with a null listener!
     return NS_OK;
   
-  if (!m_listenerList)
-    rv = NS_NewISupportsArray(getter_AddRefs(m_listenerList));
-  
-  if (NS_SUCCEEDED(rv) && m_listenerList)
+  m_listenerList.AppendObject(listener);
+  if (m_closeProgress || m_processCanceled)
+    listener->OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, 0);
+  else
   {
-    m_listenerList->AppendElement(listener);
-    if (m_closeProgress || m_processCanceled)
-      listener->OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, 0);
-    else
-    {
-      listener->OnStatusChange(nullptr, nullptr, 0, m_pendingStatus.get());
-      if (m_pendingStateFlags != -1)
-        listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags, m_pendingStateValue);
-    }
+    listener->OnStatusChange(nullptr, nullptr, 0, m_pendingStatus.get());
+    if (m_pendingStateFlags != -1)
+      listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags, m_pendingStateValue);
   }
     
   return NS_OK;
 }
 
 /* void UnregisterListener (in nsIWebProgressListener listener); */
 NS_IMETHODIMP nsPrintProgress::UnregisterListener(nsIWebProgressListener *listener)
 {
-  if (m_listenerList && listener)
-    m_listenerList->RemoveElement(listener);
+  if (listener)
+    m_listenerList.RemoveObject(listener);
   
   return NS_OK;
 }
 
 /* void doneIniting (); */
 NS_IMETHODIMP nsPrintProgress::DoneIniting()
 {
   if (m_observer) {
     m_observer->Observe(nullptr, nullptr, nullptr);
   }
   return NS_OK;
 }
 
 /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in nsresult aStatus); */
 NS_IMETHODIMP nsPrintProgress::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus)
 {
-  nsresult rv = NS_OK;
-
   m_pendingStateFlags = aStateFlags;
   m_pendingStateValue = aStatus;
   
-  if (m_listenerList)
+  uint32_t count = m_listenerList.Count();
+  for (uint32_t i = count - 1; i < count; i --)
   {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_FAILED(rv))
-      return rv;
-  
-    nsCOMPtr<nsISupports> aSupports;
-    nsCOMPtr<nsIWebProgressListener> aProgressListener;
-    for (i = count - 1; i >= 0; i --)
-    {
-      m_listenerList->GetElementAt(i, getter_AddRefs(aSupports));
-      aProgressListener = do_QueryInterface(aSupports);
-      if (aProgressListener)
-        aProgressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
-    }
+    nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
+    if (progressListener)
+      progressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
   }
   
-  return rv;
+  return NS_OK;
 }
 
 /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
 NS_IMETHODIMP nsPrintProgress::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, int32_t aCurSelfProgress, int32_t aMaxSelfProgress, int32_t aCurTotalProgress, int32_t aMaxTotalProgress)
 {
-  nsresult rv = NS_OK;
-
-  if (m_listenerList)
+  uint32_t count = m_listenerList.Count();
+  for (uint32_t i = count - 1; i < count; i --)
   {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_FAILED(rv))
-      return rv;
-  
-    nsCOMPtr<nsISupports> aSupports;
-    nsCOMPtr<nsIWebProgressListener> aProgressListener;
-    for (i = count - 1; i >= 0; i --)
-    {
-      m_listenerList->GetElementAt(i, getter_AddRefs(aSupports));
-      aProgressListener = do_QueryInterface(aSupports);
-      if (aProgressListener)
-        aProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
-    }
+    nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.safeObjectAt(i);
+    if (progressListener)
+      progressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
   }
   
-  return rv;
+  return NS_OK;
 }
 
 /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */
 NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, uint32_t aFlags)
 {
     return NS_OK;
 }
 
 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
 NS_IMETHODIMP nsPrintProgress::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
 {
-  nsresult rv = NS_OK;
-
   if (aMessage && *aMessage)
   m_pendingStatus = aMessage;
-  if (m_listenerList)
+
+  uint32_t count = m_listenerList.Count();
+  for (uint32_t i = count - 1; i < count; i --)
   {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_FAILED(rv))
-      return rv;
-  
-    nsCOMPtr<nsISupports> aSupports;
-    nsCOMPtr<nsIWebProgressListener> aProgressListener;
-    for (i = count - 1; i >= 0; i --)
-    {
-      m_listenerList->GetElementAt(i, getter_AddRefs(aSupports));
-      aProgressListener = do_QueryInterface(aSupports);
-      if (aProgressListener)
-        aProgressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
-    }
+    nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
+    if (progressListener)
+      progressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
   }
   
-  return rv;
+  return NS_OK;
 }
 
 /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
 NS_IMETHODIMP nsPrintProgress::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t state)
 {
     return NS_OK;
 }
 
 nsresult nsPrintProgress::ReleaseListeners()
 {
-  nsresult rv = NS_OK;
-
-  if (m_listenerList)
-  {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_SUCCEEDED(rv))    
-      for (i = count - 1; i >= 0; i --)
-        m_listenerList->RemoveElementAt(i);
-  }
-  
-  return rv;
+  m_listenerList.Clear();
+  return NS_OK;
 }
 
 NS_IMETHODIMP nsPrintProgress::ShowStatusString(const PRUnichar *status)
 {
   return OnStatusChange(nullptr, nullptr, NS_OK, status);
 }
 
 /* void startMeteors (); */
--- a/embedding/components/printingui/src/os2/nsPrintProgress.h
+++ b/embedding/components/printingui/src/os2/nsPrintProgress.h
@@ -3,18 +3,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __nsPrintProgress_h
 #define __nsPrintProgress_h
 
 #include "nsIPrintProgress.h"
 
+#include "nsCOMArray.h"
 #include "nsCOMPtr.h"
-#include "nsISupportsArray.h"
 #include "nsIDOMWindow.h"
 #include "nsIPrintStatusFeedback.h"
 #include "nsIObserver.h"
 #include "nsString.h"
 
 class nsPrintProgress : public nsIPrintProgress, public nsIPrintStatusFeedback
 {
 public: 
@@ -30,13 +30,13 @@ private:
   nsresult ReleaseListeners();
 
   bool                              m_closeProgress;
   bool                              m_processCanceled;
   nsString                          m_pendingStatus;
   int32_t                           m_pendingStateFlags;
   int32_t                           m_pendingStateValue;
   nsCOMPtr<nsIDOMWindow>            m_dialog;
-  nsCOMPtr<nsISupportsArray>        m_listenerList;
+  nsCOMArray<nsIWebProgressListener>        m_listenerList;
   nsCOMPtr<nsIObserver>             m_observer;
 };
 
 #endif
--- a/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp
+++ b/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp
@@ -117,179 +117,115 @@ NS_IMETHODIMP nsPrintProgress::SetProces
   m_processCanceled = aProcessCanceledByUser;
   OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, NS_OK);
   return NS_OK;
 }
 
 /* void RegisterListener (in nsIWebProgressListener listener); */
 NS_IMETHODIMP nsPrintProgress::RegisterListener(nsIWebProgressListener * listener)
 {
-  nsresult rv = NS_OK;
-  
   if (!listener) //Nothing to do with a null listener!
     return NS_OK;
   
-  if (!m_listenerList)
-    rv = NS_NewISupportsArray(getter_AddRefs(m_listenerList));
-  
-  if (NS_SUCCEEDED(rv) && m_listenerList)
+  m_listenerList.AppendObject(listener);
+  if (m_closeProgress || m_processCanceled)
+    listener->OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, NS_OK);
+  else
   {
-    m_listenerList->AppendElement(listener);
-    if (m_closeProgress || m_processCanceled)
-      listener->OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, NS_OK);
-    else
-    {
-      listener->OnStatusChange(nullptr, nullptr, NS_OK, m_pendingStatus.get());
-      if (m_pendingStateFlags != -1)
-        listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags, m_pendingStateValue);
-    }
+    listener->OnStatusChange(nullptr, nullptr, NS_OK, m_pendingStatus.get());
+    if (m_pendingStateFlags != -1)
+      listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags, m_pendingStateValue);
   }
     
   return NS_OK;
 }
 
 /* void UnregisterListener (in nsIWebProgressListener listener); */
 NS_IMETHODIMP nsPrintProgress::UnregisterListener(nsIWebProgressListener *listener)
 {
-  if (m_listenerList && listener)
-    m_listenerList->RemoveElement(listener);
+  if (listener)
+    m_listenerList.RemoveObject(listener);
   
   return NS_OK;
 }
 
 /* void doneIniting (); */
 NS_IMETHODIMP nsPrintProgress::DoneIniting()
 {
   if (m_observer) {
     m_observer->Observe(nullptr, nullptr, nullptr);
   }
   return NS_OK;
 }
 
 /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in nsresult aStatus); */
 NS_IMETHODIMP nsPrintProgress::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus)
 {
-  nsresult rv = NS_OK;
-
   m_pendingStateFlags = aStateFlags;
   m_pendingStateValue = aStatus;
   
-  if (m_listenerList)
+  uint32_t count = m_listenerList.Count();
+  for (uint32_t i = count - 1; i < count; i --)
   {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_FAILED(rv))
-      return rv;
-  
-    nsCOMPtr<nsISupports> aSupports;
-    nsCOMPtr<nsIWebProgressListener> aProgressListener;
-    for (i = count - 1; i >= 0; i --)
-    {
-      m_listenerList->GetElementAt(i, getter_AddRefs(aSupports));
-      aProgressListener = do_QueryInterface(aSupports);
-      if (aProgressListener)
-        aProgressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
-    }
+    nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
+    if (progressListener)
+      progressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
   }
   
-  return rv;
+  return NS_OK;
 }
 
 /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
 NS_IMETHODIMP nsPrintProgress::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, int32_t aCurSelfProgress, int32_t aMaxSelfProgress, int32_t aCurTotalProgress, int32_t aMaxTotalProgress)
 {
-  nsresult rv = NS_OK;
-
-  if (m_listenerList)
+  uint32_t count = m_listenerList.Count();
+  for (uint32_t i = count - 1; i < count; i --)
   {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_FAILED(rv))
-      return rv;
-  
-    nsCOMPtr<nsISupports> aSupports;
-    nsCOMPtr<nsIWebProgressListener> aProgressListener;
-    for (i = count - 1; i >= 0; i --)
-    {
-      m_listenerList->GetElementAt(i, getter_AddRefs(aSupports));
-      aProgressListener = do_QueryInterface(aSupports);
-      if (aProgressListener)
-        aProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
-    }
+    nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
+    if (progressListener)
+      progressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
   }
   
-  return rv;
+  return NS_OK;
 }
 
 /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */
 NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, uint32_t aFlags)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
 NS_IMETHODIMP nsPrintProgress::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
 {
-  nsresult rv = NS_OK;
-
   if (aMessage && *aMessage)
   m_pendingStatus = aMessage;
-  if (m_listenerList)
+
+  uint32_t count = m_listenerList.Count();
+  for (uint32_t i = count - 1; i < count; i --)
   {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_FAILED(rv))
-      return rv;
-  
-    nsCOMPtr<nsISupports> aSupports;
-    nsCOMPtr<nsIWebProgressListener> aProgressListener;
-    for (i = count - 1; i >= 0; i --)
-    {
-      m_listenerList->GetElementAt(i, getter_AddRefs(aSupports));
-      aProgressListener = do_QueryInterface(aSupports);
-      if (aProgressListener)
-        aProgressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
-    }
+    nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
+    if (progressListener)
+      progressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
   }
   
-  return rv;
+  return NS_OK;
 }
 
 /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
 NS_IMETHODIMP nsPrintProgress::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t state)
 {
     return NS_OK;
 }
 
 nsresult nsPrintProgress::ReleaseListeners()
 {
-  nsresult rv = NS_OK;
-
-  if (m_listenerList)
-  {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_SUCCEEDED(rv))    
-      for (i = count - 1; i >= 0; i --)
-        m_listenerList->RemoveElementAt(i);
-  }
+  m_listenerList.Clear();
   
-  return rv;
+  return NS_OK;
 }
 
 NS_IMETHODIMP nsPrintProgress::ShowStatusString(const PRUnichar *status)
 {
   return OnStatusChange(nullptr, nullptr, NS_OK, status);
 }
 
 /* void startMeteors (); */
--- a/embedding/components/printingui/src/unixshared/nsPrintProgress.h
+++ b/embedding/components/printingui/src/unixshared/nsPrintProgress.h
@@ -4,18 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __nsPrintProgress_h
 #define __nsPrintProgress_h
 
 #include "nsIPrintProgress.h"
 #include "nsIPrintingPromptService.h"
 
+#include "nsCOMArray.h"
 #include "nsCOMPtr.h"
-#include "nsISupportsArray.h"
 #include "nsIDOMWindow.h"
 #include "nsIPrintStatusFeedback.h"
 #include "nsIObserver.h"
 #include "nsString.h"
 
 class nsPrintProgress : public nsIPrintProgress, public nsIPrintStatusFeedback
 {
 public: 
@@ -31,14 +31,14 @@ private:
   nsresult ReleaseListeners();
 
   bool                              m_closeProgress;
   bool                              m_processCanceled;
   nsString                          m_pendingStatus;
   int32_t                           m_pendingStateFlags;
   nsresult                          m_pendingStateValue;
   nsCOMPtr<nsIDOMWindow>            m_dialog;
-  nsCOMPtr<nsISupportsArray>        m_listenerList;
+  nsCOMArray<nsIWebProgressListener>        m_listenerList;
   nsCOMPtr<nsIObserver>             m_observer;
   nsCOMPtr<nsIPrintSettings>        m_PrintSetting;
 };
 
 #endif
--- a/embedding/components/printingui/src/win/nsPrintProgress.cpp
+++ b/embedding/components/printingui/src/win/nsPrintProgress.cpp
@@ -145,180 +145,115 @@ NS_IMETHODIMP nsPrintProgress::SetProces
   m_processCanceled = aProcessCanceledByUser;
   OnStateChange(nullptr, nullptr, nsIWebProgressListener::STATE_STOP, NS_OK);
   return NS_OK;
 }
 
 /* void RegisterListener (in nsIWebProgressListener listener); */
 NS_IMETHODIMP nsPrintProgress::RegisterListener(nsIWebProgressListener * listener)
 {
-  nsresult rv = NS_OK;
-  
   if (!listener) //Nothing to do with a null listener!
     return NS_OK;
   
-  if (!m_listenerList)
-    rv = NS_NewISupportsArray(getter_AddRefs(m_listenerList));
-  
-  if (NS_SUCCEEDED(rv) && m_listenerList)
+  m_listenerList.AppendObject(listener);
+  if (m_closeProgress || m_processCanceled)
+    listener->OnStateChange(nullptr, nullptr,
+                            nsIWebProgressListener::STATE_STOP, NS_OK);
+  else
   {
-    m_listenerList->AppendElement(listener);
-    if (m_closeProgress || m_processCanceled)
-      listener->OnStateChange(nullptr, nullptr,
-                              nsIWebProgressListener::STATE_STOP, NS_OK);
-    else
-    {
-      listener->OnStatusChange(nullptr, nullptr, NS_OK, m_pendingStatus.get());
-      if (m_pendingStateFlags != -1)
-        listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags, m_pendingStateValue);
-    }
+    listener->OnStatusChange(nullptr, nullptr, NS_OK, m_pendingStatus.get());
+    if (m_pendingStateFlags != -1)
+      listener->OnStateChange(nullptr, nullptr, m_pendingStateFlags, m_pendingStateValue);
   }
     
   return NS_OK;
 }
 
 /* void UnregisterListener (in nsIWebProgressListener listener); */
 NS_IMETHODIMP nsPrintProgress::UnregisterListener(nsIWebProgressListener *listener)
 {
-  if (m_listenerList && listener)
-    m_listenerList->RemoveElement(listener);
+  if (listener)
+    m_listenerList.RemoveObject(listener);
   
   return NS_OK;
 }
 
 /* void doneIniting (); */
 NS_IMETHODIMP nsPrintProgress::DoneIniting()
 {
   if (m_observer) {
     m_observer->Observe(nullptr, nullptr, nullptr);
   }
   return NS_OK;
 }
 
 /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in nsresult aStatus); */
 NS_IMETHODIMP nsPrintProgress::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus)
 {
-  nsresult rv = NS_OK;
-
   m_pendingStateFlags = aStateFlags;
   m_pendingStateValue = aStatus;
   
-  if (m_listenerList)
+  uint32_t count = m_listenerList.Count();
+  for (uint32_t i = count - 1; i < count; i --)
   {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_FAILED(rv))
-      return rv;
-  
-    nsCOMPtr<nsISupports> aSupports;
-    nsCOMPtr<nsIWebProgressListener> aProgressListener;
-    for (i = count - 1; i >= 0; i --)
-    {
-      m_listenerList->GetElementAt(i, getter_AddRefs(aSupports));
-      aProgressListener = do_QueryInterface(aSupports);
-      if (aProgressListener)
-        aProgressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
-    }
+    nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
+    if (progressListener)
+      progressListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus);
   }
   
-  return rv;
+  return NS_OK;
 }
 
 /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
 NS_IMETHODIMP nsPrintProgress::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, int32_t aCurSelfProgress, int32_t aMaxSelfProgress, int32_t aCurTotalProgress, int32_t aMaxTotalProgress)
 {
-  nsresult rv = NS_OK;
-
-  if (m_listenerList)
+  uint32_t count = m_listenerList.Count();
+  for (uint32_t i = count - 1; i < count; i --)
   {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_FAILED(rv))
-      return rv;
-  
-    nsCOMPtr<nsISupports> aSupports;
-    nsCOMPtr<nsIWebProgressListener> aProgressListener;
-    for (i = count - 1; i >= 0; i --)
-    {
-      m_listenerList->GetElementAt(i, getter_AddRefs(aSupports));
-      aProgressListener = do_QueryInterface(aSupports);
-      if (aProgressListener)
-        aProgressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
-    }
+    nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
+    if (progressListener)
+      progressListener->OnProgressChange(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress);
   }
   
-  return rv;
+  return NS_OK;
 }
 
 /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location, in unsigned long aFlags); */
 NS_IMETHODIMP nsPrintProgress::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location, uint32_t aFlags)
 {
     return NS_OK;
 }
 
 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
 NS_IMETHODIMP nsPrintProgress::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
 {
-  nsresult rv = NS_OK;
-
   if (aMessage && *aMessage)
   m_pendingStatus = aMessage;
-  if (m_listenerList)
+
+  uint32_t count = m_listenerList.Count();
+  for (uint32_t i = count - 1; i < count; i --)
   {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_FAILED(rv))
-      return rv;
-  
-    nsCOMPtr<nsISupports> aSupports;
-    nsCOMPtr<nsIWebProgressListener> aProgressListener;
-    for (i = count - 1; i >= 0; i --)
-    {
-      m_listenerList->GetElementAt(i, getter_AddRefs(aSupports));
-      aProgressListener = do_QueryInterface(aSupports);
-      if (aProgressListener)
-        aProgressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
-    }
+    nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i);
+    if (progressListener)
+      progressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
   }
   
-  return rv;
+  return NS_OK;
 }
 
 /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
 NS_IMETHODIMP nsPrintProgress::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t state)
 {
     return NS_OK;
 }
 
 nsresult nsPrintProgress::ReleaseListeners()
 {
-  nsresult rv = NS_OK;
-
-  if (m_listenerList)
-  {
-    uint32_t count;
-    int32_t i;
-
-    rv = m_listenerList->Count(&count);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "m_listenerList->Count() failed");
-    if (NS_SUCCEEDED(rv))    
-      for (i = count - 1; i >= 0; i --)
-        m_listenerList->RemoveElementAt(i);
-  }
-  
-  return rv;
+  m_listenerList.Clear();
+  return NS_OK;
 }
 
 NS_IMETHODIMP nsPrintProgress::ShowStatusString(const PRUnichar *status)
 {
   return OnStatusChange(nullptr, nullptr, NS_OK, status);
 }
 
 /* void startMeteors (); */
--- a/embedding/components/printingui/src/win/nsPrintProgress.h
+++ b/embedding/components/printingui/src/win/nsPrintProgress.h
@@ -3,18 +3,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __nsPrintProgress_h
 #define __nsPrintProgress_h
 
 #include "nsIPrintProgress.h"
 
+#include "nsCOMArray.h"
 #include "nsCOMPtr.h"
-#include "nsISupportsArray.h"
 #include "nsIDOMWindow.h"
 #include "nsIPrintStatusFeedback.h"
 #include "nsString.h"
 #include "nsIWindowWatcher.h"
 #include "nsIObserver.h"
 
 class nsPrintProgress : public nsIPrintProgress, public nsIPrintStatusFeedback
 {
@@ -31,13 +31,13 @@ private:
   nsresult ReleaseListeners();
 
   bool                              m_closeProgress;
   bool                              m_processCanceled;
   nsString                          m_pendingStatus;
   int32_t                           m_pendingStateFlags;
   nsresult                          m_pendingStateValue;
   nsCOMPtr<nsIDOMWindow>            m_dialog;
-  nsCOMPtr<nsISupportsArray>        m_listenerList;
+  nsCOMArray<nsIWebProgressListener>        m_listenerList;
   nsCOMPtr<nsIObserver>             m_observer;
 };
 
 #endif
--- a/extensions/spellcheck/hunspell/src/mozHunspell.cpp
+++ b/extensions/spellcheck/hunspell/src/mozHunspell.cpp
@@ -93,17 +93,17 @@ NS_INTERFACE_MAP_END
 NS_IMPL_CYCLE_COLLECTION_3(mozHunspell,
                            mPersonalDictionary,
                            mEncoder,
                            mDecoder)
 
 // Memory reporting stuff.
 static int64_t gHunspellAllocatedSize = 0;
 
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_ALLOC_FUN(HunspellMallocSizeOfOnAlloc, "hunspell")
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_ALLOC_FUN(HunspellMallocSizeOfOnAlloc)
 NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_FREE_FUN(HunspellMallocSizeOfOnFree)
 
 void HunspellReportMemoryAllocation(void* ptr) {
   gHunspellAllocatedSize += HunspellMallocSizeOfOnAlloc(ptr);
 }
 void HunspellReportMemoryDeallocation(void* ptr) {
   gHunspellAllocatedSize -= HunspellMallocSizeOfOnFree(ptr);
 }
--- a/gfx/gl/Makefile.in
+++ b/gfx/gl/Makefile.in
@@ -8,17 +8,19 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= gl
 LIBRARY_NAME	= gl
 LIBXUL_LIBRARY	= 1
 EXPORT_LIBRARY	= 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS = 1
+endif # !_MSC_VER
 
 EXPORTS	= \
 	GLDefs.h \
 	GLContext.h \
 	GLContextTypes.h \
 	GLContextSymbols.h \
 	GLContextProvider.h \
 	GLContextProviderImpl.h \
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -120,16 +120,20 @@ CompositorParent::StartUpWithExistingThr
   sCompositorLoop = aMsgLoop;
   sCompositorThreadID = aThreadID;
   sMainLoop = MessageLoop::current();
   sCompositorThreadRefCount = 1;
 }
 
 void CompositorParent::StartUp()
 {
+  // Check if compositor started already with StartUpWithExistingThread
+  if (sCompositorThreadID) {
+    return;
+  }
   MOZ_ASSERT(!sCompositorLoop);
   CreateCompositorMap();
   CreateThread();
   sMainLoop = MessageLoop::current();
 }
 
 void CompositorParent::ShutDown()
 {
--- a/gfx/src/Makefile.in
+++ b/gfx/src/Makefile.in
@@ -12,17 +12,19 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE         = gfx
 MODULE_NAME    = nsGfxModule
 LIBRARY_NAME   = gkgfx
 EXPORT_LIBRARY = 1
 GRE_MODULE     = 1
 LIBXUL_LIBRARY = 1
 IS_COMPONENT   = 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS = 1
+endif # !_MSC_VER
 
 XPIDLSRCS = \
 	nsIFontEnumerator.idl \
 	nsIScriptableRegion.idl \
 	$(NULL)
 
 EXPORTS	= \
 	gfxCore.h \
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -41,17 +41,17 @@ GetFreetypeSize()
 NS_MEMORY_REPORTER_IMPLEMENT(Freetype,
     "explicit/freetype",
     KIND_HEAP,
     UNITS_BYTES,
     GetFreetypeSize,
     "Memory used by Freetype."
 )
 
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_ALLOC_FUN(FreetypeMallocSizeOfOnAlloc, "freetype")
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_ALLOC_FUN(FreetypeMallocSizeOfOnAlloc)
 NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_FREE_FUN(FreetypeMallocSizeOfOnFree)
 
 static void*
 CountingAlloc(FT_Memory memory, long size)
 {
     void *p = malloc(size);
     sFreetypeMemoryUsed += FreetypeMallocSizeOfOnAlloc(p);
     return p;
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -1124,17 +1124,17 @@ gfxFontFamily::SizeOfIncludingThis(nsMal
  * Expires unused fonts after a short interval;
  * notifies fonts to age their cached shaped-word records;
  * observes memory-pressure notification and tells fonts to clear their
  * shaped-word caches to free up memory.
  */
 
 NS_IMPL_ISUPPORTS1(gfxFontCache::MemoryReporter, nsIMemoryMultiReporter)
 
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(FontCacheMallocSizeOf, "font-cache")
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(FontCacheMallocSizeOf)
 
 NS_IMETHODIMP
 gfxFontCache::MemoryReporter::GetName(nsACString &aName)
 {
     aName.AssignLiteral("font-cache");
     return NS_OK;
 }
 
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -67,17 +67,17 @@ gfxFontListPrefObserver::Observe(nsISupp
     // but it probably isn't that big a deal.
     gfxPlatformFontList::PlatformFontList()->ClearPrefFonts();
     gfxFontCache::GetCache()->AgeAllGenerations();
     return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS1(gfxPlatformFontList::MemoryReporter, nsIMemoryMultiReporter)
 
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(FontListMallocSizeOf, "font-list")
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(FontListMallocSizeOf)
 
 NS_IMETHODIMP
 gfxPlatformFontList::MemoryReporter::GetName(nsACString &aName)
 {
     aName.AssignLiteral("font-list");
     return NS_OK;
 }
 
--- a/image/build/Makefile.in
+++ b/image/build/Makefile.in
@@ -12,17 +12,19 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE		= imglib2
 LIBRARY_NAME	= imglib2
 EXPORT_LIBRARY = 1
 IS_COMPONENT	= 1
 MODULE_NAME	= nsImageLib2Module
 GRE_MODULE	= 1
 LIBXUL_LIBRARY = 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS = 1
+endif # !_MSC_VER
 
 CPPSRCS = \
 		nsImageModule.cpp \
 		$(NULL)
 
 LOCAL_INCLUDES	= \
 		-I. \
 		-I$(srcdir)/../src \
--- a/image/src/Makefile.in
+++ b/image/src/Makefile.in
@@ -11,17 +11,19 @@ VPATH		= @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= imglib2
 LIBRARY_NAME	= imglib2_s
 FORCE_STATIC_LIB = 1
 MODULE_NAME	= nsImageLib2Module
 GRE_MODULE	= 1
 LIBXUL_LIBRARY  = 1
+ifndef _MSC_VER
 FAIL_ON_WARNINGS = 1
+endif # !_MSC_VER
 
 
 EXPORTS		=  imgLoader.h \
 		   imgRequest.h \
 		   imgRequestProxy.h \
 		   $(NULL)
 
 CPPSRCS		= \
--- a/image/src/imgLoader.cpp
+++ b/image/src/imgLoader.cpp
@@ -59,17 +59,17 @@
 #include "nsIChannelPolicy.h"
 #include "nsILoadContext.h"
 
 #include "nsContentUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::image;
 
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(ImagesMallocSizeOf, "images")
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(ImagesMallocSizeOf)
 
 class imgMemoryReporter MOZ_FINAL :
   public nsIMemoryMultiReporter
 {
 public:
   imgMemoryReporter()
   {
   }
--- a/ipc/chromium/src/base/histogram.cc
+++ b/ipc/chromium/src/base/histogram.cc
@@ -718,35 +718,38 @@ Histogram::SampleSet::~SampleSet() {
 void Histogram::SampleSet::Resize(const Histogram& histogram) {
   counts_.resize(histogram.bucket_count(), 0);
 }
 
 void Histogram::SampleSet::CheckSize(const Histogram& histogram) const {
   DCHECK_EQ(histogram.bucket_count(), counts_.size());
 }
 
-
-void Histogram::SampleSet::AccumulateWithLinearStats(Sample value,
-                                                     Count count,
-                                                     size_t index) {
+void Histogram::SampleSet::Accumulate(Sample value, Count count,
+				      size_t index) {
   DCHECK(count == 1 || count == -1);
   counts_[index] += count;
-  int64_t amount = static_cast<int64_t>(count) * value;
-  sum_ += amount;
-  sum_squares_ += amount * value;
   redundant_count_ += count;
+  sum_ += static_cast<int64_t>(count) * value;
   DCHECK_GE(counts_[index], 0);
   DCHECK_GE(sum_, 0);
   DCHECK_GE(redundant_count_, 0);
 }
 
+void Histogram::SampleSet::AccumulateWithLinearStats(Sample value,
+                                                     Count count,
+                                                     size_t index) {
+  Accumulate(value, count, index);
+  sum_squares_ += static_cast<int64_t>(count) * value * value;
+}
+
 void Histogram::SampleSet::AccumulateWithExponentialStats(Sample value,
                                                           Count count,
                                                           size_t index) {
-  AccumulateWithLinearStats(value, count, index);
+  Accumulate(value, count, index);
   DCHECK_GE(value, 0);
   double value_log = log(static_cast<double>(value) + 1);
   log_sum_ += count * value_log;
   log_sum_squares_ += count * value_log * value_log;
 }
 
 Count Histogram::SampleSet::TotalCount() const {
   Count total = 0;
--- a/ipc/chromium/src/base/histogram.h
+++ b/ipc/chromium/src/base/histogram.h
@@ -369,16 +369,18 @@ class Histogram {
 
     // These fields may or may not be updated at the discretion of the
     // histogram.  We use the natural log and compute ln(sample+1) so that
     // zeros are handled sanely.
     double log_sum_;      // sum of logs of samples.
     double log_sum_squares_; // sum of squares of logs of samples
 
    private:
+    void Accumulate(Sample value, Count count, size_t index);
+
     // Allow tests to corrupt our innards for testing purposes.
     FRIEND_TEST(HistogramTest, CorruptSampleCounts);
 
     // To help identify memory corruption, we reduntantly save the number of
     // samples we've accumulated into all of our buckets.  We can compare this
     // count to the sum of the counts in all buckets, and detect problems.  Note
     // that due to races in histogram accumulation (if a histogram is indeed
     // updated on several threads simultaneously), the tallies might mismatch,
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -321,17 +321,17 @@ JS_ClearAllWatchPoints(JSContext *cx)
             wpmap->clear();
     }
     return true;
 }
 
 /************************************************************************/
 
 JS_PUBLIC_API(unsigned)
-JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
+JS_PCToLineNumber(JSContext *cx, RawScript script, jsbytecode *pc)
 {
     return js::PCToLineNumber(script, pc);
 }
 
 JS_PUBLIC_API(jsbytecode *)
 JS_LineNumberToPC(JSContext *cx, JSScript *script, unsigned lineno)
 {
     return js_LineNumberToPC(script, lineno);
--- a/js/src/jsdbgapi.h
+++ b/js/src/jsdbgapi.h
@@ -136,18 +136,19 @@ JS_ClearWatchPoint(JSContext *cx, JSObje
 extern JS_PUBLIC_API(JSBool)
 JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj);
 
 extern JS_PUBLIC_API(JSBool)
 JS_ClearAllWatchPoints(JSContext *cx);
 
 /************************************************************************/
 
+// RawScript because this needs to be callable from a signal handler
 extern JS_PUBLIC_API(unsigned)
-JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
+JS_PCToLineNumber(JSContext *cx, js::RawScript script, jsbytecode *pc);
 
 extern JS_PUBLIC_API(jsbytecode *)
 JS_LineNumberToPC(JSContext *cx, JSScript *script, unsigned lineno);
 
 extern JS_PUBLIC_API(jsbytecode *)
 JS_EndPC(JSContext *cx, JSScript *script);
 
 extern JS_PUBLIC_API(JSBool)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -679,18 +679,20 @@ class ProfileEntry
 
 JS_FRIEND_API(void)
 SetRuntimeProfilingStack(JSRuntime *rt, ProfileEntry *stack, uint32_t *size,
                          uint32_t max);
 
 JS_FRIEND_API(void)
 EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled);
 
+// Use RawScript rather than UnrootedScript because it may be called from a
+// signal handler
 JS_FRIEND_API(jsbytecode*)
-ProfilingGetPC(JSRuntime *rt, JSScript *script, void *ip);
+ProfilingGetPC(JSRuntime *rt, RawScript script, void *ip);
 
 #ifdef JS_THREADSAFE
 JS_FRIEND_API(void *)
 GetOwnerThread(const JSContext *cx);
 
 JS_FRIEND_API(bool)
 ContextHasOutstandingRequests(const JSContext *cx);
 #endif
--- a/js/src/methodjit/MethodJIT.cpp
+++ b/js/src/methodjit/MethodJIT.cpp
@@ -628,18 +628,20 @@ JS_STATIC_ASSERT(JSFrameReg == JSC::ARMR
 JS_STATIC_ASSERT(JSReturnReg_Type == JSC::ARMRegisters::r5);
 JS_STATIC_ASSERT(JSReturnReg_Data == JSC::ARMRegisters::r4);
 
 #ifdef MOZ_THUMB2
 #define FUNCTION_HEADER_EXTRA \
   ".align 2\n" \
   ".thumb\n" \
   ".thumb_func\n"
+#define BRANCH_AND_LINK(x) "blx " x
 #else
 #define FUNCTION_HEADER_EXTRA
+#define BRANCH_AND_LINK(x) "bl " x
 #endif
 
 asm (
 ".text\n"
 FUNCTION_HEADER_EXTRA
 ".globl " SYMBOL_STRING(JaegerTrampoline)   "\n"
 SYMBOL_STRING(JaegerTrampoline) ":"         "\n"
     /*
@@ -688,32 +690,32 @@ SYMBOL_STRING(JaegerTrampoline) ":"     
 "   sub     sp, sp, #(4*7)"                     "\n"
 
     /* Preserve 'code' (r2) in an arbitrary callee-saved register. */
 "   mov     r4, r2"                             "\n"
     /* Preserve 'fp' (r1) in r10 (JSFrameReg). */
 "   mov     r10, r1"                            "\n"
 
 "   mov     r0, sp"                             "\n"
-"   blx  " SYMBOL_STRING_VMFRAME(PushActiveVMFrame)"\n"
+"   " BRANCH_AND_LINK(SYMBOL_STRING_VMFRAME(PushActiveVMFrame)) "\n"
 
     /* Call the compiled JavaScript function. */
 "   bx     r4"                                  "\n"
 );
 
 asm (
 ".text\n"
 FUNCTION_HEADER_EXTRA
 ".globl " SYMBOL_STRING(JaegerTrampolineReturn)   "\n"
 SYMBOL_STRING(JaegerTrampolineReturn) ":"         "\n"
 "   strd    r4, r5, [r10, #24]"             "\n" /* fp->rval type,data */
 
     /* Tidy up. */
 "   mov     r0, sp"                         "\n"
-"   blx  " SYMBOL_STRING_VMFRAME(PopActiveVMFrame) "\n"
+"   " BRANCH_AND_LINK(SYMBOL_STRING_VMFRAME(PopActiveVMFrame)) "\n"
 
     /* Skip past the parameters we pushed (such as cx and the like). */
 "   add     sp, sp, #(4*7 + 4*6)"           "\n"
 
     /* Set a 'true' return value to indicate successful completion. */
 "   mov     r0, #1"                         "\n"
 "   pop     {r4-r11,pc}"                    "\n"
 );
@@ -722,27 +724,27 @@ asm (
 ".text\n"
 FUNCTION_HEADER_EXTRA
 ".globl " SYMBOL_STRING(JaegerThrowpoline)  "\n"
 SYMBOL_STRING(JaegerThrowpoline) ":"        "\n"
     /* Find the VMFrame pointer for js_InternalThrow. */
 "   mov     r0, sp"                         "\n"
 
     /* Call the utility function that sets up the internal throw routine. */
-"   blx  " SYMBOL_STRING_RELOC(js_InternalThrow) "\n"
+"   " BRANCH_AND_LINK(SYMBOL_STRING_RELOC(js_InternalThrow)) "\n"
 
     /* If js_InternalThrow found a scripted handler, jump to it. Otherwise, tidy
      * up and return. */
 "   cmp     r0, #0"                         "\n"
 "   it      ne"                             "\n"
 "   bxne    r0"                             "\n"
 
     /* Tidy up, then return '0' to represent an unhandled exception. */
 "   mov     r0, sp"                         "\n"
-"   blx  " SYMBOL_STRING_VMFRAME(PopActiveVMFrame) "\n"
+"   " BRANCH_AND_LINK(SYMBOL_STRING_VMFRAME(PopActiveVMFrame)) "\n"
 "   add     sp, sp, #(4*7 + 4*6)"           "\n"
 "   mov     r0, #0"                         "\n"
 "   pop     {r4-r11,pc}"                    "\n"
 );
 
 asm (
 ".text\n"
 FUNCTION_HEADER_EXTRA
@@ -756,26 +758,26 @@ SYMBOL_STRING(JaegerInterpolineScripted)
 
 FUNCTION_HEADER_EXTRA
 ".globl " SYMBOL_STRING(JaegerInterpoline)  "\n"
 SYMBOL_STRING(JaegerInterpoline) ":"        "\n"
 "   mov     r3, sp"                         "\n"    /* f */
 "   mov     r2, r0"                         "\n"    /* returnReg */
 "   mov     r1, r5"                         "\n"    /* returnType */
 "   mov     r0, r4"                         "\n"    /* returnData */
-"   blx  " SYMBOL_STRING_RELOC(js_InternalInterpret) "\n"
+"   " BRANCH_AND_LINK(SYMBOL_STRING_RELOC(js_InternalInterpret)) "\n"
 "   cmp     r0, #0"                         "\n"
 "   ldr     r10, [sp, #(4*7)]"              "\n"    /* Load (StackFrame*)f->regs->fp_ */
 "   ldrd    r4, r5, [r10, #(4*6)]"          "\n"    /* Load rval payload and type. */
 "   ldr     r1, [sp, #(4*3)]"               "\n"    /* Load scratch. */
 "   it      ne"                             "\n"
 "   bxne    r0"                             "\n"
     /* Tidy up, then return 0. */
 "   mov     r0, sp"                         "\n"
-"   blx  " SYMBOL_STRING_VMFRAME(PopActiveVMFrame) "\n"
+"   " BRANCH_AND_LINK(SYMBOL_STRING_VMFRAME(PopActiveVMFrame)) "\n"
 "   add     sp, sp, #(4*7 + 4*6)"           "\n"
 "   mov     r0, #0"                         "\n"
 "   pop     {r4-r11,pc}"                    "\n"
 );
 
 asm (
 ".text\n"
 FUNCTION_HEADER_EXTRA
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -2524,17 +2524,17 @@ sandbox_resolve(JSContext *cx, HandleObj
 {
     jsval v;
     JSBool b, resolved;
 
     if (!JS_GetProperty(cx, obj, "lazy", &v))
         return false;
 
     JS_ValueToBoolean(cx, v, &b);
-    if (b && (flags & JSRESOLVE_ASSIGNING) == 0) {
+    if (b) {
         if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
             return false;
         if (resolved) {
             objp.set(obj);
             return true;
         }
     }
     objp.set(NULL);
@@ -4578,19 +4578,16 @@ env_enumerate(JSContext *cx, HandleObjec
 
 static JSBool
 env_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
             MutableHandleObject objp)
 {
     JSString *valstr;
     const char *name, *value;
 
-    if (flags & JSRESOLVE_ASSIGNING)
-        return true;
-
     IdStringifier idstr(cx, id, true);
     if (idstr.threw())
         return false;
 
     name = idstr.getBytes();
     value = getenv(name);
     if (value) {
         valstr = JS_NewStringCopyZ(cx, value);
--- a/js/src/vm/SPSProfiler.cpp
+++ b/js/src/vm/SPSProfiler.cpp
@@ -218,18 +218,20 @@ JMChunkInfo::JMChunkInfo(mjit::JSActiveF
   : mainStart(frame->mainCodeStart),
     mainEnd(frame->mainCodeEnd),
     stubStart(frame->stubCodeStart),
     stubEnd(frame->stubCodeEnd),
     pcLengths(pcLengths),
     chunk(chunk)
 {}
 
+// Use RawScript instead of UnrootedScript because this may be called from a
+// signal handler
 jsbytecode*
-SPSProfiler::ipToPC(UnrootedScript script, size_t ip)
+SPSProfiler::ipToPC(RawScript script, size_t ip)
 {
     if (!jminfo.initialized())
         return NULL;
 
     JITInfoMap::Ptr ptr = jminfo.lookup(script);
     if (!ptr)
         return NULL;
     JMScriptInfo *info = ptr->value;
--- a/js/src/vm/SPSProfiler.h
+++ b/js/src/vm/SPSProfiler.h
@@ -229,26 +229,26 @@ class SPSProfiler
 
     bool registerMJITCode(mjit::JITChunk *chunk,
                           mjit::JSActiveFrame *outerFrame,
                           mjit::JSActiveFrame **inlineFrames);
     void discardMJITCode(mjit::JITScript *jscr,
                          mjit::JITChunk *chunk, void* address);
     bool registerICCode(mjit::JITChunk *chunk, UnrootedScript script, jsbytecode* pc,
                         void *start, size_t size);
-    jsbytecode *ipToPC(UnrootedScript script, size_t ip);
+    jsbytecode *ipToPC(RawScript script, size_t ip);
 
   private:
     JMChunkInfo *registerScript(mjit::JSActiveFrame *frame,
                                 mjit::PCLengthEntry *lenths,
                                 mjit::JITChunk *chunk);
     void unregisterScript(UnrootedScript script, mjit::JITChunk *chunk);
   public:
 #else
-    jsbytecode *ipToPC(UnrootedScript script, size_t ip) { return NULL; }
+    jsbytecode *ipToPC(RawScript script, size_t ip) { return NULL; }
 #endif
 
     void setProfilingStack(ProfileEntry *stack, uint32_t *size, uint32_t max);
     const char *profileString(JSContext *cx, UnrootedScript script, UnrootedFunction maybeFun);
     void onScriptFinalized(UnrootedScript script);
 
     /* meant to be used for testing, not recommended to call in normal code */
     size_t stringsCount() { return strings.count(); }
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -940,19 +940,16 @@ env_enumerate(JSContext *cx, JSHandleObj
 }
 
 static JSBool
 env_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
             JSMutableHandleObject objp)
 {
     JSString *idstr, *valstr;
 
-    if (flags & JSRESOLVE_ASSIGNING)
-        return true;
-
     jsval idval;
     if (!JS_IdToValue(cx, id, &idval))
         return false;
 
     idstr = JS_ValueToString(cx, idval);
     if (!idstr)
         return false;
     JSAutoByteString name(cx, idstr);
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -4041,17 +4041,17 @@ nsXPCComponents_Utils::ForceGC()
     js::GCForReason(rt, js::gcreason::COMPONENT_UTILS);
     return NS_OK;
 }
 
 /* void forceCC (); */
 NS_IMETHODIMP
 nsXPCComponents_Utils::ForceCC()
 {
-    nsJSContext::CycleCollectNow(nullptr, 0);
+    nsJSContext::CycleCollectNow();
     return NS_OK;
 }
 
 /* void forceShrinkingGC (); */
 NS_IMETHODIMP
 nsXPCComponents_Utils::ForceShrinkingGC()
 {
     JSRuntime* rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1477,17 +1477,17 @@ NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJS
         nsresult rv;                                                          \