Merge m-c to fx-team.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 26 Jul 2013 22:27:22 -0400
changeset 140210 4874fa438b1c9316ae97485a28531959149465a3
parent 140111 db96c1377702f6ad584039f9074979d77dc2fee1 (current diff)
parent 140209 fb48c7d58b8be9ce281d9dc032aaa10d5125efd0 (diff)
child 140212 55ac60d61c0308cb06ea09a0eef4e53ce7cead52
push id1945
push userryanvm@gmail.com
push dateSat, 27 Jul 2013 02:27:26 +0000
treeherderfx-team@4874fa438b1c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone25.0a1
Merge m-c to fx-team.
browser/devtools/webconsole/test/test-bug-595934-canvas.html
browser/devtools/webconsole/test/test-bug-595934-canvas.js
dom/mobilemessage/interfaces/nsIDOMSmsManager.idl
dom/mobilemessage/src/SmsManager.cpp
dom/mobilemessage/src/SmsManager.h
toolkit/themes/linux/mozapps/plugins/pluginDisabled-16.png
toolkit/themes/linux/mozapps/plugins/pluginDisabled.png
toolkit/themes/osx/mozapps/plugins/contentPluginBlocked.png
toolkit/themes/osx/mozapps/plugins/contentPluginClickToPlay.png
toolkit/themes/osx/mozapps/plugins/contentPluginClickToPlayPlain.png
toolkit/themes/osx/mozapps/plugins/contentPluginClose.png
toolkit/themes/osx/mozapps/plugins/contentPluginCrashed.png
toolkit/themes/osx/mozapps/plugins/contentPluginDisabled.png
toolkit/themes/osx/mozapps/plugins/contentPluginDownload.png
toolkit/themes/osx/mozapps/plugins/contentPluginMissing.png
toolkit/themes/osx/mozapps/plugins/pluginDisabled-16.png
toolkit/themes/osx/mozapps/plugins/pluginDisabled.png
toolkit/themes/osx/mozapps/plugins/pluginProblem.css
toolkit/themes/windows/mozapps/plugins/contentPluginBlocked.png
toolkit/themes/windows/mozapps/plugins/contentPluginClickToPlay.png
toolkit/themes/windows/mozapps/plugins/contentPluginClickToPlayPlain.png
toolkit/themes/windows/mozapps/plugins/contentPluginClose.png
toolkit/themes/windows/mozapps/plugins/contentPluginCrashed.png
toolkit/themes/windows/mozapps/plugins/contentPluginDisabled.png
toolkit/themes/windows/mozapps/plugins/contentPluginDownload.png
toolkit/themes/windows/mozapps/plugins/contentPluginMissing.png
toolkit/themes/windows/mozapps/plugins/pluginDisabled-16-aero.png
toolkit/themes/windows/mozapps/plugins/pluginDisabled-16.png
toolkit/themes/windows/mozapps/plugins/pluginDisabled-aero.png
toolkit/themes/windows/mozapps/plugins/pluginDisabled.png
toolkit/themes/windows/mozapps/plugins/pluginProblem.css
xpcom/glue/SSE.cpp
xpcom/glue/SSE.h
xpcom/glue/arm.cpp
xpcom/glue/arm.h
xpcom/tests/ShowSSEConfig.cpp
--- a/accessible/src/base/ARIAMap.cpp
+++ b/accessible/src/base/ARIAMap.cpp
@@ -171,19 +171,20 @@ static nsRoleMapEntry sWAIRoleMaps[] =
   { // grid
     &nsGkAtoms::grid,
     roles::TABLE,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eSelect | eTable,
-    states::FOCUSABLE,
+    kNoReqStates,
     eARIAMultiSelectable,
-    eARIAReadonlyOrEditable
+    eARIAReadonlyOrEditable,
+    eFocusableUntilDisabled
   },
   { // gridcell
     &nsGkAtoms::gridcell,
     roles::GRID_CELL,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
@@ -258,17 +259,18 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     roles::LISTBOX,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eListControl | eSelect,
     kNoReqStates,
     eARIAMultiSelectable,
-    eARIAReadonly
+    eARIAReadonly,
+    eFocusableUntilDisabled
   },
   { // listitem
     &nsGkAtoms::listitem,
     roles::LISTITEM,
     kUseMapRole,
     eNoValue,
     eNoAction, // XXX: should depend on state, parent accessible
     eNoLiveAttr,
@@ -600,29 +602,31 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     roles::OUTLINE,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eSelect,
     kNoReqStates,
     eARIAReadonly,
-    eARIAMultiSelectable
+    eARIAMultiSelectable,
+    eFocusableUntilDisabled
   },
   { // treegrid
     &nsGkAtoms::treegrid,
     roles::TREE_TABLE,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     eSelect | eTable,
     kNoReqStates,
     eARIAReadonly,
-    eARIAMultiSelectable
+    eARIAMultiSelectable,
+    eFocusableUntilDisabled
   },
   { // treeitem
     &nsGkAtoms::treeitem,
     roles::OUTLINEITEM,
     kUseMapRole,
     eNoValue,
     eActivateAction, // XXX: should expose second 'expand/collapse' action based
                      // on states
--- a/accessible/src/base/ARIAStateMap.cpp
+++ b/accessible/src/base/ARIAStateMap.cpp
@@ -1,15 +1,16 @@
 /* -*- 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 "ARIAMap.h"
+#include "nsAccUtils.h"
 #include "States.h"
 
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 using namespace mozilla::a11y::aria;
 
@@ -322,16 +323,26 @@ aria::MapToState(EStateRule aRule, dom::
     {
       if (!aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_valuenow) &&
           !aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_valuetext))
         *aState |= states::MIXED;
 
       return true;
     }
 
+    case eFocusableUntilDisabled:
+    {
+      if (!nsAccUtils::HasDefinedARIAToken(aElement, nsGkAtoms::aria_disabled) ||
+          aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_disabled,
+                                nsGkAtoms::_false, eCaseMatters))
+        *aState |= states::FOCUSABLE;
+
+      return true;
+    }
+
     default:
       return false;
   }
 }
 
 static void
 MapEnumType(dom::Element* aElement, uint64_t* aState, const EnumTypeData& aData)
 {
--- a/accessible/src/base/ARIAStateMap.h
+++ b/accessible/src/base/ARIAStateMap.h
@@ -39,17 +39,18 @@ enum EStateRule
   eARIAPressed,
   eARIAReadonly,
   eARIAReadonlyOrEditable,
   eARIAReadonlyOrEditableIfDefined,
   eARIARequired,
   eARIASelectable,
   eARIASelectableIfDefined,
   eReadonlyUntilEditable,
-  eIndeterminateIfNoValue
+  eIndeterminateIfNoValue,
+  eFocusableUntilDisabled
 };
 
 /**
  * Expose the accessible states for the given element accordingly to state
  * mapping rule.
  *
  * @param  aRule     [in] state mapping rule ID
  * @param  aElement  [in] node of the accessible
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -713,43 +713,29 @@ HyperTextAccessible::GetRelativeOffset(n
     rv = RenderedToContentOffset(frame, aFromOffset, &contentOffset);
     NS_ENSURE_SUCCESS(rv, -1);
   }
 
   nsPeekOffsetStruct pos(aAmount, aDirection, contentOffset,
                          0, kIsJumpLinesOk, kIsScrollViewAStop, kIsKeyboardSelect, kIsVisualBidi,
                          aWordMovementType);
   rv = aFromFrame->PeekOffset(&pos);
-  if (NS_FAILED(rv)) {
-    pos.mResultContent = aFromFrame->GetContent();
-    if (aDirection == eDirPrevious) {
-      // Use passed-in frame as starting point in failure case for now,
-      // this is a hack to deal with starting on a list bullet frame,
-      // which fails in PeekOffset() because the line iterator doesn't see it.
-      // XXX Need to look at our overall handling of list bullets, which are an odd case
-      int32_t endOffsetUnused;
-      aFromFrame->GetOffsets(pos.mContentOffset, endOffsetUnused);
-    }
-    else {
-      // XXX: PeekOffset fails on a last frame in the document for
-      // eSelectLine/eDirNext. DOM selection (up/down arrowing processing) has
-      // similar code to handle this case. One day it should be incorporated
-      // into PeekOffset.
-      int32_t startOffsetUnused;
-      aFromFrame->GetOffsets(startOffsetUnused, pos.mContentOffset);
-    }
+
+  // PeekOffset fails on last/first lines of the text in certain cases.
+  if (NS_FAILED(rv) && aAmount == eSelectLine) {
+    pos.mAmount = (aDirection == eDirNext) ? eSelectEndLine : eSelectBeginLine;
+    aFromFrame->PeekOffset(&pos);
   }
-
-  // Turn the resulting node and offset into a hyperTextOffset
-  int32_t hyperTextOffset;
   if (!pos.mResultContent)
     return -1;
 
+  // Turn the resulting node and offset into a hyperTextOffset
   // If finalAccessible is nullptr, then DOMPointToHypertextOffset() searched
   // through the hypertext children without finding the node/offset position.
+  int32_t hyperTextOffset;
   Accessible* finalAccessible =
     DOMPointToHypertextOffset(pos.mResultContent, pos.mContentOffset,
                               &hyperTextOffset, aDirection == eDirNext);
 
   if (!finalAccessible && aDirection == eDirPrevious) {
     // If we reached the end during search, this means we didn't find the DOM point
     // and we're actually at the start of the paragraph
     hyperTextOffset = 0;
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -196,16 +196,19 @@ this.AccessFu = {
         this._output(aMessage.json, aMessage.target);
         break;
       case 'AccessFu:Input':
         this.Input.setEditState(aMessage.json);
         break;
       case 'AccessFu:ActivateContextMenu':
         this.Input.activateContextMenu(aMessage.json);
         break;
+      case 'AccessFu:DoScroll':
+        this.Input.doScroll(aMessage.json);
+        break;
     }
   },
 
   _output: function _output(aPresentationData, aBrowser) {
     for each (let presenter in aPresentationData) {
       if (!presenter)
         continue;
 
@@ -235,23 +238,25 @@ this.AccessFu = {
     }
   },
 
   _addMessageListeners: function _addMessageListeners(aMessageManager) {
     aMessageManager.addMessageListener('AccessFu:Present', this);
     aMessageManager.addMessageListener('AccessFu:Input', this);
     aMessageManager.addMessageListener('AccessFu:Ready', this);
     aMessageManager.addMessageListener('AccessFu:ActivateContextMenu', this);
+    aMessageManager.addMessageListener('AccessFu:DoScroll', this);
   },
 
   _removeMessageListeners: function _removeMessageListeners(aMessageManager) {
     aMessageManager.removeMessageListener('AccessFu:Present', this);
     aMessageManager.removeMessageListener('AccessFu:Input', this);
     aMessageManager.removeMessageListener('AccessFu:Ready', this);
     aMessageManager.removeMessageListener('AccessFu:ActivateContextMenu', this);
+    aMessageManager.removeMessageListener('AccessFu:DoScroll', this);
   },
 
   _handleMessageManager: function _handleMessageManager(aMessageManager) {
     if (this._enabled) {
       this._addMessageListeners(aMessageManager);
     }
     this._loadFrameScript(aMessageManager);
   },
@@ -663,26 +668,26 @@ var Input = {
         break;
       case 'swiperight1':
         this.moveCursor('moveNext', 'Simple', 'gestures');
         break;
       case 'swipeleft1':
         this.moveCursor('movePrevious', 'Simple', 'gesture');
         break;
       case 'swiperight2':
-        this.scroll(-1, true);
+        this.sendScrollMessage(-1, true);
         break;
       case 'swipedown2':
-        this.scroll(-1);
+        this.sendScrollMessage(-1);
         break;
       case 'swipeleft2':
-        this.scroll(1, true);
+        this.sendScrollMessage(1, true);
         break;
       case 'swipeup2':
-        this.scroll(1);
+        this.sendScrollMessage(1);
         break;
       case 'explore2':
         Utils.CurrentBrowser.contentWindow.scrollBy(
           -aGesture.deltaX, -aGesture.deltaY);
         break;
       case 'swiperight3':
         this.moveCursor('moveNext', this.quickNavMode.current, 'gesture');
         break;
@@ -815,34 +820,52 @@ var Input = {
     mm.sendAsyncMessage('AccessFu:Activate', {offset: offset});
   },
 
   sendContextMenuMessage: function sendContextMenuMessage() {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
     mm.sendAsyncMessage('AccessFu:ContextMenu', {});
   },
 
-  activateContextMenu: function activateContextMenu(aMessage) {
+  activateContextMenu: function activateContextMenu(aDetails) {
     if (Utils.MozBuildApp === 'mobile/android') {
-      let p = AccessFu.adjustContentBounds(aMessage.bounds, Utils.CurrentBrowser,
+      let p = AccessFu.adjustContentBounds(aDetails.bounds, Utils.CurrentBrowser,
                                            true, true).center();
       Services.obs.notifyObservers(null, 'Gesture:LongPress',
                                    JSON.stringify({x: p.x, y: p.y}));
     }
   },
 
   setEditState: function setEditState(aEditState) {
     this.editState = aEditState;
   },
 
+  // XXX: This is here for backwards compatability with screen reader simulator
+  // it should be removed when the extension is updated on amo.
   scroll: function scroll(aPage, aHorizontal) {
+    this.sendScrollMessage(aPage, aHorizontal);
+  },
+
+  sendScrollMessage: function sendScrollMessage(aPage, aHorizontal) {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
     mm.sendAsyncMessage('AccessFu:Scroll', {page: aPage, horizontal: aHorizontal, origin: 'top'});
   },
 
+  doScroll: function doScroll(aDetails) {
+    let horizontal = aDetails.horizontal;
+    let page = aDetails.page;
+    let p = AccessFu.adjustContentBounds(aDetails.bounds, Utils.CurrentBrowser,
+                                         true, true).center();
+    let wu = Utils.win.QueryInterface(Ci.nsIInterfaceRequestor).
+      getInterface(Ci.nsIDOMWindowUtils);
+    wu.sendWheelEvent(p.x, p.y,
+                      horizontal ? page : 0, horizontal ? 0 : page, 0,
+                      Utils.win.WheelEvent.DOM_DELTA_PAGE, 0, 0, 0, 0);
+  },
+
   get keyMap() {
     delete this.keyMap;
     this.keyMap = {
       a: ['moveNext', 'Anchor'],
       A: ['movePrevious', 'Anchor'],
       b: ['moveNext', 'Button'],
       B: ['movePrevious', 'Button'],
       c: ['moveNext', 'Combobox'],
--- a/accessible/src/jsat/content-script.js
+++ b/accessible/src/jsat/content-script.js
@@ -301,90 +301,27 @@ function presentCaretChange(aText, aOldO
   if (aOldOffset !== aNewOffset) {
     let msg = Presentation.textSelectionChanged(aText, aNewOffset, aNewOffset,
                                                 aOldOffset, aOldOffset, true);
     sendAsyncMessage('AccessFu:Present', msg);
   }
 }
 
 function scroll(aMessage) {
-  let vc = Utils.getVirtualCursor(content.document);
-
-  function tryToScroll() {
-    let horiz = aMessage.json.horizontal;
-    let page = aMessage.json.page;
-
-    // Search up heirarchy for scrollable element.
-    let acc = vc.position;
-    while (acc) {
-      let elem = acc.DOMNode;
-
-      // This is inspired by IndieUI events. Once they are
-      // implemented, it should be easy to transition to them.
-      // https://dvcs.w3.org/hg/IndieUI/raw-file/tip/src/indie-ui-events.html#scrollrequest
-      let uiactions = elem.getAttribute ? elem.getAttribute('uiactions') : '';
-      if (uiactions && uiactions.split(' ').indexOf('scroll') >= 0) {
-        let evt = elem.ownerDocument.createEvent('CustomEvent');
-        let details = horiz ? { deltaX: page * elem.clientWidth } :
-          { deltaY: page * elem.clientHeight };
-        evt.initCustomEvent(
-          'scrollrequest', true, true,
-          ObjectWrapper.wrap(details, elem.ownerDocument.defaultView));
-        if (!elem.dispatchEvent(evt))
-          return;
-      }
-
-      // We will do window scrolling next.
-      if (elem == content.document)
-        break;
-
-      if (!horiz && elem.clientHeight < elem.scrollHeight) {
-        let s = content.getComputedStyle(elem);
-        if (s.overflowY == 'scroll' || s.overflowY == 'auto') {
-          elem.scrollTop += page * elem.clientHeight;
-          return true;
-        }
-      }
-
-      if (horiz) {
-        if (elem.clientWidth < elem.scrollWidth) {
-          let s = content.getComputedStyle(elem);
-          if (s.overflowX == 'scroll' || s.overflowX == 'auto') {
-            elem.scrollLeft += page * elem.clientWidth;
-            return true;
-          }
-        }
-      }
-      acc = acc.parent;
-    }
-
-    // Scroll window.
-    if (!horiz && content.scrollMaxY &&
-        ((page > 0 && content.scrollY < content.scrollMaxY) ||
-         (page < 0 && content.scrollY > 0))) {
-      content.scroll(0, content.innerHeight * page + content.scrollY);
-      return true;
-    } else if (horiz && content.scrollMaxX &&
-               ((page > 0 && content.scrollX < content.scrollMaxX) ||
-                (page < 0 && content.scrollX > 0))) {
-      content.scroll(content.innerWidth * page + content.scrollX);
-      return true;
-    }
-
-    return false;
+  function sendScrollCoordinates(aAccessible) {
+    let bounds = Utils.getBounds(aAccessible);
+    sendAsyncMessage('AccessFu:DoScroll',
+                     { bounds: bounds,
+                       page: aMessage.json.page,
+                       horizontal: aMessage.json.horizontal });
   }
 
-  if (aMessage.json.origin != 'child' &&
-      forwardToChild(aMessage, scroll, vc.position)) {
-    return;
-  }
-
-  if (!tryToScroll()) {
-    // Failed to scroll anything in this document. Try in parent document.
-    forwardToParent(aMessage);
+  let position = Utils.getVirtualCursor(content.document).position;
+  if (!forwardToChild(aMessage, scroll, position)) {
+    sendScrollCoordinates(position);
   }
 }
 
 addMessageListener(
   'AccessFu:Start',
   function(m) {
     Logger.debug('AccessFu:Start');
     if (m.json.buildApp)
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -153,28 +153,28 @@ function isObject(aObj, aExpectedObj, aM
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Helpers for getting DOM node/accessible
 
 /**
  * Return the DOM node by identifier (may be accessible, DOM node or ID).
  */
-function getNode(aAccOrNodeOrID)
+function getNode(aAccOrNodeOrID, aDocument)
 {
   if (!aAccOrNodeOrID)
     return null;
 
   if (aAccOrNodeOrID instanceof nsIDOMNode)
     return aAccOrNodeOrID;
 
   if (aAccOrNodeOrID instanceof nsIAccessible)
     return aAccOrNodeOrID.DOMNode;
 
-  node = document.getElementById(aAccOrNodeOrID);
+  node = (aDocument || document).getElementById(aAccOrNodeOrID);
   if (!node) {
     ok(false, "Can't get DOM element for " + aAccOrNodeOrID);
     return null;
   }
 
   return node;
 }
 
--- a/accessible/tests/mochitest/states/test_aria.html
+++ b/accessible/tests/mochitest/states/test_aria.html
@@ -193,16 +193,24 @@
       testStates("aria_vslider", 0, EXT_STATE_VERTICAL, 0, EXT_STATE_HORIZONTAL);
 
       // indeterminate ARIA progressbars (no aria-valuenow or aria-valuetext attribute)
       // should expose mixed state
       testStates("aria_progressbar", STATE_MIXED);
       testStates("aria_progressbar_valuenow", 0, 0, STATE_MIXED);
       testStates("aria_progressbar_valuetext", 0, 0, STATE_MIXED);
 
+      testStates("aria_listbox", STATE_FOCUSABLE);
+      testStates("aria_grid", STATE_FOCUSABLE);
+      testStates("aria_tree", STATE_FOCUSABLE);
+      testStates("aria_treegrid", STATE_FOCUSABLE);
+      testStates("aria_listbox_disabled", 0, 0, STATE_FOCUSABLE);
+      testStates("aria_grid_disabled", 0, 0, STATE_FOCUSABLE);
+      testStates("aria_tree_disabled", 0, 0, STATE_FOCUSABLE);
+      testStates("aria_treegrid_disabled", 0, 0, STATE_FOCUSABLE);
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 
 </head>
@@ -215,60 +223,66 @@
     Mozilla Bug 457219
   </a><br />
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=429285"
      title="Propagate aria-disabled to descendants">
     Mozilla Bug 429285
   </a>
   <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=457226"
+     title="Mochitests for ARIA states">
+    Mozilla Bug 457226
+  </a>
+  <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=499653"
      title="Unify ARIA state attributes mapping rules">
     Mozilla Bug 499653
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=681674"
      title="aria-autocomplete not supported on standard form text input controls">
     Mozilla Bug 681674
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=681674"
      title="aria-orientation should be applied to separator and slider roles">
     Mozilla Bug 681674
   </a>
   <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=689847"
+     title="Expose active state on current item of selectable widgets">
+    Mozilla Bug 689847
+  </a>
+  <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=699017"
      title="File input control should be propogate states to descendants">
     Mozilla Bug 699017
   </a>
   <a target="_blank"
-     href="https://bugzilla.mozilla.org/show_bug.cgi?id=689847"
-     title="Expose active state on current item of selectable widgets">
-    Mozilla Bug 689847
-  </a>
-  <a target="_blank"
-     href="https://bugzilla.mozilla.org/show_bug.cgi?id=457226"
-     title="Mochitests for ARIA states">
-    Mozilla Bug 457226
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=690199"
+     title="ARIA select widget should expose focusable state regardless the way they manage its children">
+    Mozilla Bug 690199
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=740851"
      title="ARIA undetermined progressmeters should expose mixed state">
     Mozilla Bug 740851
   </a>
   <a target="_blank"
-     href="https://bugzilla.mozilla.org/show_bug.cgi?id=762876
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=762876"
      title="fix default horizontal / vertical state of role=scrollbar and ensure only one of horizontal / vertical states is exposed">
     Mozilla Bug 762876
   </a>
   <a target="_blank"
-     href="https://bugzilla.mozilla.org/show_bug.cgi?id=835121
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=835121"
      title="ARIA grid should be editable by default">
     Mozilla Bug 835121
   </a>
+
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div id="textbox_autocomplete_inline" role="textbox" aria-autocomplete="inline"></div>
   <div id="textbox_autocomplete_list" role="textbox" aria-autocomplete="list"></div>
   <div id="textbox_autocomplete_both" role="textbox" aria-autocomplete="both"></div>
@@ -408,10 +422,44 @@
   <div id="aria_slider" role="slider">slider</div>
   <div id="aria_hslider" role="slider" aria-orientation="horizontal">horizontal slider</div>
   <div id="aria_vslider" role="slider" aria-orientation="vertical">vertical slider</div>
   
   <!-- indeterminate ARIA progressbars should expose mixed state -->
   <div id="aria_progressbar" role="progressbar"></div>
   <div id="aria_progressbar_valuenow" role="progressbar" aria-valuenow="1"></div>
   <div id="aria_progressbar_valuetext" role="progressbar" aria-valuetext="value"></div>
+
+  <!-- ARIA select widget should expose focusable state regardless the way they manage its children -->
+  <div id="aria_listbox" role="listbox">
+    <div role="option" tabindex="0">A</div>
+    <div role="option" tabindex="0">a</div>
+  </div>
+  <div id="aria_grid" role="grid">
+    <div role="row"><div role="gridcell" tabindex="0">B</div></div></div>
+    <div role="row"><div role="gridcell" tabindex="0">b</div></div></div>
+  <div id="aria_tree" role="tree">
+    <div role="treeitem" tabindex="0">C</div>
+    <div role="treeitem" tabindex="0">c</div>
+  </div>
+  <div id="aria_treegrid" role="treegrid">
+    <div role="row"><div role="gridcell" tabindex="0">D</div></div>
+    <div role="row"><div role="gridcell" tabindex="0">d</div></div>
+  </div>
+  <div id="aria_listbox_disabled" role="listbox" aria-disabled="true">
+    <div role="option">E</div>
+    <div role="option">e</div>
+  </div>
+  <div id="aria_grid_disabled" role="grid" aria-disabled="true">
+    <div role="row"><div role="gridcell">F</div></div>
+    <div role="row"><div role="gridcell">f</div></div>
+  </div>
+  <div id="aria_tree_disabled" role="tree" aria-disabled="true">
+    <div role="treeitem">G</div>
+    <div role="treeitem">g</div>
+  </div>
+  <div id="aria_treegrid_disabled" role="treegrid" aria-disabled="true">
+    <div role="row"><div role="gridcell">H</div></div>
+    <div role="row"><div role="gridcell">h</div></div>
+  </div>
+
 </body>
 </html>
--- a/accessible/tests/mochitest/text/test_atcaretoffset.html
+++ b/accessible/tests/mochitest/text/test_atcaretoffset.html
@@ -110,17 +110,17 @@
 
       // __a__w__o__r__d__\n
       //  0  1  2  3  4  5
       // __t__w__o__ (soft line break)
       //  6  7  8  9
       // __w__o__r__d__s
       // 10 11 12 13 14 15
 
-      traverseTextByLines(gQueue, "textarea", 
+      traverseTextByLines(gQueue, "textarea",
                           [ [ "aword", "\n", 0, 5 ],
                             [ "two ", "", 6, 10 ],
                             [ "words", "", 10, 15 ]] );
 
       traverseTextByLines(gQueue, "ta_wrapped", 
                           [ [ "hi ", "", 0, 3 ],
                             [ "hello", "", 3, 8 ],
                             [ " my ", "", 8, 12 ],
--- a/accessible/tests/mochitest/text/test_lineboundary.html
+++ b/accessible/tests/mochitest/text/test_lineboundary.html
@@ -12,17 +12,18 @@
           src="../text.js"></script>
   <script type="application/javascript">
     function doTest()
     {
       //////////////////////////////////////////////////////////////////////////
       // __h__e__l__l__o__ __m__y__ __f__r__i__e__n__d__
       //  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
 
-      var IDs = [ "input", "div", "editable", "textarea" ];
+      var IDs = [ "input", "div", "editable", "textarea",
+                  getNode("ta", getNode("ta_cntr").contentDocument) ];
 
       testTextBeforeOffset(IDs, BOUNDARY_LINE_START,
                            [ [ 0, 15, "", 0, 0 ] ]);
       testTextBeforeOffset(IDs, BOUNDARY_LINE_END,
                            [ [ 0, 15, "", 0, 0 ] ]);
 
       testTextAtOffset(IDs, BOUNDARY_LINE_START,
                        [ [ 0, 15, "hello my friend", 0, 15 ] ]);
@@ -71,16 +72,36 @@
                             [ 8, 8, "two words\n", 9, 19 ],
                             [ 9, 19, "", 19, 19 ]]);
       testTextAfterOffset(IDs, BOUNDARY_LINE_END,
                           [ [ 0, 7, "\n", 7, 8 ],
                             [ 8, 8, "\ntwo words", 8, 18 ],
                             [ 9, 18, "\n", 18, 19 ],
                             [ 19, 19, "", 19, 19 ]]);
 
+      //////////////////////////////////////////////////////////////////////////
+      // a * b (* is embedded char for link)
+      testTextBeforeOffset([ getAccessible("ht_1").firstChild ], BOUNDARY_LINE_START,
+                           [ [ 0, 5, "", 0, 0 ] ]);
+
+      testTextBeforeOffset([ getAccessible("ht_1").firstChild ], BOUNDARY_LINE_END,
+                           [ [ 0, 5, "", 0, 0 ] ]);
+
+      testTextAtOffset([ getAccessible("ht_1").firstChild ], BOUNDARY_LINE_START,
+                       [ [ 0, 5, "a " + kEmbedChar + " c", 0, 5 ] ]);
+
+      testTextAtOffset([ getAccessible("ht_1").firstChild ], BOUNDARY_LINE_END,
+                       [ [ 0, 5, "a " + kEmbedChar + " c", 0, 5 ] ]);
+
+      testTextAfterOffset([ getAccessible("ht_1").firstChild ], BOUNDARY_LINE_START,
+                          [ [ 0, 5, "", 5, 5 ] ]);
+
+      testTextAfterOffset([ getAccessible("ht_1").firstChild ], BOUNDARY_LINE_END,
+                          [ [ 0, 5, "", 5, 5 ] ]);
+                           
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
@@ -105,16 +126,18 @@
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <input id="input" value="hello my friend"/>
   <div id="div">hello my friend</div>
   <div id="editable" contenteditable="true">hello my friend</div>
   <textarea id="textarea">hello my friend</textarea>
+  <iframe id="ta_cntr"
+          src="data:text/html,<html><body><textarea id='ta'>hello my friend</textarea></body></html>"></iframe>
 
   <pre>
     <div id="ml_div">oneword
 
 two words
 </div>
   <div id="ml_divbr">oneword<br/><br/>two words<br/></div>
   <div id="ml_editable" contenteditable="true">oneword
@@ -122,10 +145,12 @@ two words
 two words
 </div>
   <div id="ml_editablebr" contenteditable="true">oneword<br/><br/>two words<br/></div>
   <textarea id="ml_textarea" cols="300">oneword
 
 two words
 </textarea>
   </pre>
+
+  <iframe id="ht_1" src="data:text/html,<html><body>a <a href=''>b</a> c</body></html>"></iframe>
 </body>
 </html>
--- a/b2g/components/TelURIParser.jsm
+++ b/b2g/components/TelURIParser.jsm
@@ -7,28 +7,28 @@
 this.EXPORTED_SYMBOLS = ["TelURIParser"];
 
 /**
  * Singleton providing functionality for parsing tel: and sms: URIs
  */
 this.TelURIParser = {
   parseURI: function(scheme, uri) {
     // https://www.ietf.org/rfc/rfc2806.txt
-    let subscriber = uri.slice((scheme + ':').length);
+    let subscriber = decodeURIComponent(uri.slice((scheme + ':').length));
 
     if (!subscriber.length) {
       return null;
     }
 
     let number = '';
     let pos = 0;
     let len = subscriber.length;
 
     // visual-separator
-    let visualSeparator = [ '-', '.', '(', ')' ];
+    let visualSeparator = [ ' ', '-', '.', '(', ')' ];
     let digits = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ];
     let dtmfDigits = [ '*', '#', 'A', 'B', 'C', 'D' ];
     let pauseCharacter = [ 'p', 'w' ];
 
     // global-phone-number
     if (subscriber[pos] == '+') {
       number += '+';
       for (++pos; pos < len; ++pos) {
--- a/b2g/components/test/unit/test_bug793310.js
+++ b/b2g/components/test/unit/test_bug793310.js
@@ -1,16 +1,19 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function run_test() {
   Components.utils.import("resource:///modules/TelURIParser.jsm")
 
   // global-phone-number
-   do_check_eq(TelURIParser.parseURI('tel', 'tel:+1234'), '+1234');
+  do_check_eq(TelURIParser.parseURI('tel', 'tel:+1234'), '+1234');
+
+  // global-phone-number => white space separator
+  do_check_eq(TelURIParser.parseURI('tel', 'tel:+123 456 789'), '+123 456 789');
 
   // global-phone-number => ignored chars
   do_check_eq(TelURIParser.parseURI('tel', 'tel:+1234_123'), '+1234');
 
   // global-phone-number => visualSeparator + digits
   do_check_eq(TelURIParser.parseURI('tel', 'tel:+-.()1234567890'), '+-.()1234567890');
 
   // local-phone-number
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "72f1b7c657c65389c843dcd032e5bb787f4afafc", 
+    "revision": "f2454e95b24f028b6ebc1b1edb880c12f80454de", 
     "repo_path": "/integration/gaia-central"
 }
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -236,16 +236,19 @@ static int do_main(int argc, char* argv[
       // relaunches Metro Firefox with this command line arg.
       mainFlags = XRE_MAIN_FLAG_USE_METRO;
     } else {
       // This command-line flag is used to test the metro browser in a desktop
       // environment.
       for (int idx = 1; idx < argc; idx++) {
         if (IsArg(argv[idx], "metrodesktop")) {
           metroOnDesktop = true;
+          // Disable crash reporting when running in metrodesktop mode.
+          char crashSwitch[] = "MOZ_CRASHREPORTER_DISABLE=1";
+          putenv(crashSwitch);
           break;
         } 
       }
     }
   }
 #endif
 
   // Desktop browser launch
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -758,16 +758,22 @@ pref("browser.safebrowsing.reportURL", "
 pref("browser.safebrowsing.reportGenericURL", "http://%LOCALE%.phish-generic.mozilla.com/?hl=%LOCALE%");
 pref("browser.safebrowsing.reportErrorURL", "http://%LOCALE%.phish-error.mozilla.com/?hl=%LOCALE%");
 pref("browser.safebrowsing.reportPhishURL", "http://%LOCALE%.phish-report.mozilla.com/?hl=%LOCALE%");
 pref("browser.safebrowsing.reportMalwareURL", "http://%LOCALE%.malware-report.mozilla.com/?hl=%LOCALE%");
 pref("browser.safebrowsing.reportMalwareErrorURL", "http://%LOCALE%.malware-error.mozilla.com/?hl=%LOCALE%");
 
 pref("browser.safebrowsing.warning.infoURL", "https://www.mozilla.org/%LOCALE%/firefox/phishing-protection/");
 pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
+// Since the application reputation query isn't hooked in anywhere yet, this
+// preference does not matter. To be extra safe, don't turn this preference on
+// for official builds without whitelisting (bug 842828).
+#ifndef MOZILLA_OFFICIAL
+pref("browser.safebrowsing.appRepURL", "https://sb-ssl.google.com/safebrowsing/clientreport/download");
+#endif
 
 #ifdef MOZILLA_OFFICIAL
 // Normally the "client ID" sent in updates is appinfo.name, but for
 // official Firefox releases from Mozilla we use a special identifier.
 pref("browser.safebrowsing.id", "navclient-auto-ffox");
 #endif
 
 // Name of the about: page contributed by safebrowsing to handle display of error
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -264,28 +264,28 @@ var gPluginHandler = {
         // plugin. Object tags can, and often do, deal with that themselves,
         // so don't stomp on the page developers toes.
         if (installable && !(plugin instanceof HTMLObjectElement)) {
           let installStatus = doc.getAnonymousElementByAttribute(plugin, "class", "installStatus");
           installStatus.setAttribute("installable", "true");
           let iconStatus = doc.getAnonymousElementByAttribute(plugin, "class", "icon");
           iconStatus.setAttribute("installable", "true");
 
-          let installLink = doc.getAnonymousElementByAttribute(plugin, "class", "installPluginLink");
+          let installLink = doc.getAnonymousElementByAttribute(plugin, "anonid", "installPluginLink");
           this.addLinkClickCallback(installLink, "installSinglePlugin", plugin);
         }
         break;
 
       case "PluginBlocklisted":
       case "PluginOutdated":
         shouldShowNotification = true;
         break;
 
       case "PluginVulnerableUpdatable":
-        let updateLink = doc.getAnonymousElementByAttribute(plugin, "class", "checkForUpdatesLink");
+        let updateLink = doc.getAnonymousElementByAttribute(plugin, "anonid", "checkForUpdatesLink");
         this.addLinkClickCallback(updateLink, "openPluginUpdatePage");
         /* FALLTHRU */
 
       case "PluginVulnerableNoUpdate":
       case "PluginClickToPlay":
         this._handleClickToPlayEvent(plugin);
         let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
         let pluginName = this._getPluginInfo(plugin).pluginName;
@@ -301,17 +301,17 @@ var gPluginHandler = {
         shouldShowNotification = true;
         break;
 
       case "PluginPlayPreview":
         this._handlePlayPreviewEvent(plugin);
         break;
 
       case "PluginDisabled":
-        let manageLink = doc.getAnonymousElementByAttribute(plugin, "class", "managePluginsLink");
+        let manageLink = doc.getAnonymousElementByAttribute(plugin, "anonid", "managePluginsLink");
         this.addLinkClickCallback(manageLink, "managePlugins");
         shouldShowNotification = true;
         break;
 
       case "PluginInstantiated":
       case "PluginRemoved":
         shouldShowNotification = true;
         break;
--- a/browser/base/content/test/browser_pluginnotification.js
+++ b/browser/base/content/test/browser_pluginnotification.js
@@ -129,17 +129,17 @@ function test3() {
   ok(!gTestBrowser.missingPlugins, "Test 3, Should not be a missing plugin list");
 
   new TabOpenListener("about:addons", test4, prepareTest5);
 
   var pluginNode = gTestBrowser.contentDocument.getElementById("test");
   ok(pluginNode, "Test 3, Found plugin in page");
   var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
   is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_DISABLED, "Test 3, plugin fallback type should be PLUGIN_DISABLED");
-  var manageLink = gTestBrowser.contentDocument.getAnonymousElementByAttribute(pluginNode, "class", "managePluginsLink");
+  var manageLink = gTestBrowser.contentDocument.getAnonymousElementByAttribute(pluginNode, "anonid", "managePluginsLink");
   ok(manageLink, "Test 3, found 'manage' link in plugin-problem binding");
 
   EventUtils.synthesizeMouseAtCenter(manageLink, {}, gTestBrowser.contentWindow);
 }
 
 function test4(tab, win) {
   is(win.wrappedJSObject.gViewController.currentViewId, "addons://list/plugin", "Test 4, Should have displayed the plugins pane");
   gBrowser.removeTab(tab);
@@ -339,17 +339,17 @@ function test18a() {
   var doc = gTestBrowser.contentDocument;
   var plugin = doc.getElementById("test");
   ok(plugin, "Test 18a, Found plugin in page");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE, "Test 18a, plugin fallback type should be PLUGIN_VULNERABLE_UPDATABLE");
   ok(!objLoadingContent.activated, "Test 18a, Plugin should not be activated");
   var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
   ok(overlay.style.visibility != "hidden", "Test 18a, Plugin overlay should exist, not be hidden");
-  var updateLink = doc.getAnonymousElementByAttribute(plugin, "class", "checkForUpdatesLink");
+  var updateLink = doc.getAnonymousElementByAttribute(plugin, "anonid", "checkForUpdatesLink");
   ok(updateLink.style.visibility != "hidden", "Test 18a, Plugin should have an update link");
 
   var tabOpenListener = new TabOpenListener(Services.urlFormatter.formatURLPref("plugins.update.url"), false, false);
   tabOpenListener.handleEvent = function(event) {
     if (event.type == "TabOpen") {
       gBrowser.tabContainer.removeEventListener("TabOpen", this, false);
       this.tab = event.originalTarget;
       ok(event.target.label == this.url, "Test 18a, Update link should open up the plugin check page");
@@ -382,17 +382,17 @@ function test18c() {
   var doc = gTestBrowser.contentDocument;
   var plugin = doc.getElementById("test");
   ok(plugin, "Test 18c, Found plugin in page");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE, "Test 18c, plugin fallback type should be PLUGIN_VULNERABLE_NO_UPDATE");
   ok(!objLoadingContent.activated, "Test 18c, Plugin should not be activated");
   var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
   ok(overlay.style.visibility != "hidden", "Test 18c, Plugin overlay should exist, not be hidden");
-  var updateLink = doc.getAnonymousElementByAttribute(plugin, "class", "checkForUpdatesLink");
+  var updateLink = doc.getAnonymousElementByAttribute(plugin, "anonid", "checkForUpdatesLink");
   ok(updateLink.style.display != "block", "Test 18c, Plugin should not have an update link");
 
   // check that click "Always allow" works with blocklisted plugins
   clickToPlayNotification.reshow();
   PopupNotifications.panel.firstChild._primaryButton.click();
 
   var condition = function() objLoadingContent.activated;
   waitForCondition(condition, test18d, "Test 18d, Waited too long for plugin to activate");
--- a/browser/devtools/webconsole/test/Makefile.in
+++ b/browser/devtools/webconsole/test/Makefile.in
@@ -112,16 +112,17 @@ MOCHITEST_BROWSER_FILES = \
 	browser_webconsole_bug_737873_mixedcontent.js \
 	browser_output_breaks_after_console_dir_uninspectable.js \
 	browser_console_log_inspectable_object.js \
 	browser_bug_638949_copy_link_location.js \
 	browser_output_longstring_expand.js \
 	browser_netpanel_longstring_expand.js \
 	browser_repeated_messages_accuracy.js \
 	browser_webconsole_bug_821877_csp_errors.js \
+	browser_webconsole_bug_846918_hsts_invalid-headers.js \
 	browser_eval_in_debugger_stackframe.js \
 	browser_console_variables_view.js \
 	browser_console_variables_view_while_debugging.js \
 	browser_console.js \
 	browser_longstring_hang.js \
 	browser_console_consolejsm_output.js \
 	browser_webconsole_bug_837351_securityerrors.js \
 	browser_bug_865871_variables_view_close_on_esc_key.js \
@@ -180,18 +181,16 @@ MOCHITEST_BROWSER_FILES += \
 	test-bug-595934-css-loader.css \
 	test-bug-595934-css-loader.css^headers^ \
 	test-bug-595934-imagemap.html \
 	test-bug-595934-html.html \
 	test-bug-595934-malformedxml.xhtml \
 	test-bug-595934-svg.xhtml \
 	test-bug-595934-workers.html \
 	test-bug-595934-workers.js \
-	test-bug-595934-canvas.html \
-	test-bug-595934-canvas.js \
 	test-bug-595934-css-parser.html \
 	test-bug-595934-css-parser.css \
 	test-bug-595934-canvas-css.html \
 	test-bug-595934-canvas-css.js \
 	test-bug-595934-malformedxml-external.html \
 	test-bug-595934-malformedxml-external.xml \
 	test-bug-595934-empty-getelementbyid.html \
 	test-bug-595934-empty-getelementbyid.js \
@@ -231,16 +230,18 @@ MOCHITEST_BROWSER_FILES += \
 	test-result-format-as-string.html \
 	test-bug-737873-mixedcontent.html \
 	test-repeated-messages.html \
 	test-bug-766001-console-log.js \
 	test-bug-766001-js-console-links.html \
 	test-bug-766001-js-errors.js \
 	test-bug-821877-csperrors.html \
 	test-bug-821877-csperrors.html^headers^ \
+	test-bug-846918-hsts-invalid-headers.html \
+	test-bug-846918-hsts-invalid-headers.html^headers^ \
 	test-eval-in-stackframe.html \
 	test-bug-859170-longstring-hang.html \
 	test-bug-837351-security-errors.html \
 	test-bug-869003-top-window.html \
 	test-bug-869003-iframe.html \
 	test-consoleiframes.html \
 	test-iframe1.html \
 	test-iframe2.html \
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js
@@ -41,41 +41,36 @@ const TESTS = [
     matchString: "no element found",
   },
   { // #5
     file: "test-bug-595934-svg.xhtml",
     category: "SVG",
     matchString: "fooBarSVG",
   },
   { // #6
-    file: "test-bug-595934-canvas.html",
-    category: "Canvas",
-    matchString: "strokeStyle",
-  },
-  { // #7
     file: "test-bug-595934-css-parser.html",
     category: "CSS Parser",
     matchString: "foobarCssParser",
   },
-  { // #8
+  { // #7
     file: "test-bug-595934-malformedxml-external.html",
     category: "malformed-xml",
     matchString: "</html>",
   },
-  { // #9
+  { // #8
     file: "test-bug-595934-empty-getelementbyid.html",
     category: "DOM",
     matchString: "getElementById",
   },
-  { // #10
+  { // #9
     file: "test-bug-595934-canvas-css.html",
     category: "CSS Parser",
     matchString: "foobarCanvasCssParser",
   },
-  { // #11
+  { // #10
     file: "test-bug-595934-image.html",
     category: "Image",
     matchString: "corrupt",
   },
 ];
 
 let pos = -1;
 
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_846918_hsts_invalid-headers.js
@@ -0,0 +1,27 @@
+ /* Any copyright is dedicated to the Public Domain.
+  * http://creativecommons.org/publicdomain/zero/1.0/ */
+/* Tests that errors about invalid HSTS security headers are logged
+ *  to the web console */
+const TEST_URI = "https://example.com/browser/browser/devtools/webconsole/test/test-bug-846918-hsts-invalid-headers.html";
+const HSTS_INVALID_HEADER_MSG = "The site specified an invalid Strict-Transport-Security header.";
+
+function test()
+{
+  addTab(TEST_URI);
+  browser.addEventListener("load", function onLoad(aEvent) {
+    browser.removeEventListener(aEvent.type, onLoad, true);
+    openConsole(null, function testHSTSErrorLogged (hud) {
+      waitForMessages({
+        webconsole: hud,
+        messages: [
+          {
+          name: "Invalid HSTS header error displayed successfully",
+          text: HSTS_INVALID_HEADER_MSG,
+          category: CATEGORY_SECURITY,
+          severity: SEVERITY_WARNING
+        },
+        ],
+      }).then(finishTest);
+    });
+  }, true);
+}
deleted file mode 100644
--- a/browser/devtools/webconsole/test/test-bug-595934-canvas.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <title>Web Console test for bug 595934 - category: Canvas</title>
-<!-- Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/ -->
-    <script type="text/javascript"
-      src="test-bug-595934-canvas.js"></script>
-  </head>
-  <body>
-    <p>Web Console test for bug 595934 - category "Canvas".</p>
-    <p><canvas width="200" height="200">Canvas support is required!</canvas></p>
-  </body>
-</html>
deleted file mode 100644
--- a/browser/devtools/webconsole/test/test-bug-595934-canvas.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-window.addEventListener("DOMContentLoaded", function() {
-  var canvas = document.querySelector("canvas");
-  var context = canvas.getContext("2d");
-  context.strokeStyle = document;
-}, false);
-
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-846918-hsts-invalid-headers.html
@@ -0,0 +1,13 @@
+<!doctype html>
+ <html>
+   <head>
+     <meta charset="utf8">
+     <title>Bug 846918 - Report invalid strict-transport-security
+       headers to the web console</title>
+     <!-- Any copyright is dedicated to the Public Domain.
+         http://creativecommons.org/publicdomain/zero/1.0/ -->
+   </head>
+   <body>
+     <p>This page is served with an invalid STS header.</p>
+   </body>
+ </html>
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webconsole/test/test-bug-846918-hsts-invalid-headers.html^headers^
@@ -0,0 +1,1 @@
+Strict-Transport-Security: max-age444
\ No newline at end of file
--- a/browser/devtools/webconsole/webconsole.js
+++ b/browser/devtools/webconsole/webconsole.js
@@ -4416,16 +4416,17 @@ var Utils = {
   {
     switch (aScriptError.category) {
       case "CSS Parser":
       case "CSS Loader":
         return CATEGORY_CSS;
 
       case "Mixed Content Blocker":
       case "CSP":
+      case "Invalid HSTS Headers":
         return CATEGORY_SECURITY;
 
       default:
         return CATEGORY_JS;
     }
   },
 
   /**
--- a/browser/metro/base/content/browser.js
+++ b/browser/metro/base/content/browser.js
@@ -16,16 +16,19 @@ const kSetInactiveStateTimeout = 100;
 
 const kDefaultMetadata = { autoSize: false, allowZoom: true, autoScale: true };
 
 // Override sizeToContent in the main window. It breaks things (bug 565887)
 window.sizeToContent = function() {
   Cu.reportError("window.sizeToContent is not allowed in this window");
 }
 
+/*
+ * Returns the browser for the currently displayed tab.
+ */
 function getBrowser() {
   return Browser.selectedBrowser;
 }
 
 var Browser = {
   _debugEvents: false,
   _tabs: [],
   _selectedTab: null,
@@ -122,21 +125,30 @@ var Browser = {
     window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow = new nsBrowserAccess();
 
     Elements.browsers.addEventListener("DOMUpdatePageReport", PopupBlockerObserver.onUpdatePageReport, false);
 
     // Make sure we're online before attempting to load
     Util.forceOnline();
 
     // If this is an intial window launch the commandline handler passes us the default
-    // page as an argument. commandURL _should_ never be empty, but we protect against it
-    // below. However, we delay trying to get the fallback homepage until we really need it.
+    // page as an argument.
     let commandURL = null;
-    if (window.arguments && window.arguments[0])
-      commandURL = window.arguments[0];
+    try {
+      let argsObj = window.arguments[0].wrappedJSObject;
+      if (argsObj && argsObj.pageloadURL) {
+        // Talos tp-cmdline parameter
+        commandURL = argsObj.pageloadURL;
+      } else if (window.arguments && window.arguments[0]) {
+        // BrowserCLH paramerter
+        commandURL = window.arguments[0];
+      }
+    } catch (ex) {
+      Util.dumpLn(ex);
+    }
 
     messageManager.addMessageListener("DOMLinkAdded", this);
     messageManager.addMessageListener("MozScrolledAreaChanged", this);
     messageManager.addMessageListener("Browser:ViewportMetadata", this);
     messageManager.addMessageListener("Browser:FormSubmit", this);
     messageManager.addMessageListener("Browser:ZoomToPoint:Return", this);
     messageManager.addMessageListener("Browser:CanUnload:Return", this);
     messageManager.addMessageListener("scroll", this);
--- a/browser/metro/theme/browser.css
+++ b/browser/metro/theme/browser.css
@@ -263,27 +263,28 @@ documenttab[selected] .documenttab-selec
 
 /* a 'margin-top' is applied dynamically in ContentAreaObserver */
 #browsers {
   background: white;
   transition-property: margin-top;
   transition-duration: .3s;
   transition-timing-function: ease-in-out;
 }
-
 #browsers browser {
-  transition: padding-bottom @metro_animation_duration@ @metro_animation_easing@;
+  /* unset padding-bottom immediately */
+  transition-duration: 0s;
+  transition-delay:    0s;
+  transition-property: padding-bottom;
 }
-
 #browsers[findbar] browser {
+  /* delay setting padding-bottom until the findbar has transitioned in */
+  transition-delay:    @metro_animation_duration@;
   padding-bottom: @findbar_height@;
 }
-
 /* Selection overlay and monocles */
-
 #page,
 .selection-overlay {
   -moz-stack-sizing: ignore;
 }
 
 .selection-overlay {
   pointer-events: none;
 }
--- a/build/mach_bootstrap.py
+++ b/build/mach_bootstrap.py
@@ -60,16 +60,17 @@ MACH_MODULES = [
     'python/mach/mach/commands/commandinfo.py',
     'python/mozboot/mozboot/mach_commands.py',
     'python/mozbuild/mozbuild/config.py',
     'python/mozbuild/mozbuild/mach_commands.py',
     'python/mozbuild/mozbuild/frontend/mach_commands.py',
     'testing/marionette/mach_commands.py',
     'testing/mochitest/mach_commands.py',
     'testing/xpcshell/mach_commands.py',
+    'testing/talos/mach_commands.py',
     'tools/mach_commands.py',
 ]
 
 
 CATEGORIES = {
     'build': {
         'short': 'Build Commands',
         'long': 'Interact with the build system',
--- a/build/unix/mozconfig.asan
+++ b/build/unix/mozconfig.asan
@@ -15,8 +15,11 @@ ac_add_options --enable-address-sanitize
 
 # Mandatory options required for ASan builds (both on Linux and Mac)
 export MOZ_DEBUG_SYMBOLS=1
 ac_add_options --enable-debug-symbols
 ac_add_options --disable-install-strip
 ac_add_options --disable-jemalloc
 ac_add_options --disable-crashreporter
 ac_add_options --disable-elf-hack
+
+# Avoid dependency on libstdc++ 4.7
+ac_add_options --enable-stdcxx-compat
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -203,16 +203,18 @@
 #include "nsDOMEvent.h"
 #include "nsIContentPermissionPrompt.h"
 #include "mozilla/StaticPtr.h"
 #include "nsITextControlElement.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIEditor.h"
 #include "nsIDOMCSSStyleRule.h"
 #include "mozilla/css/Rule.h"
+#include "nsIHttpChannelInternal.h"
+#include "nsISecurityConsoleMessage.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 typedef nsTArray<Link*> LinkArray;
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gDocumentLeakPRLog;
@@ -2463,16 +2465,33 @@ CSPErrorQueue::Flush(nsIDocument* aDocum
     nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
         "CSP", aDocument,
         nsContentUtils::eSECURITY_PROPERTIES,
         mErrors[i]);
   }
   mErrors.Clear();
 }
 
+void
+nsDocument::SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages)
+{
+  for (uint32_t i = 0; i < aMessages.Length(); ++i) {
+    nsAutoString messageTag;
+    aMessages[i]->GetTag(messageTag);
+
+    nsAutoString category;
+    aMessages[i]->GetCategory(category);
+
+    nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
+                                    NS_ConvertUTF16toUTF8(category).get(),
+                                    this, nsContentUtils::eSECURITY_PROPERTIES,
+                                    NS_ConvertUTF16toUTF8(messageTag).get());
+  }
+}
+
 nsresult
 nsDocument::InitCSP(nsIChannel* aChannel)
 {
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   if (!CSPService::sCSPEnabled) {
 #ifdef PR_LOGGING
     PR_LOG(gCspPRLog, PR_LOG_DEBUG,
            ("CSP is disabled, skipping CSP init for document %p", this));
@@ -4281,18 +4300,26 @@ nsDocument::SetScriptGlobalObject(nsIScr
   }
 
   // Remember the pointer to our window (or lack there of), to avoid
   // having to QI every time it's asked for.
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mScriptGlobalObject);
   mWindow = window;
 
   // Now that we know what our window is, we can flush the CSP errors to the
-  // Web Console.
+  // Web Console. We are flushing all messages that occured and were stored
+  // in the queue prior to this point.
   FlushCSPWebConsoleErrorQueue();
+  nsCOMPtr<nsIHttpChannelInternal> internalChannel =
+    do_QueryInterface(GetChannel());
+  if (internalChannel) {
+    nsCOMArray<nsISecurityConsoleMessage> messages;
+    internalChannel->TakeAllSecurityMessages(messages);
+    SendToConsole(messages);
+  }
 
   // Set our visibility state, but do not fire the event.  This is correct
   // because either we're coming out of bfcache (in which case IsVisible() will
   // still test false at this point and no state change will happen) or we're
   // doing the initial document load and don't want to fire the event for this
   // change.
   mVisibilityState = GetVisibilityState();
 }
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -89,16 +89,17 @@ class nsUnblockOnloadEvent;
 class nsChildContentList;
 class nsHTMLStyleSheet;
 class nsHTMLCSSStyleSheet;
 class nsDOMNavigationTiming;
 class nsWindowSizes;
 class nsHtml5TreeOpExecutor;
 class nsDocumentOnStack;
 class nsPointerLockPermissionRequest;
+class nsISecurityConsoleMessage;
 
 namespace mozilla {
 namespace dom {
 class UndoManager;
 }
 }
 
 /**
@@ -749,16 +750,17 @@ public:
   nsRadioGroupStruct* GetOrCreateRadioGroup(const nsAString& aName);
 
   virtual nsViewportInfo GetViewportInfo(uint32_t aDisplayWidth,
                                          uint32_t aDisplayHeight) MOZ_OVERRIDE;
 
 
 private:
   nsRadioGroupStruct* GetRadioGroupInternal(const nsAString& aName) const;
+  void SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages);
 
 public:
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE_OVERRIDABLE
 
   // nsIDOMDocument
   NS_DECL_NSIDOMDOCUMENT
 
--- a/content/canvas/src/CanvasGradient.h
+++ b/content/canvas/src/CanvasGradient.h
@@ -8,29 +8,24 @@
 #include "mozilla/Attributes.h"
 #include "nsTArray.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 #include "mozilla/dom/CanvasRenderingContext2D.h"
 #include "mozilla/gfx/2D.h"
 #include "nsWrapperCache.h"
 
-#define NS_CANVASGRADIENTAZURE_PRIVATE_IID \
-    {0x28425a6a, 0x90e0, 0x4d42, {0x9c, 0x75, 0xff, 0x60, 0x09, 0xb3, 0x10, 0xa8}}
-
 namespace mozilla {
 namespace dom {
 
-class CanvasGradient : public nsISupports,
-                       public nsWrapperCache
+class CanvasGradient : public nsWrapperCache
 {
 public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASGRADIENTAZURE_PRIVATE_IID)
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CanvasGradient)
+  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CanvasGradient)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CanvasGradient)
 
   enum Type
   {
     LINEAR = 0,
     RADIAL
   };
 
   Type GetType()
--- a/content/canvas/src/CanvasPattern.h
+++ b/content/canvas/src/CanvasPattern.h
@@ -7,34 +7,30 @@
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 #include "mozilla/dom/CanvasRenderingContext2D.h"
 #include "mozilla/RefPtr.h"
 #include "nsISupports.h"
 #include "nsWrapperCache.h"
 
-#define NS_CANVASPATTERNAZURE_PRIVATE_IID \
-    {0xc9bacc25, 0x28da, 0x421e, {0x9a, 0x4b, 0xbb, 0xd6, 0x93, 0x05, 0x12, 0xbc}}
 class nsIPrincipal;
 
 namespace mozilla {
 namespace gfx {
 class SourceSurface;
 }
 
 namespace dom {
 
-class CanvasPattern MOZ_FINAL : public nsISupports,
-                                public nsWrapperCache
+class CanvasPattern MOZ_FINAL : public nsWrapperCache
 {
 public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASPATTERNAZURE_PRIVATE_IID)
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CanvasPattern)
+  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CanvasPattern)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CanvasPattern)
 
   enum RepeatMode
   {
     REPEAT,
     REPEATX,
     REPEATY,
     NOREPEAT
   };
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -87,20 +87,21 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/unused.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsJSUtils.h"
 #include "XPCQuickStubs.h"
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 #include "mozilla/dom/HTMLImageElement.h"
 #include "mozilla/dom/HTMLVideoElement.h"
-#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 #include "mozilla/dom/TextMetrics.h"
+#include "mozilla/dom/UnionTypes.h"
 
 #ifdef USE_SKIA_GPU
 #undef free // apparently defined by some windows header, clashing with a free()
             // method in SkTypes.h
 #include "GLContext.h"
 #include "GLContextProvider.h"
 #include "GLContextSkia.h"
 #include "SurfaceTypes.h"
@@ -395,42 +396,26 @@ CanvasGradient::AddColorStop(float offse
   GradientStop newStop;
 
   newStop.offset = offset;
   newStop.color = Color::FromABGR(color);
 
   mRawStops.AppendElement(newStop);
 }
 
-NS_DEFINE_STATIC_IID_ACCESSOR(CanvasGradient, NS_CANVASGRADIENTAZURE_PRIVATE_IID)
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(CanvasGradient)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(CanvasGradient)
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CanvasGradient, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CanvasGradient, Release)
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(CanvasGradient, mContext)
 
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CanvasGradient)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(mozilla::dom::CanvasGradient)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_DEFINE_STATIC_IID_ACCESSOR(CanvasPattern, NS_CANVASPATTERNAZURE_PRIVATE_IID)
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(CanvasPattern)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(CanvasPattern)
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CanvasPattern, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CanvasPattern, Release)
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(CanvasPattern, mContext)
 
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CanvasPattern)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(mozilla::dom::CanvasPattern)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
 class CanvasRenderingContext2DUserData : public LayerUserData {
 public:
     CanvasRenderingContext2DUserData(CanvasRenderingContext2D *aContext)
     : mContext(aContext)
   {
     aContext->mUserDatas.AppendElement(this);
   }
   ~CanvasRenderingContext2DUserData()
@@ -643,62 +628,42 @@ CanvasRenderingContext2D::Reset()
   // Since the target changes the backing texture will change, and this will
   // no longer be valid.
   mIsEntireFrameInvalid = false;
   mPredictManyRedrawCalls = false;
 
   return NS_OK;
 }
 
-static void
-WarnAboutUnexpectedStyle(HTMLCanvasElement* canvasElement)
-{
-  nsContentUtils::ReportToConsole(
-    nsIScriptError::warningFlag,
-    "Canvas",
-    canvasElement ? canvasElement->OwnerDoc() : nullptr,
-    nsContentUtils::eDOM_PROPERTIES,
-    "UnexpectedCanvasVariantStyle");
-}
-
 void
 CanvasRenderingContext2D::SetStyleFromString(const nsAString& str,
                                              Style whichStyle)
 {
   MOZ_ASSERT(!str.IsVoid());
 
   nscolor color;
   if (!ParseColor(str, &color)) {
     return;
   }
 
   CurrentState().SetColorStyle(whichStyle, color);
 }
 
-nsISupports*
-CanvasRenderingContext2D::GetStyleAsStringOrInterface(nsAString& aStr,
-                                                      CanvasMultiGetterType& aType,
-                                                      Style aWhichStyle)
+void
+CanvasRenderingContext2D::GetStyleAsUnion(StringOrCanvasGradientOrCanvasPatternReturnValue& aValue,
+                                          Style aWhichStyle)
 {
   const ContextState &state = CurrentState();
-  nsISupports* supports;
   if (state.patternStyles[aWhichStyle]) {
-    aStr.SetIsVoid(true);
-    supports = state.patternStyles[aWhichStyle];
-    aType = CMG_STYLE_PATTERN;
+    aValue.SetAsCanvasPattern() = state.patternStyles[aWhichStyle];
   } else if (state.gradientStyles[aWhichStyle]) {
-    aStr.SetIsVoid(true);
-    supports = state.gradientStyles[aWhichStyle];
-    aType = CMG_STYLE_GRADIENT;
+    aValue.SetAsCanvasGradient() = state.gradientStyles[aWhichStyle];
   } else {
-    StyleColorToString(state.colorStyles[aWhichStyle], aStr);
-    supports = nullptr;
-    aType = CMG_STYLE_STRING;
+    StyleColorToString(state.colorStyles[aWhichStyle], aValue.SetAsString());
   }
-  return supports;
 }
 
 // static
 void
 CanvasRenderingContext2D::StyleColorToString(const nscolor& aColor, nsAString& aStr)
 {
   // We can't reuse the normal CSS color stringification code,
   // because the spec calls for a different algorithm for canvas.
@@ -1344,102 +1309,35 @@ CanvasRenderingContext2D::GetMozCurrentT
   return MatrixToJSObject(cx, ctm, error);
 }
 
 //
 // colors
 //
 
 void
-CanvasRenderingContext2D::SetStyleFromJSValue(JSContext* cx,
-                                              JS::Handle<JS::Value> value,
-                                              Style whichStyle)
+CanvasRenderingContext2D::SetStyleFromUnion(const StringOrCanvasGradientOrCanvasPattern& value,
+                                            Style whichStyle)
 {
-  if (value.isString()) {
-    nsDependentJSString strokeStyle;
-    if (strokeStyle.init(cx, value.toString())) {
-      SetStyleFromString(strokeStyle, whichStyle);
-    }
+  if (value.IsString()) {
+    SetStyleFromString(value.GetAsString(), whichStyle);
     return;
   }
 
-  if (value.isObject()) {
-    nsCOMPtr<nsISupports> holder;
-
-    CanvasGradient* gradient;
-    JS::Rooted<JS::Value> rootedVal(cx, value);
-    nsresult rv = xpc_qsUnwrapArg<CanvasGradient>(cx, value, &gradient,
-                                                  static_cast<nsISupports**>(getter_AddRefs(holder)),
-                                                  rootedVal.address());
-    if (NS_SUCCEEDED(rv)) {
-      SetStyleFromGradient(gradient, whichStyle);
-      return;
-    }
-
-    CanvasPattern* pattern;
-    rv = xpc_qsUnwrapArg<CanvasPattern>(cx, value, &pattern,
-                                        static_cast<nsISupports**>(getter_AddRefs(holder)),
-                                        rootedVal.address());
-    if (NS_SUCCEEDED(rv)) {
-      SetStyleFromPattern(pattern, whichStyle);
-      return;
-    }
+  if (value.IsCanvasGradient()) {
+    SetStyleFromGradient(value.GetAsCanvasGradient(), whichStyle);
+    return;
   }
 
-  WarnAboutUnexpectedStyle(mCanvasElement);
-}
-
-static JS::Value
-WrapStyle(JSContext* cx, JSObject* objArg,
-          CanvasRenderingContext2D::CanvasMultiGetterType type,
-          nsAString& str, nsISupports* supports, ErrorResult& error)
-{
-  JS::Rooted<JS::Value> v(cx);
-  bool ok;
-  switch (type) {
-    case CanvasRenderingContext2D::CMG_STYLE_STRING:
-    {
-      ok = xpc::StringToJsval(cx, str, v.address());
-      break;
-    }
-    case CanvasRenderingContext2D::CMG_STYLE_PATTERN:
-    case CanvasRenderingContext2D::CMG_STYLE_GRADIENT:
-    {
-      JS::Rooted<JSObject*> obj(cx, objArg);
-      ok = dom::WrapObject(cx, obj, supports, &v);
-      break;
-    }
-    default:
-      MOZ_CRASH("unexpected CanvasMultiGetterType");
+  if (value.IsCanvasPattern()) {
+    SetStyleFromPattern(value.GetAsCanvasPattern(), whichStyle);
+    return;
   }
-  if (!ok) {
-    error.Throw(NS_ERROR_FAILURE);
-  }
-  return v;
-}
-
-
-JS::Value
-CanvasRenderingContext2D::GetStrokeStyle(JSContext* cx,
-                                         ErrorResult& error)
-{
-  nsString str;
-  CanvasMultiGetterType t;
-  nsISupports* supports = GetStyleAsStringOrInterface(str, t, STYLE_STROKE);
-  return WrapStyle(cx, GetWrapper(), t, str, supports, error);
-}
-
-JS::Value
-CanvasRenderingContext2D::GetFillStyle(JSContext* cx,
-                                       ErrorResult& error)
-{
-  nsString str;
-  CanvasMultiGetterType t;
-  nsISupports* supports = GetStyleAsStringOrInterface(str, t, STYLE_FILL);
-  return WrapStyle(cx, GetWrapper(), t, str, supports, error);
+
+  MOZ_ASSUME_UNREACHABLE("Invalid union value");
 }
 
 void
 CanvasRenderingContext2D::SetFillRule(const nsAString& aString)
 {
   FillRule rule;
 
   if (aString.EqualsLiteral("evenodd"))
--- a/content/canvas/src/CanvasRenderingContext2D.h
+++ b/content/canvas/src/CanvasRenderingContext2D.h
@@ -12,47 +12,49 @@
 #include "mozilla/RefPtr.h"
 #include "nsColor.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
 #include "mozilla/dom/HTMLVideoElement.h"
 #include "CanvasUtils.h"
 #include "gfxFont.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/ImageData.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/CanvasGradient.h"
 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 #include "mozilla/dom/CanvasPattern.h"
 #include "mozilla/gfx/Rect.h"
 
 class nsXULElement;
 
 namespace mozilla {
 namespace gfx {
 class SourceSurface;
 }
 
 namespace dom {
+class HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement;
+class StringOrCanvasGradientOrCanvasPattern;
+class StringOrCanvasGradientOrCanvasPatternReturnValue;
 class TextMetrics;
 
 extern const mozilla::gfx::Float SIGMA_MAX;
 
 template<typename T> class Optional;
 
 struct CanvasBidiProcessor;
 class CanvasRenderingContext2DUserData;
 
 /**
  ** CanvasRenderingContext2D
  **/
 class CanvasRenderingContext2D :
   public nsICanvasRenderingContextInternal,
   public nsWrapperCache
 {
-typedef mozilla::dom::HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement
+typedef HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement
   HTMLImageOrCanvasOrVideoElement;
 
 public:
   CanvasRenderingContext2D();
   virtual ~CanvasRenderingContext2D();
 
   virtual JSObject* WrapObject(JSContext *cx,
                                JS::Handle<JSObject*> scope) MOZ_OVERRIDE;
@@ -86,28 +88,35 @@ public:
     if (globalAlpha >= 0.0 && globalAlpha <= 1.0) {
       CurrentState().globalAlpha = ToFloat(globalAlpha);
     }
   }
 
   void GetGlobalCompositeOperation(nsAString& op, mozilla::ErrorResult& error);
   void SetGlobalCompositeOperation(const nsAString& op,
                                    mozilla::ErrorResult& error);
-  JS::Value GetStrokeStyle(JSContext* cx, mozilla::ErrorResult& error);
 
-  void SetStrokeStyle(JSContext* cx, JS::Handle<JS::Value> value)
+  void GetStrokeStyle(StringOrCanvasGradientOrCanvasPatternReturnValue& value)
   {
-    SetStyleFromJSValue(cx, value, STYLE_STROKE);
+    GetStyleAsUnion(value, STYLE_STROKE);
   }
 
-  JS::Value GetFillStyle(JSContext* cx, mozilla::ErrorResult& error);
+  void SetStrokeStyle(const StringOrCanvasGradientOrCanvasPattern& value)
+  {
+    SetStyleFromUnion(value, STYLE_STROKE);
+  }
 
-  void SetFillStyle(JSContext* cx, JS::Handle<JS::Value> value)
+  void GetFillStyle(StringOrCanvasGradientOrCanvasPatternReturnValue& value)
   {
-    SetStyleFromJSValue(cx, value, STYLE_FILL);
+    GetStyleAsUnion(value, STYLE_FILL);
+  }
+
+  void SetFillStyle(const StringOrCanvasGradientOrCanvasPattern& value)
+  {
+    SetStyleFromUnion(value, STYLE_FILL);
   }
 
   already_AddRefed<CanvasGradient>
     CreateLinearGradient(double x0, double y0, double x1, double y1);
   already_AddRefed<CanvasGradient>
     CreateRadialGradient(double x0, double y0, double r0, double x1, double y1,
                          double r1, ErrorResult& aError);
   already_AddRefed<CanvasPattern>
@@ -157,20 +166,20 @@ public:
   void StrokeRect(double x, double y, double w, double h);
   void BeginPath();
   void Fill(const CanvasWindingRule& winding);
   void Stroke();
   void Clip(const CanvasWindingRule& winding);
   bool IsPointInPath(double x, double y, const CanvasWindingRule& winding);
   bool IsPointInStroke(double x, double y);
   void FillText(const nsAString& text, double x, double y,
-                const mozilla::dom::Optional<double>& maxWidth,
+                const Optional<double>& maxWidth,
                 mozilla::ErrorResult& error);
   void StrokeText(const nsAString& text, double x, double y,
-                  const mozilla::dom::Optional<double>& maxWidth,
+                  const Optional<double>& maxWidth,
                   mozilla::ErrorResult& error);
   TextMetrics*
     MeasureText(const nsAString& rawText, mozilla::ErrorResult& error);
 
   void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
                  double dx, double dy, mozilla::ErrorResult& error)
   {
     DrawImage(image, 0.0, 0.0, 0.0, 0.0, dx, dy, 0.0, 0.0, 0, error);
@@ -185,28 +194,28 @@ public:
 
   void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
                  double sx, double sy, double sw, double sh, double dx,
                  double dy, double dw, double dh, mozilla::ErrorResult& error)
   {
     DrawImage(image, sx, sy, sw, sh, dx, dy, dw, dh, 6, error);
   }
 
-  already_AddRefed<mozilla::dom::ImageData>
+  already_AddRefed<ImageData>
     CreateImageData(JSContext* cx, double sw, double sh,
                     mozilla::ErrorResult& error);
-  already_AddRefed<mozilla::dom::ImageData>
-    CreateImageData(JSContext* cx, mozilla::dom::ImageData& imagedata,
+  already_AddRefed<ImageData>
+    CreateImageData(JSContext* cx, ImageData& imagedata,
                     mozilla::ErrorResult& error);
-  already_AddRefed<mozilla::dom::ImageData>
+  already_AddRefed<ImageData>
     GetImageData(JSContext* cx, double sx, double sy, double sw, double sh,
                  mozilla::ErrorResult& error);
-  void PutImageData(mozilla::dom::ImageData& imageData,
+  void PutImageData(ImageData& imageData,
                     double dx, double dy, mozilla::ErrorResult& error);
-  void PutImageData(mozilla::dom::ImageData& imageData,
+  void PutImageData(ImageData& imageData,
                     double dx, double dy, double dirtyX, double dirtyY,
                     double dirtyWidth, double dirtyHeight,
                     mozilla::ErrorResult& error);
 
   double LineWidth()
   {
     return CurrentState().lineWidth;
   }
@@ -266,17 +275,17 @@ public:
       mDSPathBuilder->MoveTo(mTarget->GetTransform() *
                              mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
     }
   }
 
   void LineTo(double x, double y)
   {
     EnsureWritablePath();
-    
+
     LineTo(mozilla::gfx::Point(ToFloat(x), ToFloat(y)));
   }
 
   void QuadraticCurveTo(double cpx, double cpy, double x, double y)
   {
     EnsureWritablePath();
 
     if (mPathBuilder) {
@@ -469,31 +478,32 @@ protected:
   /**
     * Lookup table used to speed up PutImageData().
     */
   static uint8_t (*sPremultiplyTable)[256];
 
   static mozilla::gfx::DrawTarget* sErrorTarget;
 
   // Some helpers.  Doesn't modify a color on failure.
-  void SetStyleFromJSValue(JSContext* cx, JS::Handle<JS::Value> value,
-                           Style whichStyle);
+  void SetStyleFromUnion(const StringOrCanvasGradientOrCanvasPattern& value,
+                         Style whichStyle);
   void SetStyleFromString(const nsAString& str, Style whichStyle);
 
-  void SetStyleFromGradient(CanvasGradient *gradient, Style whichStyle)
+  void SetStyleFromGradient(CanvasGradient& gradient, Style whichStyle)
   {
-    CurrentState().SetGradientStyle(whichStyle, gradient);
+    CurrentState().SetGradientStyle(whichStyle, &gradient);
   }
 
-  void SetStyleFromPattern(CanvasPattern *pattern, Style whichStyle)
+  void SetStyleFromPattern(CanvasPattern& pattern, Style whichStyle)
   {
-    CurrentState().SetPatternStyle(whichStyle, pattern);
+    CurrentState().SetPatternStyle(whichStyle, &pattern);
   }
 
-  nsISupports* GetStyleAsStringOrInterface(nsAString& aStr, CanvasMultiGetterType& aType, Style aWhichStyle);
+  void GetStyleAsUnion(StringOrCanvasGradientOrCanvasPatternReturnValue& aValue,
+                       Style aWhichStyle);
 
   // Returns whether a color was successfully parsed.
   bool ParseColor(const nsAString& aString, nscolor* aColor);
 
   static void StyleColorToString(const nscolor& aColor, nsAString& aStr);
 
   /**
    * Creates the error target, if it doesn't exist
@@ -711,17 +721,17 @@ protected:
 
   /*
     * Implementation of the fillText, strokeText, and measure functions with
     * the operation abstracted to a flag.
     */
   nsresult DrawOrMeasureText(const nsAString& text,
                              float x,
                              float y,
-                             const mozilla::dom::Optional<double>& maxWidth,
+                             const Optional<double>& maxWidth,
                              TextDrawOperation op,
                              float* aWidth);
 
   // state stack handling
   class ContextState {
   public:
     ContextState() : textAlign(TEXT_ALIGN_START),
                      textBaseline(TEXT_BASELINE_ALPHABETIC),
--- a/content/html/content/src/HTMLCanvasElement.cpp
+++ b/content/html/content/src/HTMLCanvasElement.cpp
@@ -8,16 +8,17 @@
 #include "BasicLayers.h"
 #include "imgIEncoder.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "mozilla/Base64.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/CanvasRenderingContext2D.h"
 #include "mozilla/dom/HTMLCanvasElementBinding.h"
+#include "mozilla/dom/UnionTypes.h"
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "nsAsyncDOMEvent.h"
 #include "nsAttrValueInlines.h"
 #include "nsContentUtils.h"
 #include "nsDisplayList.h"
 #include "nsDOMFile.h"
--- a/content/html/content/test/file_iframe_sandbox_d_if8.html
+++ b/content/html/content/test/file_iframe_sandbox_d_if8.html
@@ -1,24 +1,18 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 341604</title>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
+
 <script type="application/javascript">
-function doTest() {
-  if (location.search == "?onreload") {
-    try {
-      window.parent.modify_if_8();
-    } catch (error) {
-      window.parent.postMessage({ok: true, desc: "allow-same-origin is no longer in effect after reload - parent access blocked."}, "*");
-    }
-  } else {
+  function doTest() {
     window.parent.modify_if_8();
   }
-}
 </script>
+
 <body onload="doTest()">
   I am sandboxed with 'allow-scripts' and 'allow-same-origin' the first time I am loaded, and with 'allow-scripts' the second time
 </body>
 </html>
--- a/content/html/content/test/test_bug893537.html
+++ b/content/html/content/test/test_bug893537.html
@@ -10,16 +10,19 @@ https://bugzilla.mozilla.org/show_bug.cg
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=893537">Mozilla Bug 893537</a>
 
 <iframe id="pframe" src="file_bug893537.html"></iframe>
 
 <pre id="test">
 <script>
+  <!-- Bug 895303 -->
+  SimpleTest.expectAssertions(0, 1);
+
   SimpleTest.waitForExplicitFinish();
   var pframe = $("pframe");
   
   var loadState = 1;
   pframe.contentWindow.addEventListener("load", function () {
 
     if (loadState == 1) {
       var iframe = pframe.contentDocument.getElementById("iframe");
--- a/content/html/content/test/test_iframe_sandbox_navigation.html
+++ b/content/html/content/test/test_iframe_sandbox_navigation.html
@@ -38,17 +38,17 @@ function receiveMessage(event) {
 
 // Open windows for tests to attempt to navigate later.
 var windowsToClose = new Array();
 windowsToClose.push(window.open("about:blank", "window_to_navigate"));
 windowsToClose.push(window.open("about:blank", "window_to_navigate2"));
 
 var attemptedTests = 0;
 var passedTests = 0;
-var totalTestsToPass = 8;
+var totalTestsToPass = 7;
 var totalTestsToAttempt = 13;
 
 function ok_wrapper(result, desc, addToAttempted = true) {
   ok(result, desc);
 
   if (result) {
     passedTests++;
   }
@@ -115,17 +115,17 @@ function doTest() {
   // page to file_iframe_sandbox_navigation_fail.html).
 
   // passes if good, fails if bad
   // 5) When a link is clicked in a sandboxed iframe, the document navigated to is sandboxed
   // the same as the original document and is not same origin with parent document
   // (done by file_iframe_sandbox_d_if6.html which simulates a link click and navigates
   // to file_iframe_sandbox_d_if7.html which attempts to call back into its parent).
 
-  // passes if good, fails if bad
+  // fails if bad
   // 6) An iframe (if_8) has sandbox="allow-same-origin allow-scripts", the sandboxed document
   // (file_iframe_sandbox_d_if_8.html) that it contains accesses its parent (this file) and removes
   // 'allow-same-origin' and then triggers a reload.
   // The document should not be able to access its parent (this file).
 
   // fails if bad
   // 7) An iframe (if_9) has sandbox="allow-same-origin allow-scripts", the sandboxed document
   // (file_iframe_sandbox_d_if_9.html) that it contains accesses its parent (this file) and removes
@@ -175,35 +175,36 @@ function doTest() {
 }
 
 addLoadEvent(doTest);
 
 window.modified_if_8 = false;
 
 function reload_if_8() {
   var if_8 = document.getElementById('if_8');
-  if_8.src = 'file_iframe_sandbox_d_if8.html?onreload';
+  if_8.src = 'file_iframe_sandbox_d_if8.html';
 }
 
 function modify_if_8() {
   // If this is the second time this has been called
   // that's a failed test (allow-same-origin was removed
   // the first time).
   if (window.modified_if_8) {
-    ok_wrapper(false, "an sandboxed iframe from which 'allow-same-origin' was removed should not be able to access its parent");
+    ok_wrapper(false, "a sandboxed iframe from which 'allow-same-origin' was removed should not be able to access its parent");
 
     // need to return here since we end up in an infinite loop otherwise
     return;
   }
 
   var if_8 = document.getElementById('if_8');
   window.modified_if_8 = true;
 
   if_8.sandbox = 'allow-scripts';
   sendMouseEvent({type:'click'}, 'a_button');
+  testAttempted();
 }
 
 window.modified_if_9 = false;
 
 function reload_if_9() {
   var if_9 = document.getElementById('if_9');
   if_9.src = 'file_iframe_sandbox_d_if9.html';
 }
--- a/content/media/AudioNodeEngine.cpp
+++ b/content/media/AudioNodeEngine.cpp
@@ -34,16 +34,30 @@ WriteZeroesToAudioBlock(AudioChunk* aChu
   if (aLength == 0)
     return;
   for (uint32_t i = 0; i < aChunk->mChannelData.Length(); ++i) {
     memset(static_cast<float*>(const_cast<void*>(aChunk->mChannelData[i])) + aStart,
            0, aLength*sizeof(float));
   }
 }
 
+void AudioBufferCopyWithScale(const float* aInput,
+                              float aScale,
+                              float* aOutput,
+                              uint32_t aSize)
+{
+  if (aScale == 1.0f) {
+    PodCopy(aOutput, aInput, aSize);
+  } else {
+    for (uint32_t i = 0; i < aSize; ++i) {
+      aOutput[i] = aInput[i]*aScale;
+    }
+  }
+}
+
 void AudioBufferAddWithScale(const float* aInput,
                              float aScale,
                              float* aOutput,
                              uint32_t aSize)
 {
   if (aScale == 1.0f) {
     for (uint32_t i = 0; i < aSize; ++i) {
       aOutput[i] += aInput[i];
--- a/content/media/AudioNodeEngine.h
+++ b/content/media/AudioNodeEngine.h
@@ -83,16 +83,24 @@ private:
 void AllocateAudioBlock(uint32_t aChannelCount, AudioChunk* aChunk);
 
 /**
  * aChunk must have been allocated by AllocateAudioBlock.
  */
 void WriteZeroesToAudioBlock(AudioChunk* aChunk, uint32_t aStart, uint32_t aLength);
 
 /**
+ * Copy with scale. aScale == 1.0f should be optimized.
+ */
+void AudioBufferCopyWithScale(const float* aInput,
+                              float aScale,
+                              float* aOutput,
+                              uint32_t aSize);
+
+/**
  * Pointwise multiply-add operation. aScale == 1.0f should be optimized.
  */
 void AudioBufferAddWithScale(const float* aInput,
                              float aScale,
                              float* aOutput,
                              uint32_t aSize);
 
 /**
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -1,14 +1,15 @@
 /* -*- 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 "MediaStreamGraphImpl.h"
+#include "mozilla/LinkedList.h"
 
 #include "AudioSegment.h"
 #include "VideoSegment.h"
 #include "nsContentUtils.h"
 #include "nsIAppShell.h"
 #include "nsIObserver.h"
 #include "nsServiceManagerUtils.h"
 #include "nsWidgetsCID.h"
@@ -18,16 +19,17 @@
 #include "mozilla/Attributes.h"
 #include "TrackUnionStream.h"
 #include "ImageContainer.h"
 #include "AudioChannelCommon.h"
 #include "AudioNodeEngine.h"
 #include "AudioNodeStream.h"
 #include <algorithm>
 #include "DOMMediaStream.h"
+#include "GeckoProfiler.h"
 
 using namespace mozilla::layers;
 using namespace mozilla::dom;
 
 namespace mozilla {
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* gMediaStreamGraphLog;
@@ -308,30 +310,40 @@ MediaStreamGraphImpl::GetAudioPosition(M
   return aStream->mAudioOutputStreams[0].mAudioPlaybackStartTime +
       TicksToTimeRoundDown(aStream->mAudioOutputStreams[0].mStream->GetRate(),
                            positionInFrames);
 }
 
 void
 MediaStreamGraphImpl::UpdateCurrentTime()
 {
-  GraphTime prevCurrentTime = mCurrentTime;
-  TimeStamp now = TimeStamp::Now();
-  GraphTime nextCurrentTime =
-    SecondsToMediaTime((now - mCurrentTimeStamp).ToSeconds()) + mCurrentTime;
+  GraphTime prevCurrentTime, nextCurrentTime;
+  if (mRealtime) {
+    TimeStamp now = TimeStamp::Now();
+    prevCurrentTime = mCurrentTime;
+    nextCurrentTime =
+      SecondsToMediaTime((now - mCurrentTimeStamp).ToSeconds()) + mCurrentTime;
+
+    mCurrentTimeStamp = now;
+    LOG(PR_LOG_DEBUG+1, ("Updating current time to %f (real %f, mStateComputedTime %f)",
+          MediaTimeToSeconds(nextCurrentTime),
+          (now - mInitialTimeStamp).ToSeconds(),
+          MediaTimeToSeconds(mStateComputedTime)));
+  } else {
+    prevCurrentTime = mCurrentTime;
+    nextCurrentTime = mCurrentTime + MEDIA_GRAPH_TARGET_PERIOD_MS;
+    LOG(PR_LOG_DEBUG+1, ("Updating offline current time to %f (mStateComputedTime %f)",
+          MediaTimeToSeconds(nextCurrentTime),
+          MediaTimeToSeconds(mStateComputedTime)));
+  }
+
   if (mStateComputedTime < nextCurrentTime) {
     LOG(PR_LOG_WARNING, ("Media graph global underrun detected"));
     nextCurrentTime = mStateComputedTime;
   }
-  mCurrentTimeStamp = now;
-
-  LOG(PR_LOG_DEBUG+1, ("Updating current time to %f (real %f, mStateComputedTime %f)",
-                       MediaTimeToSeconds(nextCurrentTime),
-                       (now - mInitialTimeStamp).ToSeconds(),
-                       MediaTimeToSeconds(mStateComputedTime)));
 
   if (prevCurrentTime >= nextCurrentTime) {
     NS_ASSERTION(prevCurrentTime == nextCurrentTime, "Time can't go backwards!");
     // This could happen due to low clock resolution, maybe?
     LOG(PR_LOG_DEBUG, ("Time did not advance"));
     // There's not much left to do here, but the code below that notifies
     // listeners that streams have ended still needs to run.
   }
@@ -449,68 +461,70 @@ MediaStreamGraphImpl::MarkConsumed(Media
   }
   // Mark all the inputs to this stream as consumed
   for (uint32_t i = 0; i < ps->mInputs.Length(); ++i) {
     MarkConsumed(ps->mInputs[i]->mSource);
   }
 }
 
 void
-MediaStreamGraphImpl::UpdateStreamOrderForStream(nsTArray<MediaStream*>* aStack,
+MediaStreamGraphImpl::UpdateStreamOrderForStream(mozilla::LinkedList<MediaStream>* aStack,
                                                  already_AddRefed<MediaStream> aStream)
 {
   nsRefPtr<MediaStream> stream = aStream;
   NS_ASSERTION(!stream->mHasBeenOrdered, "stream should not have already been ordered");
   if (stream->mIsOnOrderingStack) {
-    for (int32_t i = aStack->Length() - 1; ; --i) {
-      aStack->ElementAt(i)->AsProcessedStream()->mInCycle = true;
-      if (aStack->ElementAt(i) == stream)
-        break;
+    MediaStream* iter = aStack->getLast();
+    if (iter) {
+      do {
+        iter->AsProcessedStream()->mInCycle = true;
+        iter = iter->getPrevious();
+      } while (iter && iter != stream);
     }
     return;
   }
   ProcessedMediaStream* ps = stream->AsProcessedStream();
   if (ps) {
-    aStack->AppendElement(stream);
+    aStack->insertBack(stream);
     stream->mIsOnOrderingStack = true;
     for (uint32_t i = 0; i < ps->mInputs.Length(); ++i) {
       MediaStream* source = ps->mInputs[i]->mSource;
       if (!source->mHasBeenOrdered) {
         nsRefPtr<MediaStream> s = source;
         UpdateStreamOrderForStream(aStack, s.forget());
       }
     }
-    aStack->RemoveElementAt(aStack->Length() - 1);
+    aStack->popLast();
     stream->mIsOnOrderingStack = false;
   }
 
   stream->mHasBeenOrdered = true;
   *mStreams.AppendElement() = stream.forget();
 }
 
 void
 MediaStreamGraphImpl::UpdateStreamOrder()
 {
-  nsTArray<nsRefPtr<MediaStream> > oldStreams;
-  oldStreams.SwapElements(mStreams);
-  for (uint32_t i = 0; i < oldStreams.Length(); ++i) {
-    MediaStream* stream = oldStreams[i];
+  mOldStreams.SwapElements(mStreams);
+  mStreams.ClearAndRetainStorage();
+  for (uint32_t i = 0; i < mOldStreams.Length(); ++i) {
+    MediaStream* stream = mOldStreams[i];
     stream->mHasBeenOrdered = false;
     stream->mIsConsumed = false;
     stream->mIsOnOrderingStack = false;
     stream->mInBlockingSet = false;
     ProcessedMediaStream* ps = stream->AsProcessedStream();
     if (ps) {
       ps->mInCycle = false;
     }
   }
 
-  nsAutoTArray<MediaStream*,10> stack;
-  for (uint32_t i = 0; i < oldStreams.Length(); ++i) {
-    nsRefPtr<MediaStream>& s = oldStreams[i];
+  mozilla::LinkedList<MediaStream> stack;
+  for (uint32_t i = 0; i < mOldStreams.Length(); ++i) {
+    nsRefPtr<MediaStream>& s = mOldStreams[i];
     if (!s->mAudioOutputs.IsEmpty() || !s->mVideoOutputs.IsEmpty()) {
       MarkConsumed(s);
     }
     if (!s->mHasBeenOrdered) {
       UpdateStreamOrderForStream(&stack, s.forget());
     }
   }
 }
@@ -883,38 +897,57 @@ MediaStreamGraphImpl::PlayVideo(MediaStr
       NS_NewRunnableMethod(output, &VideoFrameContainer::Invalidate);
     NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
   }
   if (!aStream->mNotifiedFinished) {
     aStream->mLastPlayedVideoFrame = *frame;
   }
 }
 
+bool
+MediaStreamGraphImpl::ShouldUpdateMainThread()
+{
+  if (mRealtime) {
+    return true;
+  }
+
+  TimeStamp now = TimeStamp::Now();
+  if ((now - mLastMainThreadUpdate).ToMilliseconds() > MEDIA_GRAPH_TARGET_PERIOD_MS) {
+    mLastMainThreadUpdate = now;
+    return true;
+  }
+  return false;
+}
+
 void
 MediaStreamGraphImpl::PrepareUpdatesToMainThreadState(bool aFinalUpdate)
 {
   mMonitor.AssertCurrentThreadOwns();
 
-  mStreamUpdates.SetCapacity(mStreamUpdates.Length() + mStreams.Length());
-  for (uint32_t i = 0; i < mStreams.Length(); ++i) {
-    MediaStream* stream = mStreams[i];
-    if (!stream->MainThreadNeedsUpdates()) {
-      continue;
+  // We don't want to update the main thread about timing update when we are not
+  // running in realtime.
+  if (ShouldUpdateMainThread()) {
+    mStreamUpdates.SetCapacity(mStreamUpdates.Length() + mStreams.Length());
+    for (uint32_t i = 0; i < mStreams.Length(); ++i) {
+      MediaStream* stream = mStreams[i];
+      if (!stream->MainThreadNeedsUpdates()) {
+        continue;
+      }
+      StreamUpdate* update = mStreamUpdates.AppendElement();
+      update->mGraphUpdateIndex = stream->mGraphUpdateIndices.GetAt(mCurrentTime);
+      update->mStream = stream;
+      update->mNextMainThreadCurrentTime =
+        GraphTimeToStreamTime(stream, mCurrentTime);
+      update->mNextMainThreadFinished =
+        stream->mFinished &&
+        StreamTimeToGraphTime(stream, stream->GetBufferEnd()) <= mCurrentTime;
     }
-    StreamUpdate* update = mStreamUpdates.AppendElement();
-    update->mGraphUpdateIndex = stream->mGraphUpdateIndices.GetAt(mCurrentTime);
-    update->mStream = stream;
-    update->mNextMainThreadCurrentTime =
-      GraphTimeToStreamTime(stream, mCurrentTime);
-    update->mNextMainThreadFinished =
-      stream->mFinished &&
-      StreamTimeToGraphTime(stream, stream->GetBufferEnd()) <= mCurrentTime;
-  }
-  if (!mPendingUpdateRunnables.IsEmpty()) {
-    mUpdateRunnables.MoveElementsFrom(mPendingUpdateRunnables);
+    if (!mPendingUpdateRunnables.IsEmpty()) {
+      mUpdateRunnables.MoveElementsFrom(mPendingUpdateRunnables);
+    }
   }
 
   // Don't send the message to the main thread if it's not going to have
   // any work to do.
   if (aFinalUpdate ||
       !mUpdateRunnables.IsEmpty() ||
       !mStreamUpdates.IsEmpty()) {
     EnsureStableStateEventPosted();
@@ -1167,16 +1200,17 @@ MediaStreamGraphImpl::RunThread()
       mNeedAnotherIteration = false;
       messageQueue.SwapElements(mMessageQueue);
     }
   }
 
   if (!mRealtime) {
     mNonRealtimeIsRunning = false;
   }
+  profiler_unregister_thread();
 }
 
 void
 MediaStreamGraphImpl::ApplyStreamUpdate(StreamUpdate* aUpdate)
 {
   mMonitor.AssertCurrentThreadOwns();
 
   MediaStream* stream = aUpdate->mStream;
@@ -1212,16 +1246,33 @@ MediaStreamGraphImpl::ForceShutDown()
     MonitorAutoLock lock(mMonitor);
     mForceShutDown = true;
     EnsureImmediateWakeUpLocked(lock);
   }
 }
 
 namespace {
 
+class MediaStreamGraphInitThreadRunnable : public nsRunnable {
+public:
+  explicit MediaStreamGraphInitThreadRunnable(MediaStreamGraphImpl* aGraph)
+    : mGraph(aGraph)
+  {
+  }
+  NS_IMETHOD Run()
+  {
+    char aLocal;
+    profiler_register_thread("MediaStreamGraph", &aLocal);
+    mGraph->RunThread();
+    return NS_OK;
+  }
+private:
+  MediaStreamGraphImpl* mGraph;
+};
+
 class MediaStreamGraphThreadRunnable : public nsRunnable {
 public:
   explicit MediaStreamGraphThreadRunnable(MediaStreamGraphImpl* aGraph)
     : mGraph(aGraph)
   {
   }
   NS_IMETHOD Run()
   {
@@ -1351,17 +1402,17 @@ MediaStreamGraphImpl::RunInStableState()
       NS_DispatchToMainThread(event);
     }
 
     if (mLifecycleState == LIFECYCLE_THREAD_NOT_STARTED) {
       mLifecycleState = LIFECYCLE_RUNNING;
       // Start the thread now. We couldn't start it earlier because
       // the graph might exit immediately on finding it has no streams. The
       // first message for a new graph must create a stream.
-      nsCOMPtr<nsIRunnable> event = new MediaStreamGraphThreadRunnable(this);
+      nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
       NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread), event);
     }
 
     if (mCurrentTaskMessageQueue.IsEmpty()) {
       if (mLifecycleState == LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP && IsEmpty()) {
         // Complete shutdown. First, ensure that this graph is no longer used.
         // A new graph graph will be created if one is needed.
         LOG(PR_LOG_DEBUG, ("Disconnecting MediaStreamGraph %p", this));
@@ -2163,17 +2214,17 @@ MediaStreamGraphImpl::MediaStreamGraphIm
   , mNonRealtimeProcessing(false)
 {
 #ifdef PR_LOGGING
   if (!gMediaStreamGraphLog) {
     gMediaStreamGraphLog = PR_NewLogModule("MediaStreamGraph");
   }
 #endif
 
-  mCurrentTimeStamp = mInitialTimeStamp = TimeStamp::Now();
+  mCurrentTimeStamp = mInitialTimeStamp = mLastMainThreadUpdate = TimeStamp::Now();
 }
 
 NS_IMPL_ISUPPORTS1(MediaStreamGraphShutdownObserver, nsIObserver)
 
 static bool gShutdownObserverRegistered = false;
 
 NS_IMETHODIMP
 MediaStreamGraphShutdownObserver::Observe(nsISupports *aSubject,
--- a/content/media/MediaStreamGraph.h
+++ b/content/media/MediaStreamGraph.h
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_MEDIASTREAMGRAPH_H_
 #define MOZILLA_MEDIASTREAMGRAPH_H_
 
 #include "mozilla/Mutex.h"
+#include "mozilla/LinkedList.h"
 #include "AudioStream.h"
 #include "nsTArray.h"
 #include "nsIRunnable.h"
 #include "nsISupportsImpl.h"
 #include "StreamBuffer.h"
 #include "TimeVarying.h"
 #include "VideoFrameContainer.h"
 #include "VideoSegment.h"
@@ -252,17 +253,17 @@ struct AudioChunk;
  * the DOM wrappers must keep upstream MediaStreams alive as long as they
  * could be being used in the media graph.
  *
  * At any time, however, a set of MediaStream wrappers could be
  * collected via cycle collection. Destroy messages will be sent
  * for those objects in arbitrary order and the MediaStreamGraph has to be able
  * to handle this.
  */
-class MediaStream {
+class MediaStream : public mozilla::LinkedListElement<MediaStream> {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaStream)
 
   MediaStream(DOMMediaStream* aWrapper)
     : mBufferStartTime(0)
     , mExplicitBlockerCount(0)
     , mBlocked(false)
     , mGraphUpdateIndices(0)
--- a/content/media/MediaStreamGraphImpl.h
+++ b/content/media/MediaStreamGraphImpl.h
@@ -10,16 +10,19 @@
 
 #include "mozilla/Monitor.h"
 #include "mozilla/TimeStamp.h"
 #include "nsIThread.h"
 #include "nsIRunnable.h"
 
 namespace mozilla {
 
+template <typename T>
+class LinkedList;
+
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gMediaStreamGraphLog;
 #define LOG(type, msg) PR_LOG(gMediaStreamGraphLog, type, msg)
 #else
 #define LOG(type, msg)
 #endif
 
 /**
@@ -185,16 +188,22 @@ public:
    * See EnsureRunInStableState
    */
   void EnsureStableStateEventPosted();
   /**
    * Generate messages to the main thread to update it for all state changes.
    * mMonitor must be held.
    */
   void PrepareUpdatesToMainThreadState(bool aFinalUpdate);
+  /**
+   * If we are rendering in non-realtime mode, we don't want to send messages to
+   * the main thread at each iteration for performance reasons. We instead
+   * notify the main thread at the same rate
+   */
+  bool ShouldUpdateMainThread();
   // The following methods are the various stages of RunThread processing.
   /**
    * Compute a new current time for the graph and advance all on-graph-thread
    * state to the new current time.
    */
   void UpdateCurrentTime();
   /**
    * Update the consumption state of aStream to reflect whether its data
@@ -210,17 +219,17 @@ public:
   /**
    * Update "have enough data" flags in aStream.
    */
   void UpdateBufferSufficiencyState(SourceMediaStream* aStream);
   /*
    * If aStream hasn't already been ordered, push it onto aStack and order
    * its children.
    */
-  void UpdateStreamOrderForStream(nsTArray<MediaStream*>* aStack,
+  void UpdateStreamOrderForStream(mozilla::LinkedList<MediaStream>* aStack,
                                   already_AddRefed<MediaStream> aStream);
   /**
    * Mark aStream and all its inputs (recursively) as consumed.
    */
   static void MarkConsumed(MediaStream* aStream);
   /**
    * Sort mStreams so that every stream not in a cycle is after any streams
    * it depends on, and every stream in a cycle is marked as being in a cycle.
@@ -366,16 +375,21 @@ public:
   nsCOMPtr<nsIThread> mThread;
 
   // The following state is managed on the graph thread only, unless
   // mLifecycleState > LIFECYCLE_RUNNING in which case the graph thread
   // is not running and this state can be used from the main thread.
 
   nsTArray<nsRefPtr<MediaStream> > mStreams;
   /**
+   * mOldStreams is used as temporary storage for streams when computing the
+   * order in which we compute them.
+   */
+  nsTArray<nsRefPtr<MediaStream> > mOldStreams;
+  /**
    * The current graph time for the current iteration of the RunThread control
    * loop.
    */
   GraphTime mCurrentTime;
   /**
    * Blocking decisions and all stream contents have been computed up to this
    * time. The next batch of updates from the main thread will be processed
    * at this time. Always >= mCurrentTime.
@@ -385,16 +399,20 @@ public:
    * This is only used for logging.
    */
   TimeStamp mInitialTimeStamp;
   /**
    * The real timestamp of the latest run of UpdateCurrentTime.
    */
   TimeStamp mCurrentTimeStamp;
   /**
+   * Date of the last time we updated the main thread with the graph state.
+   */
+  TimeStamp mLastMainThreadUpdate;
+  /**
    * Which update batch we are currently processing.
    */
   int64_t mProcessingGraphUpdateIndex;
   /**
    * Number of active MediaInputPorts
    */
   int32_t mPortCount;
 
--- a/content/media/test/file_access_controls.html
+++ b/content/media/test/file_access_controls.html
@@ -144,17 +144,15 @@ function nextTest() {
     // Will cause load() to be invoked.
   } else {
     gVideo.load();
   }
   gTestNum++;
 }
 
 function done() {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  mediaTestCleanup();
   opener.done();
 }
 
 </script>
 </body>
 </html>
 
--- a/content/media/test/manifest.js
+++ b/content/media/test/manifest.js
@@ -211,17 +211,17 @@ var gInvalidTests = [
   { name:"invalid-cmap-s1c2.opus", type:"audio/ogg; codecs=opus"},
 ];
 
 // Converts a path/filename to a file:// URI which we can load from disk.
 // Optionally checks whether the file actually exists on disk at the location
 // we've specified.
 function fileUriToSrc(path, mustExist) {
   // android mochitest doesn't support file://
-  if (navigator.appVersion.indexOf("Android") != -1)
+  if (navigator.appVersion.indexOf("Android") != -1 || SpecialPowers.Services.appinfo.name == "B2G")
     return path;
 
   const Ci = SpecialPowers.Ci;
   const Cc = SpecialPowers.Cc;
   const Cr = SpecialPowers.Cr;
   var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
                getService(Ci.nsIProperties);
   var f = dirSvc.get("CurWorkD", Ci.nsILocalFile);
@@ -686,30 +686,30 @@ function mediaTestCleanup() {
                                  .classes["@mozilla.org/preferences-service;1"]
                                  .getService(SpecialPowers.Ci.nsIPrefService);
   var branch = prefService.getBranch("media.");
   var oldDefault = 2;
   var oldAuto = 3;
   var oldGStreamer = undefined;
   var oldOpus = undefined;
 
-  try { oldGStreamer = branch.getBoolPref("gstreamer.enabled"); } catch(ex) { }
-  try { oldDefault   = branch.getIntPref("preload.default"); } catch(ex) { }
-  try { oldAuto      = branch.getIntPref("preload.auto"); } catch(ex) { }
-  try { oldOpus      = branch.getBoolPref("opus.enabled"); } catch(ex) { }
+  try { oldGStreamer = SpecialPowers.getBoolPref("media.gstreamer.enabled"); } catch(ex) { }
+  try { oldDefault   = SpecialPowers.getIntPref("media.preload.default"); } catch(ex) { }
+  try { oldAuto      = SpecialPowers.getIntPref("media.preload.auto"); } catch(ex) { }
+  try { oldOpus      = SpecialPowers.getBoolPref("media.opus.enabled"); } catch(ex) { }
 
-  branch.setIntPref("preload.default", 2); // preload_metadata
-  branch.setIntPref("preload.auto", 3); // preload_enough
+  SpecialPowers.setIntPref("media.preload.default", 2); // preload_metadata
+  SpecialPowers.setIntPref("media.preload.auto", 3); // preload_enough
   // test opus playback iff the pref exists
   if (oldOpus !== undefined)
-    branch.setBoolPref("opus.enabled", true);
+    SpecialPowers.setBoolPref("media.opus.enabled", true);
   if (oldGStreamer !== undefined)
-    branch.setBoolPref("gstreamer.enabled", true);
+    SpecialPowers.setBoolPref("media.gstreamer.enabled", true);
 
   window.addEventListener("unload", function() {
     if (oldGStreamer !== undefined)
-      branch.setBoolPref("gstreamer.enabled", oldGStreamer);
-    branch.setIntPref("preload.default", oldDefault);
-    branch.setIntPref("preload.auto", oldAuto);
+      SpecialPowers.setBoolPref("media.gstreamer.enabled", oldGStreamer);
+    SpecialPowers.setIntPref("media.preload.default", oldDefault);
+    SpecialPowers.setIntPref("media.preload.auto", oldAuto);
     if (oldOpus !== undefined)
-      branch.setBoolPref("opus.enabled", oldOpus);
+      SpecialPowers.setBoolPref("media.opus.enabled", oldOpus);
   }, false);
  })();
--- a/content/media/webaudio/blink/Reverb.cpp
+++ b/content/media/webaudio/blink/Reverb.cpp
@@ -75,51 +75,53 @@ static float calculateNormalizationScale
 
     return scale;
 }
 
 Reverb::Reverb(ThreadSharedFloatArrayBufferList* impulseResponse, size_t impulseResponseBufferLength, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads, bool normalize, float sampleRate)
 {
     float scale = 1;
 
+    nsAutoTArray<const float*,4> irChannels;
+    for (size_t i = 0; i < impulseResponse->GetChannels(); ++i) {
+        irChannels.AppendElement(impulseResponse->GetData(i));
+    }
+    nsAutoTArray<float,1024> tempBuf;
+
     if (normalize) {
         scale = calculateNormalizationScale(impulseResponse, impulseResponseBufferLength, sampleRate);
 
         if (scale) {
-            for (uint32_t i = 0; i < impulseResponse->GetChannels(); ++i) {
-                AudioBufferInPlaceScale(const_cast<float*>(impulseResponse->GetData(i)),
-                                        1, scale, impulseResponseBufferLength);
+            tempBuf.SetLength(irChannels.Length()*impulseResponseBufferLength);
+            for (uint32_t i = 0; i < irChannels.Length(); ++i) {
+                float* buf = &tempBuf[i*impulseResponseBufferLength];
+                AudioBufferCopyWithScale(irChannels[i], scale, buf,
+                                         impulseResponseBufferLength);
+                irChannels[i] = buf;
             }
         }
     }
 
-    initialize(impulseResponse, impulseResponseBufferLength, renderSliceSize, maxFFTSize, numberOfChannels, useBackgroundThreads);
-
-    // Undo scaling since this shouldn't be a destructive operation on impulseResponse.
-    // FIXME: What about roundoff? Perhaps consider making a temporary scaled copy
-    // instead of scaling and unscaling in place.
-    if (normalize && scale) {
-        for (uint32_t i = 0; i < impulseResponse->GetChannels(); ++i) {
-            AudioBufferInPlaceScale(const_cast<float*>(impulseResponse->GetData(i)),
-                                    1, 1 / scale, impulseResponseBufferLength);
-        }
-    }
+    initialize(irChannels, impulseResponseBufferLength, renderSliceSize,
+               maxFFTSize, numberOfChannels, useBackgroundThreads);
 }
 
-void Reverb::initialize(ThreadSharedFloatArrayBufferList* impulseResponseBuffer, size_t impulseResponseBufferLength, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads)
+void Reverb::initialize(const nsTArray<const float*>& impulseResponseBuffer,
+                        size_t impulseResponseBufferLength, size_t renderSliceSize,
+                        size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads)
 {
     m_impulseResponseLength = impulseResponseBufferLength;
 
     // The reverb can handle a mono impulse response and still do stereo processing
-    size_t numResponseChannels = impulseResponseBuffer->GetChannels();
+    size_t numResponseChannels = impulseResponseBuffer.Length();
     m_convolvers.SetCapacity(numberOfChannels);
 
     int convolverRenderPhase = 0;
     for (size_t i = 0; i < numResponseChannels; ++i) {
-        const float* channel = impulseResponseBuffer->GetData(i);
+        const float* channel = impulseResponseBuffer[i];
         size_t length = impulseResponseBufferLength;
 
         nsAutoPtr<ReverbConvolver> convolver(new ReverbConvolver(channel, length, renderSliceSize, maxFFTSize, convolverRenderPhase, useBackgroundThreads));
         m_convolvers.AppendElement(convolver.forget());
 
         convolverRenderPhase += renderSliceSize;
     }
 
--- a/content/media/webaudio/blink/Reverb.h
+++ b/content/media/webaudio/blink/Reverb.h
@@ -50,17 +50,17 @@ public:
 
     void process(const mozilla::AudioChunk* sourceBus, mozilla::AudioChunk* destinationBus, size_t framesToProcess);
     void reset();
 
     size_t impulseResponseLength() const { return m_impulseResponseLength; }
     size_t latencyFrames() const;
 
 private:
-    void initialize(mozilla::ThreadSharedFloatArrayBufferList* impulseResponseBuffer, size_t impulseResponseBufferLength, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads);
+    void initialize(const nsTArray<const float*>& impulseResponseBuffer, size_t impulseResponseBufferLength, size_t renderSliceSize, size_t maxFFTSize, size_t numberOfChannels, bool useBackgroundThreads);
 
     size_t m_impulseResponseLength;
 
     nsTArray<nsAutoPtr<ReverbConvolver> > m_convolvers;
 
     // For "True" stereo processing
     mozilla::AudioChunk m_tempBuffer;
 };
--- a/content/media/webaudio/test/test_mediaDecoding.html
+++ b/content/media/webaudio/test/test_mediaDecoding.html
@@ -152,17 +152,17 @@ var tests = [
   {
     url: "small-shot.ogg",
     valid: true,
     expected: "small-shot-expected.wav",
     expectedMono: "small-shot-mono-expected.wav",
     numberOfChannels: 2,
     duration: 0.2760,
     length: 13248,
-    fuzzTolerance: 72,
+    fuzzTolerance: 76,
     fuzzToleranceMobile: 14844
   },
   // A wave file
   //{ url: "24bit-44khz.wav", valid: true, expected: "24bit-44khz-expected.wav" },
   // A non-audio file
   { url: "invalid.txt", valid: false },
   // A webm file with no audio
   { url: "noaudio.webm", valid: false },
new file mode 100644
--- /dev/null
+++ b/content/xbl/crashtests/895805-1.xhtml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:xbl="http://www.mozilla.org/xbl">
+<head>
+<title>Bug 895805 - Adopting bound element to another document.</title>
+<xbl:bindings>
+  <xbl:binding id="crash">
+    <xbl:content>
+      <xbl:children />
+      Bug 895805 dummy binding
+    </xbl:content>
+  </xbl:binding>
+</xbl:bindings>
+<style type="text/css">
+#test {
+  -moz-binding:url(#crash);
+}
+</style>
+</head>
+<body onload="init()">
+<span id="test">Test</span>
+<script>
+function init() {
+  var boundElement = document.getElementById('test');
+  var otherDoc = document.implementation.createDocument('', '', null);
+  otherDoc.adoptNode(boundElement);
+}
+</script>
+</body>
+</html>
--- a/content/xbl/crashtests/crashtests.list
+++ b/content/xbl/crashtests/crashtests.list
@@ -32,8 +32,9 @@ load 472260-1.xhtml
 load 477878-1.html
 load 492978-1.xul
 asserts-if(Android,2) load 493123-1.xhtml
 load 495354-1.xhtml
 load 507628-1.xhtml
 load 507991-1.xhtml
 load set-field-bad-this.xhtml
 load 830614-1.xul
+load 895805-1.xhtml
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -1109,17 +1109,17 @@ nsBindingManager::Traverse(nsIContent *a
     // Don't traverse if content is not in this binding manager.
     // We also don't traverse non-elements because there should not
     // be bindings (checking the flag alone is not sufficient because
     // the flag is also set on children of insertion points that may be
     // non-elements).
     return;
   }
 
-  if (mBoundContentSet.Contains(aContent)) {
+  if (mBoundContentSet.IsInitialized() && mBoundContentSet.Contains(aContent)) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[via binding manager] mBoundContentSet entry");
     cb.NoteXPCOMChild(aContent);
   }
 
   nsISupports *value;
   if (mWrapperTable.ops &&
       (value = LookupObject(mWrapperTable, aContent))) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[via binding manager] mWrapperTable key");
--- a/content/xbl/src/nsXBLProtoImplField.cpp
+++ b/content/xbl/src/nsXBLProtoImplField.cpp
@@ -275,19 +275,17 @@ FieldSetterImpl(JSContext *cx, JS::CallA
   bool installed = false;
   JS::Rooted<JSObject*> callee(cx, js::UncheckedUnwrap(&args.calleev().toObject()));
   JS::Rooted<jsid> id(cx);
   if (!InstallXBLField(cx, callee, thisObj, &id, &installed)) {
     return false;
   }
 
   if (installed) {
-    JS::Rooted<JS::Value> v(cx,
-                            args.length() > 0 ? args[0] : JS::UndefinedValue());
-    if (!::JS_SetPropertyById(cx, thisObj, id, &v)) {
+    if (!::JS_SetPropertyById(cx, thisObj, id, args.get(0))) {
       return false;
     }
   }
   args.rval().setUndefined();
   return true;
 }
 
 static JSBool
--- a/content/xul/templates/src/nsXULTemplateBuilder.cpp
+++ b/content/xul/templates/src/nsXULTemplateBuilder.cpp
@@ -1399,34 +1399,34 @@ nsXULTemplateBuilder::InitHTMLTemplateRo
         // database
         JS::Rooted<JS::Value> jsdatabase(jscontext);
         rv = nsContentUtils::WrapNative(jscontext, scope, mDB,
                                         &NS_GET_IID(nsIRDFCompositeDataSource),
                                         jsdatabase.address(), getter_AddRefs(wrapper));
         NS_ENSURE_SUCCESS(rv, rv);
 
         bool ok;
-        ok = JS_SetProperty(jscontext, jselement, "database", &jsdatabase);
+        ok = JS_SetProperty(jscontext, jselement, "database", jsdatabase);
         NS_ASSERTION(ok, "unable to set database property");
         if (! ok)
             return NS_ERROR_FAILURE;
     }
 
     {
         // builder
         JS::Rooted<JS::Value> jsbuilder(jscontext);
         nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
         rv = nsContentUtils::WrapNative(jscontext, jselement,
                                         static_cast<nsIXULTemplateBuilder*>(this),
                                         &NS_GET_IID(nsIXULTemplateBuilder),
                                         jsbuilder.address(), getter_AddRefs(wrapper));
         NS_ENSURE_SUCCESS(rv, rv);
 
         bool ok;
-        ok = JS_SetProperty(jscontext, jselement, "builder", &jsbuilder);
+        ok = JS_SetProperty(jscontext, jselement, "builder", jsbuilder);
         if (! ok)
             return NS_ERROR_FAILURE;
     }
 
     return NS_OK;
 }
 
 nsresult
--- a/docshell/test/file_bug669671.sjs
+++ b/docshell/test/file_bug669671.sjs
@@ -1,13 +1,14 @@
 function handleRequest(request, response)
 {
   var count = parseInt(getState('count'));
-  if (!count)
+  if (!count || request.queryString == 'countreset')
     count = 0;
+
   setState('count', count + 1 + '');
 
   response.setHeader('Content-Type', 'text/html', false);
   response.setHeader('Cache-Control', 'max-age=0');
   response.write('<html><body onload="opener.onChildLoad()" ' +
                  'onunload="parseInt(\'0\')">' +
                  count + '</body></html>');
 }
--- a/docshell/test/test_bug669671.html
+++ b/docshell/test/test_bug669671.html
@@ -61,16 +61,22 @@ function checkPopupLoadCount()
   var origCount = _loadCount;
   if (popup.document.body.innerHTML >= _loadCount + '')
     _loadCount++;
   return origCount;
 }
 
 function test()
 {
+  // Step 0 - Make sure the count is reset to 0 in case of reload
+  popup.location = 'file_bug669671.sjs?countreset';
+  yield;
+  is(popup.document.body.innerHTML, '0',
+     'Load count should be reset to 0');
+
   // Step 1 - The popup's body counts how many times we've requested the
   // resource.  This is the first time we've requested it, so it should be '0'.
   checkPopupLoadCount();
 
   // Step 2 - We'll get another onChildLoad when this finishes.
   popup.location = 'file_bug669671.sjs';
   yield undefined;
 
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -25,17 +25,16 @@
 #include "nsUnicharUtils.h"
 #include "nsVariant.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "BatteryManager.h"
 #include "PowerManager.h"
 #include "nsIDOMWakeLock.h"
 #include "nsIPowerManagerService.h"
-#include "mozilla/dom/SmsManager.h"
 #include "mozilla/dom/MobileMessageManager.h"
 #include "nsISmsService.h"
 #include "mozilla/Hal.h"
 #include "nsIWebNavigation.h"
 #include "nsISiteSpecificUserAgent.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/StaticPtr.h"
 #include "Connection.h"
@@ -136,17 +135,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlugins)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMimeTypes)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotification)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPowerManager)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSmsManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileMessageManager)
 #ifdef MOZ_B2G_RIL
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTelephony)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVoicemail)
 #endif
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
 #ifdef MOZ_B2G_RIL
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileConnection)
@@ -199,21 +197,16 @@ Navigator::Invalidate()
     mBatteryManager = nullptr;
   }
 
   if (mPowerManager) {
     mPowerManager->Shutdown();
     mPowerManager = nullptr;
   }
 
-  if (mSmsManager) {
-    mSmsManager->Shutdown();
-    mSmsManager = nullptr;
-  }
-
   if (mMobileMessageManager) {
     mMobileMessageManager->Shutdown();
     mMobileMessageManager = nullptr;
   }
 
 #ifdef MOZ_B2G_RIL
   if (mTelephony) {
     mTelephony = nullptr;
@@ -963,20 +956,16 @@ Navigator::GetDeviceStorages(const nsASt
   nsDOMDeviceStorage::CreateDeviceStoragesFor(mWindow, aType, aStores, false);
 
   mDeviceStorageStores.AppendElements(aStores);
 }
 
 Geolocation*
 Navigator::GetGeolocation(ErrorResult& aRv)
 {
-  if (!Preferences::GetBool("geo.enabled", true)) {
-    return nullptr;
-  }
-
   if (mGeolocation) {
     return mGeolocation;
   }
 
   if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
@@ -1109,29 +1098,16 @@ Navigator::RequestWakeLock(const nsAStri
   // from our XPCOM method.
   NS_ENSURE_TRUE(pmService, nullptr);
 
   nsCOMPtr<nsIDOMMozWakeLock> wakelock;
   aRv = pmService->NewWakeLock(aTopic, mWindow, getter_AddRefs(wakelock));
   return wakelock.forget();
 }
 
-nsIDOMMozSmsManager*
-Navigator::GetMozSms()
-{
-  if (!mSmsManager) {
-    NS_ENSURE_TRUE(mWindow, nullptr);
-    NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr);
-
-    mSmsManager = SmsManager::CreateInstance(mWindow);
-  }
-
-  return mSmsManager;
-}
-
 nsIDOMMozMobileMessageManager*
 Navigator::GetMozMobileMessage()
 {
   if (!mMobileMessageManager) {
     // Check that our window has not gone away
     NS_ENSURE_TRUE(mWindow, nullptr);
     NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr);
 
@@ -1612,24 +1588,16 @@ Navigator::HasWakeLockSupport(JSContext*
   nsCOMPtr<nsIPowerManagerService> pmService =
     do_GetService(POWERMANAGERSERVICE_CONTRACTID);
   // No service means no wake lock support
   return !!pmService;
 }
 
 /* static */
 bool
-Navigator::HasSmsSupport(JSContext* /* unused */, JSObject* aGlobal)
-{
-  nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
-  return win && SmsManager::CreationIsAllowed(win);
-}
-
-/* static */
-bool
 Navigator::HasMobileMessageSupport(JSContext* /* unused */, JSObject* aGlobal)
 {
   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
 
 #ifndef MOZ_WEBSMS_BACKEND
   return false;
 #endif
 
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -4,17 +4,16 @@
  * 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_Navigator_h
 #define mozilla_dom_Navigator_h
 
 #include "mozilla/MemoryReporting.h"
 #include "nsIDOMNavigator.h"
-#include "nsIDOMSmsManager.h"
 #include "nsIDOMMobileMessageManager.h"
 #include "nsIMozNavigatorNetwork.h"
 #include "nsAutoPtr.h"
 #include "nsWeakReference.h"
 #include "DeviceStorage.h"
 #include "nsWrapperCache.h"
 
 class nsPluginArray;
@@ -58,17 +57,16 @@ void NS_GetNavigatorAppName(nsAString& a
 namespace mozilla {
 namespace dom {
 
 namespace battery {
 class BatteryManager;
 } // namespace battery
 
 class DesktopNotificationCenter;
-class SmsManager;
 class MobileMessageManager;
 class MozIdleObserver;
 #ifdef MOZ_GAMEPAD
 class Gamepad;
 #endif // MOZ_GAMEPAD
 #ifdef MOZ_MEDIA_NAVIGATOR
 class MozDOMGetUserMediaSuccessCallback;
 class MozDOMGetUserMediaErrorCallback;
@@ -203,17 +201,16 @@ public:
   nsDOMDeviceStorage* GetDeviceStorage(const nsAString& aType,
                                        ErrorResult& aRv);
   void GetDeviceStorages(const nsAString& aType,
                          nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores,
                          ErrorResult& aRv);
   DesktopNotificationCenter* GetMozNotification(ErrorResult& aRv);
   bool MozIsLocallyAvailable(const nsAString& aURI, bool aWhenOffline,
                              ErrorResult& aRv);
-  nsIDOMMozSmsManager* GetMozSms();
   nsIDOMMozMobileMessageManager* GetMozMobileMessage();
   nsIDOMMozConnection* GetMozConnection();
   nsDOMCameraManager* GetMozCameras(ErrorResult& aRv);
   void MozSetMessageHandler(const nsAString& aType,
                             systemMessageCallback* aCallback,
                             ErrorResult& aRv);
   bool MozHasPendingMessage(const nsAString& aType, ErrorResult& aRv);
 #ifdef MOZ_B2G_RIL
@@ -252,17 +249,16 @@ public:
   static bool HasPowerSupport(JSContext* /* unused */, JSObject* aGlobal);
   static bool HasIdleSupport(JSContext* /* unused */, JSObject* aGlobal);
   static bool HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */);
   static bool HasDesktopNotificationSupport(JSContext* /* unused*/,
                                             JSObject* /*unused */)
   {
     return HasDesktopNotificationSupport();
   }
-  static bool HasSmsSupport(JSContext* /* unused */, JSObject* aGlobal);
   static bool HasMobileMessageSupport(JSContext* /* unused */,
                                       JSObject* aGlobal);
   static bool HasCameraSupport(JSContext* /* unused */,
                                JSObject* aGlobal);
 #ifdef MOZ_B2G_RIL
   static bool HasTelephonySupport(JSContext* /* unused */,
                                   JSObject* aGlobal);
   static bool HasMobileConnectionSupport(JSContext* /* unused */,
@@ -301,17 +297,16 @@ private:
   static already_AddRefed<nsPIDOMWindow> GetWindowFromGlobal(JSObject* aGlobal);
 
   nsRefPtr<nsMimeTypeArray> mMimeTypes;
   nsRefPtr<nsPluginArray> mPlugins;
   nsRefPtr<Geolocation> mGeolocation;
   nsRefPtr<DesktopNotificationCenter> mNotification;
   nsRefPtr<battery::BatteryManager> mBatteryManager;
   nsRefPtr<power::PowerManager> mPowerManager;
-  nsRefPtr<SmsManager> mSmsManager;
   nsRefPtr<MobileMessageManager> mMobileMessageManager;
 #ifdef MOZ_B2G_RIL
   nsCOMPtr<nsIDOMTelephony> mTelephony;
   nsCOMPtr<nsIDOMMozVoicemail> mVoicemail;
 #endif
   nsRefPtr<network::Connection> mConnection;
 #ifdef MOZ_B2G_RIL
   nsRefPtr<network::MobileConnection> mMobileConnection;
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -213,17 +213,16 @@ using mozilla::dom::workers::ResolveWork
 #include "nsDOMTouchEvent.h"
 
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/dom/HTMLCollectionBinding.h"
 
 #include "BatteryManager.h"
 #include "nsIDOMPowerManager.h"
 #include "nsIDOMWakeLock.h"
-#include "nsIDOMSmsManager.h"
 #include "nsIDOMMobileMessageManager.h"
 #include "nsIDOMMozSmsMessage.h"
 #include "nsIDOMMozMmsMessage.h"
 #include "nsIDOMSmsFilter.h"
 #include "nsIDOMSmsSegmentInfo.h"
 #include "nsIDOMMozMobileMessageThread.h"
 #include "nsIDOMConnection.h"
 
@@ -572,19 +571,16 @@ static nsDOMClassInfoData sClassInfoData
                            WINDOW_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozPowerManager, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozWakeLock, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(MozSmsManager, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-
   NS_DEFINE_CLASSINFO_DATA(MozMobileMessageManager, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozSmsMessage, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozMmsMessage, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -1436,20 +1432,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(MozPowerManager, nsIDOMMozPowerManager)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozPowerManager)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozWakeLock, nsIDOMMozWakeLock)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozWakeLock)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(MozSmsManager, nsIDOMMozSmsManager)
-     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsManager)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(MozMobileMessageManager, nsIDOMMozMobileMessageManager)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozMobileMessageManager)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozSmsMessage, nsIDOMMozSmsMessage)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsMessage)
   DOM_CLASSINFO_MAP_END
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -90,17 +90,16 @@ DOMCI_CLASS(Blob)
 DOMCI_CLASS(File)
 
 // DOM modal content window class, almost identical to Window
 DOMCI_CLASS(ModalContentWindow)
 
 DOMCI_CLASS(MozPowerManager)
 DOMCI_CLASS(MozWakeLock)
 
-DOMCI_CLASS(MozSmsManager)
 DOMCI_CLASS(MozMobileMessageManager)
 DOMCI_CLASS(MozSmsMessage)
 DOMCI_CLASS(MozMmsMessage)
 DOMCI_CLASS(MozSmsFilter)
 DOMCI_CLASS(MozSmsSegmentInfo)
 DOMCI_CLASS(MozMobileMessageThread)
 
 DOMCI_CLASS(MozConnection)
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -152,20 +152,27 @@ DOMInterfaces = {
     'headerFile': 'BatteryManager.h'
 },
 
 'CameraManager': {
     'nativeType': 'nsDOMCameraManager',
     'headerFile': 'DOMCameraManager.h'
 },
 
+'CanvasGradient' : {
+    'nativeOwnership': 'refcounted'
+},
+
+'CanvasPattern' : {
+    'nativeOwnership': 'refcounted'
+},
+
 'CanvasRenderingContext2D': {
     'implicitJSContext': [
-        'createImageData', 'getImageData', 'strokeStyle',
-        'fillStyle', 'mozDash'
+        'createImageData', 'getImageData', 'mozDash'
     ],
     'resultNotAddRefed': [ 'canvas', 'measureText' ],
     'binaryNames': {
         'mozImageSmoothingEnabled': 'imageSmoothingEnabled',
         'mozFillRule': 'fillRule'
     }
 },
 
@@ -1700,17 +1707,16 @@ addExternalIface('MozMediaStreamOptions'
                  headerFile='nsIDOMNavigatorUserMedia.h')
 addExternalIface('MozMobileConnection', headerFile='nsIDOMMobileConnection.h')
 addExternalIface('MozMobileMessageManager', headerFile='nsIDOMMobileMessageManager.h')
 addExternalIface('MozObserver', nativeType='nsIObserver', notflattened=True)
 addExternalIface('MozPowerManager', headerFile='nsIDOMPowerManager.h')
 addExternalIface('MozRDFCompositeDataSource', nativeType='nsIRDFCompositeDataSource',
                  notflattened=True)
 addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=True)
-addExternalIface('MozSmsManager', headerFile='nsIDOMSmsManager.h')
 addExternalIface('MozTelephony', nativeType='nsIDOMTelephony')
 addExternalIface('MozTreeBoxObject', nativeType='nsITreeBoxObject',
                  notflattened=True)
 addExternalIface('MozTreeColumn', nativeType='nsITreeColumn',
                  headerFile='nsITreeColumns.h')
 addExternalIface('MozVoicemail')
 addExternalIface('MozWakeLock', headerFile='nsIDOMWakeLock.h')
 addExternalIface('MozXULTemplateBuilder', nativeType='nsIXULTemplateBuilder')
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -4,16 +4,17 @@
 
 # Common codegen classes.
 
 import operator
 import os
 import re
 import string
 import math
+import itertools
 
 from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType
 from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, Descriptor
 
 AUTOGENERATED_WARNING_COMMENT = \
     "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
 ADDPROPERTY_HOOK_NAME = '_addProperty'
 FINALIZE_HOOK_NAME = '_finalize'
@@ -730,32 +731,37 @@ def UnionTypes(descriptors, dictionaries
     """
 
     # Now find all the things we'll need as arguments and return values because
     # we need to wrap or unwrap them.
     headers = set()
     implheaders = set(["UnionTypes.h"])
     declarations = set()
     unionStructs = dict()
+    unionReturnValues = dict()
 
     def addInfoForType(t, descriptor=None, dictionary=None):
         """
         Add info for the given type.  descriptor and dictionary, if passed, are
         used to figure out what to do with interface types.
         """
         assert not descriptor or not dictionary
         t = t.unroll()
         if not t.isUnion():
             return
         name = str(t)
         if not name in unionStructs:
             providers = getRelevantProviders(descriptor, dictionary,
                                              config)
             # FIXME: Unions are broken in workers.  See bug 809899.
             unionStructs[name] = CGUnionStruct(t, providers[0])
+            # Unions cannot contain JSObject*.
+            if not any(member.isObject() or member.isSpiderMonkeyInterface() for member in t.flatMemberTypes):
+                unionReturnValues[name] = CGUnionReturnValueStruct(t, providers[0])
+
             for f in t.flatMemberTypes:
                 f = f.unroll()
                 if f.isInterface():
                     if f.isSpiderMonkeyInterface():
                         headers.add("jsfriendapi.h")
                         headers.add("mozilla/dom/TypedArray.h")
                     else:
                         for p in providers:
@@ -767,17 +773,18 @@ def UnionTypes(descriptors, dictionaries
                             implheaders.add(typeDesc.headerFile)
                 elif f.isDictionary():
                     declarations.add((f.inner.identifier.name, True))
                     implheaders.add(CGHeaders.getDeclarationFilename(f.inner))
 
     callForEachType(descriptors, dictionaries, callbacks, addInfoForType)
 
     return (headers, implheaders, declarations,
-            CGList(SortedDictValues(unionStructs), "\n"))
+            CGList(itertools.chain(SortedDictValues(unionStructs),
+                                   SortedDictValues(unionReturnValues)), "\n"))
 
 def UnionConversions(descriptors, dictionaries, callbacks, config):
     """
     Returns a CGThing to declare all union argument conversion helper structs.
     """
     # Now find all the things we'll need as arguments because we
     # need to unwrap them.
     headers = set()
@@ -1433,16 +1440,27 @@ class MethodDefiner(PropertyDefiner):
                                  "nativeName": stringifier.identifier.name,
                                  "length": 0,
                                  "flags": "JSPROP_ENUMERATE",
                                  "condition": PropertyDefiner.getControllingCondition(stringifier) }
                 if isChromeOnly(stringifier):
                     self.chrome.append(toStringDesc)
                 else:
                     self.regular.append(toStringDesc)
+            jsonifier = descriptor.operations['Jsonifier']
+            if jsonifier:
+                toJSONDesc = { "name": "toJSON",
+                               "nativeName": jsonifier.identifier.name,
+                               "length": 0,
+                               "flags": "JSPROP_ENUMERATE",
+                               "condition": PropertyDefiner.getControllingCondition(jsonifier) }
+                if isChromeOnly(jsonifier):
+                    self.chrome.append(toJSONDesc)
+                else:
+                    self.regular.append(toJSONDesc)
         elif (descriptor.interface.isJSImplemented() and
               descriptor.interface.hasInterfaceObject()):
             self.chrome.append({"name": '_create',
                                 "nativeName": ("%s::_Create" %
                                                descriptor.name),
                                 "methodInfo": False,
                                 "length": 2,
                                 "flags": "0",
@@ -2053,17 +2071,17 @@ def GetAccessCheck(descriptor, object):
 def InitUnforgeablePropertiesOnObject(descriptor, obj, properties, failureReturnValue=""):
     """
     properties is a PropertyArrays instance
     """
     failureReturn = "return"
     if len(failureReturnValue) > 0:
         failureReturn += " " + failureReturnValue
     failureReturn += ";"
-        
+
     defineUnforgeables = ("if (!DefineUnforgeableAttributes(aCx, " + obj + ", %s)) {\n"
                           "  " + failureReturn + "\n"
                           "}")
 
     unforgeableAttrs = properties.unforgeableAttrs
     unforgeables = []
     if unforgeableAttrs.hasNonChromeOnly():
         unforgeables.append(CGGeneric(defineUnforgeables %
@@ -2472,16 +2490,17 @@ def getJSToNativeConversionInfo(type, de
                                 treatUndefinedAs="Default",
                                 isEnforceRange=False,
                                 isClamp=False,
                                 isNullOrUndefined=False,
                                 exceptionCode=None,
                                 lenientFloatCode=None,
                                 allowTreatNonCallableAsNull=False,
                                 isCallbackReturnValue=False,
+                                isInUnionReturnValue=False,
                                 sourceDescription="value"):
     """
     Get a template for converting a JS value to a native object based on the
     given type and descriptor.  If failureCode is given, then we're actually
     testing whether we can convert the argument to the desired type.  That
     means that failures to convert due to the JS value being the wrong type of
     value need to use failureCode instead of throwing exceptions.  Failures to
     convert that are due to JS exceptions (from toString or valueOf methods) or
@@ -3020,23 +3039,26 @@ for (uint32_t i = 0; i < length; ++i) {
 
         # Allow null pointers for nullable types and old-binding classes, and
         # use an nsRefPtr or raw pointer for callback return values to make
         # them easier to return.
         argIsPointer = (type.nullable() or type.unroll().inner.isExternal() or
                         isCallbackReturnValue)
 
         # Sequences and non-worker callbacks have to hold a strong ref to the
-        # thing being passed down.  Also, callback return values always end up
+        # thing being passed down.  Union return values must hold a strong ref
+        # because they may be returning an addrefed pointer.
+        # Also, callback return values always end up
         # addrefing anyway, so there is no point trying to avoid it here and it
         # makes other things simpler since we can assume the return value is a
         # strong ref.
         forceOwningType = ((descriptor.interface.isCallback() and
                             not descriptor.workers) or
                            isMember or
+                           isInUnionReturnValue or
                            isCallbackReturnValue)
 
         typeName = descriptor.nativeType
         typePtr = typeName + "*"
 
         # Compute a few things:
         #  - declType is the type we want to return as the first element of our
         #    tuple.
@@ -3243,16 +3265,18 @@ for (uint32_t i = 0; i < length; ++i) {
                 "  FakeDependentString str;\n"
                 "%s\n"
                 "  ${declName} = str;\n"
                 "}\n" % CGIndenter(CGGeneric(getConversionCode("str"))).define(),
                 declType=declType, dealWithOptional=isOptional)
 
         if isOptional:
             declType = "Optional<nsAString>"
+        elif isInUnionReturnValue:
+            declType = "nsString"
         else:
             declType = "NonNull<nsAString>"
 
         # No need to deal with optional here; we handled it already
         return JSToNativeConversionInfo(
             "%s\n"
             "${declName} = &${holderName};" %
             getConversionCode("${holderName}"),
@@ -4084,35 +4108,31 @@ if (!returnArray) {
             toValue = "JS::ObjectValue(*%s)"
             if type.isSpiderMonkeyInterface():
                 wrapType = "nonDOMObject"
             else:
                 wrapType = "object"
         # NB: setValue(..., True) calls JS_WrapValue(), so is fallible
         return (setValue(toValue % result, wrapType), False)
 
-    if type.isUnion():
-        if type.nullable():
-            prefix = "%s->"
-        else:
-            prefix = "%s."
-        return (wrapAndSetPtr((prefix % result) +
-                              "ToJSVal(cx, ${obj}, ${jsvalHandle})"), False)
-
-    if not (type.isPrimitive() or type.isDictionary() or type.isDate()):
+    if not (type.isUnion() or type.isPrimitive() or type.isDictionary() or type.isDate()):
         raise TypeError("Need to learn to wrap %s" % type)
 
     if type.nullable():
         (recTemplate, recInfal) = getWrapTemplateForType(type.inner, descriptorProvider,
                                                          "%s.Value()" % result, successCode,
                                                          isCreator, exceptionCode)
         return ("if (%s.IsNull()) {\n" % result +
                 CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
                 "}\n" + recTemplate, recInfal)
 
+    if type.isUnion():
+        return (wrapAndSetPtr("%s.ToJSVal(cx, ${obj}, ${jsvalHandle})" % result),
+                False)
+
     if type.isDictionary():
         return (wrapAndSetPtr("%s.ToObject(cx, ${obj}, ${jsvalHandle})" % result),
                 False)
 
     if type.isDate():
         return (wrapAndSetPtr("%s.ToDateObject(cx, ${jsvalHandle})" % result),
                 False)
 
@@ -4306,17 +4326,20 @@ def getRetvalDeclarationForType(returnTy
             else:
                 result = CGTemplatedType("RootedDictionary", result)
             resultArgs = "cx"
         elif nullable:
             result = CGTemplatedType("Nullable", result)
             resultArgs = None
         return result, True, None, resultArgs
     if returnType.isUnion():
-        raise TypeError("Need to sort out ownership model for union retvals");
+        result = CGGeneric(returnType.unroll().name + "ReturnValue")
+        if returnType.nullable():
+            result = CGTemplatedType("Nullable", result)
+        return result, True, None, None
     if returnType.isDate():
         result = CGGeneric("Date")
         if returnType.nullable():
             result = CGTemplatedType("Nullable", result)
         return result, False, None, None
     raise TypeError("Don't know how to declare return value for %s" %
                     returnType)
 
@@ -4414,17 +4437,17 @@ class CGCallGenerator(CGThing):
             if not resultOutParam:
                 call = CGWrapper(call, pre="result = ")
 
         call = CGWrapper(call)
         self.cgRoot.append(call)
 
         if isFallible:
             self.cgRoot.prepend(CGGeneric("ErrorResult rv;"))
-            self.cgRoot.append(CGGeneric("rv.WouldReportJSException();"));
+            self.cgRoot.append(CGGeneric("rv.WouldReportJSException();"))
             self.cgRoot.append(CGGeneric("if (rv.Failed()) {"))
             self.cgRoot.append(CGIndenter(errorReport))
             self.cgRoot.append(CGGeneric("}"))
 
     def define(self):
         return self.cgRoot.define()
 
 class MethodNotCreatorError(Exception):
@@ -5202,16 +5225,42 @@ class CGSpecializedMethod(CGAbstractStat
         return CGMethodCall(nativeName, self.method.isStatic(), self.descriptor,
                             self.method).define()
 
     @staticmethod
     def makeNativeName(descriptor, method):
         name = method.identifier.name
         return MakeNativeName(descriptor.binaryNames.get(name, name))
 
+class CGJsonifierMethod(CGSpecializedMethod):
+    def __init__(self, descriptor, method):
+        assert method.isJsonifier()
+        CGSpecializedMethod.__init__(self, descriptor, method)
+
+    def definition_body(self):
+        ret = ('JS::Rooted<JSObject*> result(cx, JS_NewObject(cx, nullptr, nullptr, nullptr));\n'
+               'if (!result) {\n'
+               '  return false;\n'
+               '}\n')
+        for m in self.descriptor.interface.members:
+          if m.isAttr() and not m.isStatic():
+              ret += ('{ // scope for "temp"\n'
+                      '  JS::Rooted<JS::Value> temp(cx);\n'
+                      '  if (!get_%s(cx, obj, self, JSJitGetterCallArgs(&temp))) {\n'
+                      '    return false;\n'
+                      '  }\n'
+                      '  if (!JS_DefineProperty(cx, result, "%s", temp, nullptr, nullptr, JSPROP_ENUMERATE)) {\n'
+                      '    return false;\n'
+                      '  }\n'
+                      '}\n' % (m.identifier.name, m.identifier.name))
+
+        ret += ('args.rval().setObject(*result);\n'
+                'return true;')
+        return CGIndenter(CGGeneric(ret)).define()
+
 class CGLegacyCallHook(CGAbstractBindingMethod):
     """
     Call hook for our object
     """
     def __init__(self, descriptor):
         self._legacycaller = descriptor.operations["LegacyCaller"]
         args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
                 Argument('JS::Value*', 'vp')]
@@ -5797,17 +5846,17 @@ def getUnionAccessorSignatureType(type, 
     if not type.isPrimitive():
         raise TypeError("Need native type for argument type '%s'" % str(type))
 
     typeName = CGGeneric(builtinNames[type.tag()])
     if type.nullable():
         typeName = CGTemplatedType("Nullable", typeName, isReference=True)
     return typeName
 
-def getUnionTypeTemplateVars(unionType, type, descriptorProvider):
+def getUnionTypeTemplateVars(unionType, type, descriptorProvider, isReturnValue=False):
     # For dictionaries and sequences we need to pass None as the failureCode
     # for getJSToNativeConversionInfo.
     # Also, for dictionaries we would need to handle conversion of
     # null/undefined to the dictionary correctly.
     if type.isDictionary() or type.isSequence():
         raise TypeError("Can't handle dictionaries or sequences in unions")
 
     if type.isGeckoInterface():
@@ -5822,17 +5871,17 @@ def getUnionTypeTemplateVars(unionType, 
     tryNextCode = """tryNext = true;
 return true;"""
     if type.isGeckoInterface():
          tryNextCode = ("""if (mUnion.mType != mUnion.eUninitialized) {
   mUnion.Destroy%s();
 }""" % name) + tryNextCode
     conversionInfo = getJSToNativeConversionInfo(
         type, descriptorProvider, failureCode=tryNextCode,
-        isDefinitelyObject=True,
+        isDefinitelyObject=True, isInUnionReturnValue=isReturnValue,
         sourceDescription="member of %s" % unionType)
 
     # This is ugly, but UnionMember needs to call a constructor with no
     # arguments so the type can't be const.
     structType = conversionInfo.declType.define()
     if structType.startswith("const "):
         structType = structType[6:]
     externalType = getUnionAccessorSignatureType(type, descriptorProvider).define()
@@ -5916,17 +5965,17 @@ class CGUnionStruct(CGThing):
   }
   ${externalType} GetAs${name}() const
   {
     MOZ_ASSERT(Is${name}(), "Wrong type!");
     return const_cast<${structType}&>(mValue.m${name}.Value());
   }"""
         methods.extend(mapTemplate(methodTemplate, templateVars))
         # Now have to be careful: we do not want the SetAsObject() method!
-        setterTemplate = """ ${structType}& SetAs${name}()
+        setterTemplate = """  ${structType}& SetAs${name}()
   {
     mType = e${name};
     return mValue.m${name}.SetValue();
   }"""
         methods.extend(mapTemplate(setterTemplate,
                                    filter(lambda v: v["name"] != "Object",
                                           templateVars)))
         values = mapTemplate("UnionMember<${structType} > m${name};", templateVars)
@@ -5978,17 +6027,17 @@ private:
        })
 
     def define(self):
         templateVars = self.templateVars
         conversionsToJS = []
         if self.type.hasNullableType:
             conversionsToJS.append("    case eNull:\n"
                                    "    {\n"
-                                   "      rval.set(JS::NullValue());\n"
+                                   "      rval.setNull();\n"
                                    "      return true;\n"
                                    "    }")
         conversionsToJS.extend(
             map(self.getConversionToJS,
                 zip(templateVars, self.type.flatMemberTypes)))
 
         return string.Template("""bool
 ${structName}::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj,
@@ -6020,17 +6069,171 @@ private:
             val = "%s.get()->Obj()" % val
         wrapCode = wrapForType(
             type, self.descriptorProvider,
             {
                 "jsvalRef": "rval",
                 "jsvalHandle": "rval",
                 "obj": "scopeObj",
                 "result": val,
-                "objectCanBeNonNull": True
+                })
+        return CGIndenter(CGList([CGGeneric("case e%(name)s:" % templateVars),
+                                  CGWrapper(CGIndenter(CGGeneric(wrapCode)),
+                                            pre="{\n",
+                                            post="\n}")],
+                                 "\n"),
+                          4).define()
+
+class CGUnionReturnValueStruct(CGThing):
+    def __init__(self, type, descriptorProvider):
+        CGThing.__init__(self)
+        self.type = type.unroll()
+        self.descriptorProvider = descriptorProvider
+        self.templateVars = map(
+            lambda t: getUnionTypeTemplateVars(self.type, t,
+                                               self.descriptorProvider,
+                                               isReturnValue=True),
+            self.type.flatMemberTypes)
+
+    def declare(self):
+        templateVars = self.templateVars
+
+        enumValues = []
+        methods = []
+        if self.type.hasNullableType:
+            enumValues.append("eNull")
+            methods.append("""  bool IsNull() const
+  {
+    return mType == eNull;
+  }
+
+  bool SetNull()
+  {
+    mType = eNull;
+    return true;
+  }""")
+
+        enumValues.extend(mapTemplate("e${name}", templateVars))
+        methodTemplate = "  ${structType}& SetAs${name}();"
+        methods.extend(mapTemplate(methodTemplate, templateVars))
+        values = mapTemplate("UnionMember<${structType} > m${name};", templateVars)
+        return string.Template("""
+class ${structName}ReturnValue {
+public:
+  ${structName}ReturnValue() : mType(eUninitialized)
+  {
+  }
+  ~${structName}ReturnValue();
+
+${methods}
+
+  bool ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj,
+               JS::MutableHandle<JS::Value> rval) const;
+
+private:
+  enum Type {
+    eUninitialized,
+    ${enumValues}
+  };
+  union Value {
+    ${values}
+  };
+
+  Type mType;
+  Value mValue;
+};
+
+""").substitute(
+    {
+       "structName": self.type.__str__(),
+       "methods": "\n\n".join(methods),
+       "enumValues": ",\n    ".join(enumValues),
+       "values": "\n    ".join(values)
+       })
+
+    def define(self):
+        templateVars = self.templateVars
+        conversionsToJS = []
+        if self.type.hasNullableType:
+            conversionsToJS.append("    case eNull:\n"
+                                   "    {\n"
+                                   "      rval.setNull();\n"
+                                   "      return true;\n"
+                                   "    }")
+        conversionsToJS.extend(
+            map(self.getConversionToJS,
+                zip(templateVars, self.type.flatMemberTypes)))
+
+        toJSVal = string.Template("""
+
+bool
+${structName}ReturnValue::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
+{
+  switch (mType) {
+${doConversionsToJS}
+
+    case eUninitialized:
+    {
+      break;
+    }
+  }
+  return false;
+}
+""").substitute({
+                "structName": str(self.type),
+                "doConversionsToJS": "\n\n".join(conversionsToJS)
+                })
+        templateVars = self.templateVars
+
+        methods = []
+        methodTemplate = """${structType}&
+%sReturnValue::SetAs${name}()
+{
+  mType = e${name};
+  return mValue.m${name}.SetValue();
+}""" % str(self.type)
+        methods.extend(mapTemplate(methodTemplate, templateVars))
+
+        callDestructors = []
+        if self.type.hasNullableType:
+            callDestructors.append("      case eNull:\n"
+                                   "        break;")
+        callDestructors.extend(mapTemplate("    case e${name}:\n"
+                                           "       mValue.m${name}.Destroy();\n"
+                                           "       mType = eUninitialized;\n"
+                                           "       break;", templateVars))
+        destructor = string.Template("""
+${structName}ReturnValue::~${structName}ReturnValue()
+{
+  switch (mType) {
+${callDestructors}
+    case eUninitialized:
+      break;
+  }
+}
+
+""").substitute(
+    {
+       "structName": self.type.__str__(),
+       "callDestructors": "\n".join(callDestructors),
+       })
+
+        return destructor + "\n\n".join(methods) + toJSVal
+
+    def getConversionToJS(self, arg):
+        (templateVars, type) = arg
+        assert not type.nullable() # flatMemberTypes never has nullable types
+        val = "mValue.m%(name)s.Value()" % templateVars
+        wrapCode = wrapForType(
+            type, self.descriptorProvider,
+            {
+                "jsvalRef": "rval",
+                "jsvalHandle": "rval",
+                "obj": "scopeObj",
+                "result": val,
                 })
         return CGIndenter(CGList([CGGeneric("case e%(name)s:" % templateVars),
                                   CGWrapper(CGIndenter(CGGeneric(wrapCode)),
                                             pre="{\n",
                                             post="\n}")],
                                  "\n"),
                           4).define()
 
@@ -7539,25 +7742,29 @@ class CGDescriptor(CGThing):
            descriptor.interface.hasChildInterfaces() or
            descriptor.interface.parent):
            raise TypeError("Owned interface cannot have a parent or children")
 
         self._deps = descriptor.interface.getDeps()
 
         cgThings = []
         # These are set to true if at least one non-static
-        # method/getter/setter exist on the interface.
-        (hasMethod, hasGetter, hasLenientGetter,
-         hasSetter, hasLenientSetter) = False, False, False, False, False
+        # method/getter/setter or jsonifier exist on the interface.
+        (hasMethod, hasGetter, hasLenientGetter, hasSetter, hasJsonifier,
+            hasLenientSetter) = False, False, False, False, False, False
         for n in descriptor.interface.namedConstructors:
             cgThings.append(CGClassConstructor(descriptor, n,
                                                NamedConstructorName(n)))
         for m in descriptor.interface.members:
-            if (m.isMethod() and
-                (not m.isIdentifierLess() or m == descriptor.operations['Stringifier'])):
+            if (m.isMethod() and m == descriptor.operations['Jsonifier']):
+                hasJsonifier = True
+                hasMethod = True
+                jsonifierMethod = m
+            elif (m.isMethod() and
+                  (not m.isIdentifierLess() or m == descriptor.operations['Stringifier'])):
                 if m.isStatic():
                     assert descriptor.interface.hasInterfaceObject
                     cgThings.append(CGStaticMethod(descriptor, m))
                 elif descriptor.interface.hasInterfacePrototypeObject():
                     cgThings.append(CGSpecializedMethod(descriptor, m))
                     cgThings.append(CGMemberJITInfo(descriptor, m))
                     hasMethod = True
             elif m.isAttr():
@@ -7581,16 +7788,19 @@ class CGDescriptor(CGThing):
                         else:
                             hasSetter = True
                 elif m.getExtendedAttribute("PutForwards"):
                     cgThings.append(CGSpecializedForwardingSetter(descriptor, m))
                     hasSetter = True
                 if (not m.isStatic() and
                     descriptor.interface.hasInterfacePrototypeObject()):
                     cgThings.append(CGMemberJITInfo(descriptor, m))
+        if hasJsonifier:
+            cgThings.append(CGJsonifierMethod(descriptor, jsonifierMethod))
+            cgThings.append(CGMemberJITInfo(descriptor, jsonifierMethod))
         if hasMethod: cgThings.append(CGGenericMethod(descriptor))
         if hasGetter: cgThings.append(CGGenericGetter(descriptor))
         if hasLenientGetter: cgThings.append(CGGenericGetter(descriptor,
                                                              lenientThis=True))
         if hasSetter: cgThings.append(CGGenericSetter(descriptor))
         if hasLenientSetter: cgThings.append(CGGenericSetter(descriptor,
                                                              lenientThis=True))
 
@@ -8984,16 +9194,19 @@ class CGBindingImplClass(CGClass):
                     return
             if name == "LegacyCaller":
                 if op.isIdentifierLess():
                     # XXXbz I wish we were consistent about our renaming here.
                     name = "LegacyCall"
                 else:
                     # We already added this method
                     return
+            if name == "Jsonifier":
+                # We already added this method
+                return
             self.methodDecls.append(
                 CGNativeMember(descriptor, op,
                                name,
                                (returnType, args),
                                descriptor.getExtendedAttributes(op)))
         # Sort things by name so we get stable ordering in the output.
         ops = descriptor.operations.items()
         ops.sort(key=lambda x: x[0])
@@ -9549,17 +9762,17 @@ class CGCallbackFunction(CGCallback):
 class CGCallbackInterface(CGCallback):
     def __init__(self, descriptor):
         iface = descriptor.interface
         attrs = [m for m in iface.members if m.isAttr() and not m.isStatic()]
         getters = [CallbackGetter(a, descriptor) for a in attrs]
         setters = [CallbackSetter(a, descriptor) for a in attrs
                    if not a.readonly]
         methods = [m for m in iface.members
-                   if m.isMethod() and not m.isStatic()]
+                   if m.isMethod() and not m.isStatic() and not m.isIdentifierLess()]
         methods = [CallbackOperation(m, sig, descriptor) for m in methods
                    for sig in m.signatures()]
         if iface.isJSImplemented() and iface.ctor():
             sigs = descriptor.interface.ctor().signatures()
             if len(sigs) != 1:
                 raise TypeError("We only handle one constructor.  See bug 869268.")
             methods.append(CGJSImplInitOperation(sigs[0], descriptor))
         CGCallback.__init__(self, iface, descriptor, "CallbackInterface",
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -272,29 +272,32 @@ class Descriptor(DescriptorProvider):
             'IndexedSetter': None,
             'IndexedCreator': None,
             'IndexedDeleter': None,
             'NamedGetter': None,
             'NamedSetter': None,
             'NamedCreator': None,
             'NamedDeleter': None,
             'Stringifier': None,
-            'LegacyCaller': None
+            'LegacyCaller': None,
+            'Jsonifier': None
             }
         if self.concrete:
             self.proxy = False
             iface = self.interface
             def addOperation(operation, m):
                 if not operations[operation]:
                     operations[operation] = m
             # Since stringifiers go on the prototype, we only need to worry
             # about our own stringifier, not those of our ancestor interfaces.
             for m in iface.members:
                 if m.isMethod() and m.isStringifier():
                     addOperation('Stringifier', m)
+                if m.isMethod() and m.isJsonifier():
+                    addOperation('Jsonifier', m)
                 # Don't worry about inheriting legacycallers either: in
                 # practice these are on most-derived prototypes.
                 if m.isMethod() and m.isLegacycaller():
                     if not m.isIdentifierLess():
                         raise TypeError("We don't support legacycaller with "
                                         "identifier.\n%s" % m.location);
                     if len(m.signatures()) != 1:
                         raise TypeError("We don't support overloaded "
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -713,22 +713,25 @@ class IDLInterface(IDLObjectWithScope):
             elif member.isSetter():
                 memberType = "setters"
             elif member.isCreator():
                 memberType = "creators"
             elif member.isDeleter():
                 memberType = "deleters"
             elif member.isStringifier():
                 memberType = "stringifiers"
+            elif member.isJsonifier():
+                memberType = "jsonifiers"
             elif member.isLegacycaller():
                 memberType = "legacycallers"
             else:
                 continue
 
-            if memberType != "stringifiers" and memberType != "legacycallers":
+            if (memberType != "stringifiers" and memberType != "legacycallers" and
+                memberType != "jsonifiers"):
                 if member.isNamed():
                     memberType = "named " + memberType
                 else:
                     assert member.isIndexed()
                     memberType = "indexed " + memberType
 
             if memberType in specialMembersSeen:
                 raise WebIDLError("Multiple " + memberType + " on %s" % (self),
@@ -2496,17 +2499,17 @@ class IDLAttribute(IDLInterfaceMember):
 
         if self.type.isDictionary():
             raise WebIDLError("An attribute cannot be of a dictionary type",
                               [self.location])
         if self.type.isSequence():
             raise WebIDLError("An attribute cannot be of a sequence type",
                               [self.location])
         if self.type.isUnion():
-            for f in self.type.flatMemberTypes:
+            for f in self.type.unroll().flatMemberTypes:
                 if f.isDictionary():
                     raise WebIDLError("An attribute cannot be of a union "
                                       "type if one of its member types (or "
                                       "one of its member types's member "
                                       "types, and so on) is a dictionary "
                                       "type", [self.location, f.location])
                 if f.isSequence():
                     raise WebIDLError("An attribute cannot be of a union "
@@ -2807,17 +2810,17 @@ class IDLMethod(IDLInterfaceMember, IDLS
         'Neither',
         'Named',
         'Indexed'
     )
 
     def __init__(self, location, identifier, returnType, arguments,
                  static=False, getter=False, setter=False, creator=False,
                  deleter=False, specialType=NamedOrIndexed.Neither,
-                 legacycaller=False, stringifier=False):
+                 legacycaller=False, stringifier=False, jsonifier=False):
         # REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
         IDLInterfaceMember.__init__(self, location, identifier,
                                     IDLInterfaceMember.Tags.Method)
 
         self._hasOverloads = False
 
         assert isinstance(returnType, IDLType)
 
@@ -2833,16 +2836,18 @@ class IDLMethod(IDLInterfaceMember, IDLS
         assert isinstance(creator, bool)
         self._creator = creator
         assert isinstance(deleter, bool)
         self._deleter = deleter
         assert isinstance(legacycaller, bool)
         self._legacycaller = legacycaller
         assert isinstance(stringifier, bool)
         self._stringifier = stringifier
+        assert isinstance(jsonifier, bool)
+        self._jsonifier = jsonifier
         self._specialType = specialType
 
         if static and identifier.name == "prototype":
             raise WebIDLError("The identifier of a static operation must not be 'prototype'",
                               [location])
 
         self.assertSignatureConstraints()
 
@@ -2870,16 +2875,22 @@ class IDLMethod(IDLInterfaceMember, IDLS
             assert not arguments[1].optional and not arguments[1].variadic
 
         if self._stringifier:
             assert len(self._overloads) == 1
             overload = self._overloads[0]
             assert len(overload.arguments) == 0
             assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.domstring]
 
+        if self._jsonifier:
+            assert len(self._overloads) == 1
+            overload = self._overloads[0]
+            assert len(overload.arguments) == 0
+            assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.object]
+
     def isStatic(self):
         return self._static
 
     def isGetter(self):
         return self._getter
 
     def isSetter(self):
         return self._setter
@@ -2901,16 +2912,19 @@ class IDLMethod(IDLInterfaceMember, IDLS
         return self._specialType == IDLMethod.NamedOrIndexed.Indexed
 
     def isLegacycaller(self):
         return self._legacycaller
 
     def isStringifier(self):
         return self._stringifier
 
+    def isJsonifier(self):
+        return self._jsonifier
+
     def hasOverloads(self):
         return self._hasOverloads
 
     def isIdentifierLess(self):
         return self.identifier.name[:2] == "__"
 
     def resolve(self, parentScope):
         assert isinstance(parentScope, IDLScope)
@@ -2946,16 +2960,18 @@ class IDLMethod(IDLInterfaceMember, IDLS
         assert not self.isSetter()
         assert not method.isSetter()
         assert not self.isCreator()
         assert not method.isCreator()
         assert not self.isDeleter()
         assert not method.isDeleter()
         assert not self.isStringifier()
         assert not method.isStringifier()
+        assert not self.isJsonifier()
+        assert not method.isJsonifier()
 
         return self
 
     def signatures(self):
         return [(overload.returnType, overload.arguments) for overload in
                 self._overloads]
 
     def finish(self, scope):
@@ -3279,16 +3295,17 @@ class Tokenizer(object):
         "typedef": "TYPEDEF",
         "implements": "IMPLEMENTS",
         "const": "CONST",
         "null": "NULL",
         "true": "TRUE",
         "false": "FALSE",
         "serializer": "SERIALIZER",
         "stringifier": "STRINGIFIER",
+        "jsonifier": "JSONIFIER",
         "unrestricted": "UNRESTRICTED",
         "attribute": "ATTRIBUTE",
         "readonly": "READONLY",
         "inherit": "INHERIT",
         "static": "STATIC",
         "getter": "GETTER",
         "setter": "SETTER",
         "creator": "CREATOR",
@@ -3909,16 +3926,29 @@ class Parser(Tokenizer):
                                              allowDoubleUnderscore=True)
         method = IDLMethod(self.getLocation(p, 1),
                            identifier,
                            returnType=BuiltinTypes[IDLBuiltinType.Types.domstring],
                            arguments=[],
                            stringifier=True)
         p[0] = method
 
+    def p_Jsonifier(self, p):
+        """
+            Operation : JSONIFIER SEMICOLON
+        """
+        identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
+                                             "__jsonifier", allowDoubleUnderscore=True)
+        method = IDLMethod(self.getLocation(p, 1),
+                           identifier,
+                           returnType=BuiltinTypes[IDLBuiltinType.Types.object],
+                           arguments=[],
+                           jsonifier=True)
+        p[0] = method
+
     def p_QualifierStatic(self, p):
         """
             Qualifier : STATIC
         """
         p[0] = [IDLInterfaceMember.Special.Static]
 
     def p_QualifierStringifier(self, p):
         """
@@ -4061,16 +4091,17 @@ class Parser(Tokenizer):
                          | INHERIT
                          | INTERFACE
                          | LEGACYCALLER
                          | PARTIAL
                          | SERIALIZER
                          | SETTER
                          | STATIC
                          | STRINGIFIER
+                         | JSONIFIER
                          | TYPEDEF
                          | UNRESTRICTED
         """
         p[0] = p[1]
 
     def p_Optional(self, p):
         """
             Optional : OPTIONAL
@@ -4190,16 +4221,17 @@ class Parser(Tokenizer):
                   | OBJECT
                   | OCTET
                   | OPTIONAL
                   | SEQUENCE
                   | SETTER
                   | SHORT
                   | STATIC
                   | STRINGIFIER
+                  | JSONIFIER
                   | TRUE
                   | TYPEDEF
                   | UNSIGNED
                   | VOID
         """
         pass
 
     def p_OtherOrComma(self, p):
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -502,16 +502,26 @@ public:
   //void PassUnionWithInterfaces(const TestInterfaceOrTestExternalInterface& arg);
   //void PassUnionWithInterfacesAndNullable(const TestInterfaceOrNullOrTestExternalInterface& arg);
   void PassUnionWithArrayBuffer(const ArrayBufferOrLong&);
   void PassUnionWithString(JSContext*, const StringOrObject&);
   //void PassUnionWithEnum(JSContext*, const TestEnumOrObject&);
   //void PassUnionWithCallback(JSContext*, const TestCallbackOrLong&);
   void PassUnionWithObject(JSContext*, const ObjectOrLong&);
 
+  void ReceiveUnion(const CanvasPatternOrCanvasGradientReturnValue&);
+  void ReceiveUnionContainingNull(const CanvasPatternOrNullOrCanvasGradientReturnValue&);
+  void ReceiveNullableUnion(const Nullable<CanvasPatternOrCanvasGradientReturnValue>&);
+  void GetWritableUnion(const CanvasPatternOrCanvasGradientReturnValue&);
+  void SetWritableUnion(const CanvasPatternOrCanvasGradient&);
+  void GetWritableUnionContainingNull(const CanvasPatternOrNullOrCanvasGradientReturnValue&);
+  void SetWritableUnionContainingNull(const CanvasPatternOrNullOrCanvasGradient&);
+  void GetWritableNullableUnion(const Nullable<CanvasPatternOrCanvasGradientReturnValue>&);
+  void SetWritableNullableUnion(const Nullable<CanvasPatternOrCanvasGradient>&);
+
   // Date types
   void PassDate(Date);
   void PassNullableDate(const Nullable<Date>&);
   void PassOptionalDate(const Optional<Date>&);
   void PassOptionalNullableDate(const Optional<Nullable<Date> >&);
   void PassOptionalNullableDateWithDefaultValue(const Nullable<Date>&);
   void PassDateSequence(const Sequence<Date>&);
   void PassNullableDateSequence(const Sequence<Nullable<Date> >&);
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -447,16 +447,24 @@ interface TestInterface {
   void passUnionWithString((DOMString or object) arg);
   //void passUnionWithEnum((TestEnum or object) arg);
   // Trying to use a callback in a union won't include the test
   // headers, unfortunately, so won't compile.
   //void passUnionWithCallback((TestCallback or long) arg);
   void passUnionWithObject((object or long) arg);
   //void passUnionWithDict((Dict or long) arg);
 
+  (CanvasPattern or CanvasGradient) receiveUnion();
+  (CanvasPattern? or CanvasGradient) receiveUnionContainingNull();
+  (CanvasPattern or CanvasGradient)? receiveNullableUnion();
+
+  attribute (CanvasPattern or CanvasGradient) writableUnion;
+  attribute (CanvasPattern? or CanvasGradient) writableUnionContainingNull;
+  attribute (CanvasPattern or CanvasGradient)? writableNullableUnion;
+
   // Date types
   void passDate(Date arg);
   void passNullableDate(Date? arg);
   void passOptionalDate(optional Date arg);
   void passOptionalNullableDate(optional Date? arg);
   void passOptionalNullableDateWithDefaultValue(optional Date? arg = null);
   void passDateSequence(sequence<Date> arg);
   void passNullableDateSequence(sequence<Date?> arg);
@@ -570,16 +578,17 @@ interface TestInterface {
   [Throws] attribute boolean throwingAttr;
   [GetterThrows] attribute boolean throwingGetterAttr;
   [SetterThrows] attribute boolean throwingSetterAttr;
   legacycaller short(unsigned long arg1, TestInterface arg2);
   void passArgsWithDefaults(optional long arg1,
                             optional TestInterface? arg2 = null,
                             optional Dict arg3, optional double arg4 = 5.0,
                             optional float arg5);
+  jsonifier;
 
   // If you add things here, add them to TestExampleGen and TestJSImplGen as well
 };
 
 interface TestParentInterface {
 };
 
 interface TestChildInterface : TestParentInterface {
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -343,16 +343,24 @@ interface TestExampleInterface {
   void passUnionWithString((DOMString or object) arg);
   //void passUnionWithEnum((TestEnum or object) arg);
   // Trying to use a callback in a union won't include the test
   // headers, unfortunately, so won't compile.
   //  void passUnionWithCallback((TestCallback or long) arg);
   void passUnionWithObject((object or long) arg);
   //void passUnionWithDict((Dict or long) arg);
 
+  //(CanvasPattern or CanvasGradient) receiveUnion();
+  //(CanvasPattern? or CanvasGradient) receiveUnionContainingNull();
+  //(CanvasPattern or CanvasGradient)? receiveNullableUnion();
+
+  //attribute (CanvasPattern or CanvasGradient) writableUnion;
+  //attribute (CanvasPattern? or CanvasGradient) writableUnionContainingNull;
+  //attribute (CanvasPattern or CanvasGradient)? writableNullableUnion;
+
   // Date types
   void passDate(Date arg);
   void passNullableDate(Date? arg);
   void passOptionalDate(optional Date arg);
   void passOptionalNullableDate(optional Date? arg);
   void passOptionalNullableDateWithDefaultValue(optional Date? arg = null);
   void passDateSequence(sequence<Date> arg);
   void passNullableDateSequence(sequence<Date?> arg);
@@ -467,16 +475,17 @@ interface TestExampleInterface {
   [Throws] attribute boolean throwingAttr;
   [GetterThrows] attribute boolean throwingGetterAttr;
   [SetterThrows] attribute boolean throwingSetterAttr;
   legacycaller short(unsigned long arg1, TestInterface arg2);
   void passArgsWithDefaults(optional long arg1,
                             optional TestInterface? arg2 = null,
                             optional Dict arg3, optional double arg4 = 5.0,
                             optional float arg5);
+  jsonifier;
 
   // If you add things here, add them to TestCodeGen and TestJSImplGen as well
 };
 
 interface TestExampleProxyInterface {
   getter long longIndexedGetter(unsigned long ix);
   deleter void (unsigned long ix);
   setter creator void longIndexedSetter(unsigned long y, long z);
--- a/dom/bindings/test/TestJSImplGen.webidl
+++ b/dom/bindings/test/TestJSImplGen.webidl
@@ -367,16 +367,24 @@ interface TestJSImplInterface {
   void passUnionWithString((DOMString or object) arg);
   //void passUnionWithEnum((MyTestEnum or object) arg);
   // Trying to use a callback in a union won't include the test
   // headers, unfortunately, so won't compile.
   //  void passUnionWithCallback((MyTestCallback or long) arg);
   void passUnionWithObject((object or long) arg);
   //void passUnionWithDict((Dict or long) arg);
 
+  //(CanvasPattern or CanvasGradient) receiveUnion();
+  //(CanvasPattern? or CanvasGradient) receiveUnionContainingNull();
+  //(CanvasPattern or CanvasGradient)? receiveNullableUnion();
+
+  //attribute (CanvasPattern or CanvasGradient) writableUnion;
+  //attribute (CanvasPattern? or CanvasGradient) writableUnionContainingNull;
+  //attribute (CanvasPattern or CanvasGradient)? writableNullableUnion;
+
   // Date types
   void passDate(Date arg);
   void passNullableDate(Date? arg);
   void passOptionalDate(optional Date arg);
   void passOptionalNullableDate(optional Date? arg);
   void passOptionalNullableDateWithDefaultValue(optional Date? arg = null);
   void passDateSequence(sequence<Date> arg);
   void passNullableDateSequence(sequence<Date?> arg);
@@ -459,16 +467,17 @@ interface TestJSImplInterface {
   [Throws] attribute boolean throwingAttr;
   [GetterThrows] attribute boolean throwingGetterAttr;
   [SetterThrows] attribute boolean throwingSetterAttr;
   // legacycaller short(unsigned long arg1, TestInterface arg2);
   void passArgsWithDefaults(optional long arg1,
                             optional TestInterface? arg2 = null,
                             optional Dict arg3, optional double arg4 = 5.0,
                             optional float arg5);
+  jsonifier;
 
   // If you add things here, add them to TestCodeGen as well
 };
 
 [NavigatorProperty="TestNavigator", JSImplementation="@mozilla.org/test;1"]
 interface TestNavigator {
 };
 
--- a/dom/bluetooth/BluetoothUtils.cpp
+++ b/dom/bluetooth/BluetoothUtils.cpp
@@ -56,17 +56,17 @@ SetJsObject(JSContext* aContext,
         break;
       default:
         NS_WARNING("SetJsObject: Parameter is not handled");
         break;
     }
 
     if (!JS_SetProperty(aContext, aObj,
                         NS_ConvertUTF16toUTF8(arr[i].name()).get(),
-                        &val)) {
+                        val)) {
       NS_WARNING("Failed to set property");
       return false;
     }
   }
 
   return true;
 }
 
--- a/dom/camera/CameraControlImpl.cpp
+++ b/dom/camera/CameraControlImpl.cpp
@@ -156,37 +156,37 @@ CameraControlImpl::Get(JSContext* aCx, u
 
     JS::Rooted<JSObject*> o(aCx, JS_NewObject(aCx, nullptr, nullptr, nullptr));
     if (!o) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     DOM_CAMERA_LOGI("top=%d\n", r->top);
     v = INT_TO_JSVAL(r->top);
-    if (!JS_SetProperty(aCx, o, "top", &v)) {
+    if (!JS_SetProperty(aCx, o, "top", v)) {
       return NS_ERROR_FAILURE;
     }
     DOM_CAMERA_LOGI("left=%d\n", r->left);
     v = INT_TO_JSVAL(r->left);
-    if (!JS_SetProperty(aCx, o, "left", &v)) {
+    if (!JS_SetProperty(aCx, o, "left", v)) {
       return NS_ERROR_FAILURE;
     }
     DOM_CAMERA_LOGI("bottom=%d\n", r->bottom);
     v = INT_TO_JSVAL(r->bottom);
-    if (!JS_SetProperty(aCx, o, "bottom", &v)) {
+    if (!JS_SetProperty(aCx, o, "bottom", v)) {
       return NS_ERROR_FAILURE;
     }
     DOM_CAMERA_LOGI("right=%d\n", r->right);
     v = INT_TO_JSVAL(r->right);
-    if (!JS_SetProperty(aCx, o, "right", &v)) {
+    if (!JS_SetProperty(aCx, o, "right", v)) {
       return NS_ERROR_FAILURE;
     }
     DOM_CAMERA_LOGI("weight=%d\n", r->weight);
     v = INT_TO_JSVAL(r->weight);
-    if (!JS_SetProperty(aCx, o, "weight", &v)) {
+    if (!JS_SetProperty(aCx, o, "weight", v)) {
       return NS_ERROR_FAILURE;
     }
 
     v = OBJECT_TO_JSVAL(o);
     if (!JS_SetElement(aCx, array, i, v.address())) {
       return NS_ERROR_FAILURE;
     }
   }
--- a/dom/camera/CameraRecorderProfiles.cpp
+++ b/dom/camera/CameraRecorderProfiles.cpp
@@ -31,41 +31,41 @@ RecorderVideoProfile::GetJsObject(JSCont
   JS::Rooted<JSObject*> o(aCx, JS_NewObject(aCx, nullptr, nullptr, nullptr));
   NS_ENSURE_TRUE(o, NS_ERROR_OUT_OF_MEMORY);
 
   const char* codec = GetCodecName();
   NS_ENSURE_TRUE(codec, NS_ERROR_FAILURE);
 
   JS::Rooted<JSString*> s(aCx, JS_NewStringCopyZ(aCx, codec));
   JS::Rooted<JS::Value> v(aCx, STRING_TO_JSVAL(s));
-  if (!JS_SetProperty(aCx, o, "codec", &v)) {
+  if (!JS_SetProperty(aCx, o, "codec", v)) {
     return NS_ERROR_FAILURE;
   }
 
   if (mBitrate != -1) {
     v = INT_TO_JSVAL(mBitrate);
-    if (!JS_SetProperty(aCx, o, "bitrate", &v)) {
+    if (!JS_SetProperty(aCx, o, "bitrate", v)) {
       return NS_ERROR_FAILURE;
     }
   }
   if (mFramerate != -1) {
     v = INT_TO_JSVAL(mFramerate);
-    if (!JS_SetProperty(aCx, o, "framerate", &v)) {
+    if (!JS_SetProperty(aCx, o, "framerate", v)) {
       return NS_ERROR_FAILURE;
     }
   }
   if (mWidth != -1) {
     v = INT_TO_JSVAL(mWidth);
-    if (!JS_SetProperty(aCx, o, "width", &v)) {
+    if (!JS_SetProperty(aCx, o, "width", v)) {
       return NS_ERROR_FAILURE;
     }
   }
   if (mHeight != -1) {
     v = INT_TO_JSVAL(mHeight);
-    if (!JS_SetProperty(aCx, o, "height", &v)) {
+    if (!JS_SetProperty(aCx, o, "height", v)) {
       return NS_ERROR_FAILURE;
     }
   }
 
   *aObject = o;
   return NS_OK;
 }
 
@@ -92,35 +92,35 @@ RecorderAudioProfile::GetJsObject(JSCont
   JS::Rooted<JSObject*> o(aCx, JS_NewObject(aCx, nullptr, nullptr, nullptr));
   NS_ENSURE_TRUE(o, NS_ERROR_OUT_OF_MEMORY);
 
   const char* codec = GetCodecName();
   NS_ENSURE_TRUE(codec, NS_ERROR_FAILURE);
 
   JS::Rooted<JSString*> s(aCx, JS_NewStringCopyZ(aCx, codec));
   JS::Rooted<JS::Value> v(aCx, STRING_TO_JSVAL(s));
-  if (!JS_SetProperty(aCx, o, "codec", &v)) {
+  if (!JS_SetProperty(aCx, o, "codec", v)) {
     return NS_ERROR_FAILURE;
   }
 
   if (mBitrate != -1) {
     v = INT_TO_JSVAL(mBitrate);
-    if (!JS_SetProperty(aCx, o, "bitrate", &v)) {
+    if (!JS_SetProperty(aCx, o, "bitrate", v)) {
       return NS_ERROR_FAILURE;
     }
   }
   if (mSamplerate != -1) {
     v = INT_TO_JSVAL(mSamplerate);
-    if (!JS_SetProperty(aCx, o, "samplerate", &v)) {
+    if (!JS_SetProperty(aCx, o, "samplerate", v)) {
       return NS_ERROR_FAILURE;
     }
   }
   if (mChannels != -1) {
     v = INT_TO_JSVAL(mChannels);
-    if (!JS_SetProperty(aCx, o, "channels", &v)) {
+    if (!JS_SetProperty(aCx, o, "channels", v)) {
       return NS_ERROR_FAILURE;
     }
   }
 
   *aObject = o;
   return NS_OK;
 }
 
@@ -180,16 +180,16 @@ RecorderProfileManager::GetJsObject(JSCo
       continue;
     }
 
     JS::Rooted<JSObject*> p(aCx);
     nsresult rv = profile->GetJsObject(aCx, p.address());
     NS_ENSURE_SUCCESS(rv, rv);
     JS::Rooted<JS::Value> v(aCx, OBJECT_TO_JSVAL(p));
 
-    if (!JS_SetProperty(aCx, o, profileName, &v)) {
+    if (!JS_SetProperty(aCx, o, profileName, v)) {
       return NS_ERROR_FAILURE;
     }
   }
 
   *aObject = o;
   return NS_OK;
 }
--- a/dom/camera/CameraRecorderProfiles.h
+++ b/dom/camera/CameraRecorderProfiles.h
@@ -175,33 +175,33 @@ public:
 
     JS::Rooted<JSObject*> o(aCx, JS_NewObject(aCx, nullptr, nullptr, nullptr));
     if (!o) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     JS::Rooted<JSString*> s(aCx, JS_NewStringCopyZ(aCx, format));
     JS::Rooted<JS::Value> v(aCx, STRING_TO_JSVAL(s));
-    if (!JS_SetProperty(aCx, o, "format", &v)) {
+    if (!JS_SetProperty(aCx, o, "format", v)) {
       return NS_ERROR_FAILURE;
     }
 
     JS::Rooted<JSObject*> video(aCx);
     nsresult rv = mVideo.GetJsObject(aCx, video.address());
     NS_ENSURE_SUCCESS(rv, rv);
     v = OBJECT_TO_JSVAL(video);
-    if (!JS_SetProperty(aCx, o, "video", &v)) {
+    if (!JS_SetProperty(aCx, o, "video", v)) {
       return NS_ERROR_FAILURE;
     }
 
     JS::Rooted<JSObject*> audio(aCx);
     rv = mAudio.GetJsObject(aCx, audio.address());
     NS_ENSURE_SUCCESS(rv, rv);
     v = OBJECT_TO_JSVAL(audio);
-    if (!JS_SetProperty(aCx, o, "audio", &v)) {
+    if (!JS_SetProperty(aCx, o, "audio", v)) {
       return NS_ERROR_FAILURE;
     }
 
     *aObject = o;
     return NS_OK;
   }
 
 protected:
--- a/dom/camera/DOMCameraCapabilities.cpp
+++ b/dom/camera/DOMCameraCapabilities.cpp
@@ -90,20 +90,20 @@ ParseDimensionItemAndAdd(JSContext* aCx,
   JS::Rooted<JS::Value> w(aCx, INT_TO_JSVAL(strtol(aStart, &x, 10)));
   JS::Rooted<JS::Value> h(aCx, INT_TO_JSVAL(strtol(x + 1, aEnd, 10)));
 
   JS::Rooted<JSObject*> o(aCx, JS_NewObject(aCx, nullptr, nullptr, nullptr));
   if (!o) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  if (!JS_SetProperty(aCx, o, "width", &w)) {
+  if (!JS_SetProperty(aCx, o, "width", w)) {
     return NS_ERROR_FAILURE;
   }
-  if (!JS_SetProperty(aCx, o, "height", &h)) {
+  if (!JS_SetProperty(aCx, o, "height", h)) {
     return NS_ERROR_FAILURE;
   }
 
   JS::Rooted<JS::Value> v(aCx, OBJECT_TO_JSVAL(o));
   if (!JS_SetElement(aCx, aArray, aIndex, v.address())) {
     return NS_ERROR_FAILURE;
   }
 
@@ -366,21 +366,21 @@ DOMCameraCapabilities::GetVideoSizes(JSC
   JS::Rooted<JSObject*> array(cx, JS_NewArrayObject(cx, 0, nullptr));
   if (!array) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   for (uint32_t i = 0; i < sizes.Length(); ++i) {
     JS::Rooted<JSObject*> o(cx, JS_NewObject(cx, nullptr, nullptr, nullptr));
     JS::Rooted<JS::Value> v(cx, INT_TO_JSVAL(sizes[i].width));
-    if (!JS_SetProperty(cx, o, "width", &v)) {
+    if (!JS_SetProperty(cx, o, "width", v)) {
       return NS_ERROR_FAILURE;
     }
     v = INT_TO_JSVAL(sizes[i].height);
-    if (!JS_SetProperty(cx, o, "height", &v)) {
+    if (!JS_SetProperty(cx, o, "height", v)) {
       return NS_ERROR_FAILURE;
     }
 
     v = OBJECT_TO_JSVAL(o);
     if (!JS_SetElement(cx, array, i, v.address())) {
       return NS_ERROR_FAILURE;
     }
   }
--- a/dom/contacts/fallback/ContactDB.jsm
+++ b/dom/contacts/fallback/ContactDB.jsm
@@ -101,17 +101,17 @@ this.ContactDB = function ContactDB(aGlo
 }
 
 ContactDB.prototype = {
   __proto__: IndexedDBHelper.prototype,
 
   _dispatcher: {},
 
   upgradeSchema: function upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) {
-    function loadInitialContacts() {
+    let loadInitialContacts = function() {
       // Add default contacts
       let jsm = {};
       Cu.import("resource://gre/modules/FileUtils.jsm", jsm);
       Cu.import("resource://gre/modules/NetUtil.jsm", jsm);
       // Loading resource://app/defaults/contacts.json doesn't work because
       // contacts.json is not in the omnijar.
       // So we look for the app dir instead and go from here...
       let contactsFile = jsm.FileUtils.getFile("DefRt", ["contacts.json"], false);
@@ -150,17 +150,17 @@ ContactDB.prototype = {
         contact.id = idService.generateUUID().toString().replace('-', '', 'g')
                                                         .replace('{', '')
                                                         .replace('}', '');
         contact = this.makeImport(contact);
         this.updateRecordMetadata(contact);
         if (DEBUG) debug("import: " + JSON.stringify(contact));
         objectStore.put(contact);
       }
-    }
+    }.bind(this);
 
     if (DEBUG) debug("upgrade schema from: " + aOldVersion + " to " + aNewVersion + " called!");
     let db = aDb;
     let objectStore;
 
     let steps = [
       function upgrade0to1() {
         /**
--- a/dom/locales/en-US/chrome/security/security.properties
+++ b/dom/locales/en-US/chrome/security/security.properties
@@ -4,8 +4,10 @@ BlockMixedDisplayContent = Blocked loadi
 BlockMixedActiveContent = Blocked loading mixed active content "%1$S"
 
 # CSP
 ReportOnlyCSPIgnored=Report-only CSP policy will be ignored because there are other non-report-only CSP policies applied.
 # LOCALIZATION NOTE: Do not translate "X-Content-Security-Policy", "X-Content-Security-Policy-Report-Only",  "Content-Security-Policy" or "Content-Security-Policy-Report-Only"
 OldCSPHeaderDeprecated=The X-Content-Security-Policy and X-Content-Security-Report-Only headers will be deprecated in the future. Please use the Content-Security-Policy and Content-Security-Report-Only headers with CSP spec compliant syntax instead.
 # LOCALIZATION NOTE: Do not translate "X-Content-Security-Policy/Report-Only" or "Content-Security-Policy/Report-Only"
 BothCSPHeadersPresent=This site specified both an X-Content-Security-Policy/Report-Only header and a Content-Security-Policy/Report-Only header. The X-Content-Security-Policy/Report-Only header(s) will be ignored.
+# LOCALIZATION NOTE: Do not translate "Strict-Transport-Security" or "HSTS"
+InvalidSTSHeaders=The site specified an invalid Strict-Transport-Security header.
--- a/dom/mobilemessage/interfaces/moz.build
+++ b/dom/mobilemessage/interfaces/moz.build
@@ -7,17 +7,16 @@
 XPIDL_SOURCES += [
     'nsIDOMMobileMessageManager.idl',
     'nsIDOMMozMmsEvent.idl',
     'nsIDOMMozMmsMessage.idl',
     'nsIDOMMozMobileMessageThread.idl',
     'nsIDOMMozSmsEvent.idl',
     'nsIDOMMozSmsMessage.idl',
     'nsIDOMSmsFilter.idl',
-    'nsIDOMSmsManager.idl',
     'nsIDOMSmsSegmentInfo.idl',
     'nsIMmsService.idl',
     'nsIMobileMessageCallback.idl',
     'nsIMobileMessageCursorCallback.idl',
     'nsIMobileMessageDatabaseService.idl',
     'nsIMobileMessageService.idl',
     'nsISmsService.idl',
     'nsIWapPushApplication.idl',
deleted file mode 100644
--- a/dom/mobilemessage/interfaces/nsIDOMSmsManager.idl
+++ /dev/null
@@ -1,44 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMEventTarget.idl"
-
-interface nsIDOMDOMCursor;
-interface nsIDOMDOMRequest;
-interface nsIDOMEventListener;
-interface nsIDOMMozSmsFilter;
-interface nsIDOMMozSmsSegmentInfo;
-
-[scriptable, builtinclass, uuid(8ce00d77-71b4-43f6-92a1-2eae7c9581b9)]
-interface nsIDOMMozSmsManager : nsIDOMEventTarget
-{
-  nsIDOMMozSmsSegmentInfo getSegmentInfoForText(in DOMString text);
-
-  // The first parameter can be either a DOMString (only one number) or an array
-  // of DOMStrings.
-  // The method returns a DOMRequest object if one number has been passed.
-  // An array of DOMRequest objects otherwise.
-  jsval send(in jsval number, in DOMString message);
-
-  [binaryname(GetMessageMoz)]
-  nsIDOMDOMRequest getMessage(in long id);
-
-  // The parameter can be either a message id or a SmsMessage.
-  nsIDOMDOMRequest delete(in jsval param);
-
-  // Iterates through nsIDOMMozSmsMessage.
-  nsIDOMDOMCursor getMessages(in nsIDOMMozSmsFilter filter, in boolean reverse);
-
-  nsIDOMDOMRequest markMessageRead(in long id, in boolean aValue);
-
-  // Iterates through nsIDOMMozMobileMessageThread.
-  nsIDOMDOMCursor getThreads();
-
-  [implicit_jscontext] attribute jsval onreceived;
-  [implicit_jscontext] attribute jsval onsending;
-  [implicit_jscontext] attribute jsval onsent;
-  [implicit_jscontext] attribute jsval onfailed;
-  [implicit_jscontext] attribute jsval ondeliverysuccess;
-  [implicit_jscontext] attribute jsval ondeliveryerror;
-};
--- a/dom/mobilemessage/src/MobileMessageCursorCallback.h
+++ b/dom/mobilemessage/src/MobileMessageCursorCallback.h
@@ -13,24 +13,22 @@
 
 class nsICursorContinueCallback;
 
 namespace mozilla {
 namespace dom {
 
 class DOMCursor;
 class MobileMessageManager;
-class SmsManager;
 
 namespace mobilemessage {
 
 class MobileMessageCursorCallback : public nsIMobileMessageCursorCallback
 {
   friend class mozilla::dom::MobileMessageManager;
-  friend class mozilla::dom::SmsManager;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIMOBILEMESSAGECURSORCALLBACK
 
   NS_DECL_CYCLE_COLLECTION_CLASS(MobileMessageCursorCallback)
 
   MobileMessageCursorCallback()
deleted file mode 100644
--- a/dom/mobilemessage/src/SmsManager.cpp
+++ /dev/null
@@ -1,502 +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 "SmsFilter.h"
-#include "SmsManager.h"
-#include "nsIDOMClassInfo.h"
-#include "nsISmsService.h"
-#include "nsIObserverService.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/Services.h"
-#include "Constants.h"
-#include "nsIDOMMozSmsEvent.h"
-#include "nsIDOMMozSmsMessage.h"
-#include "nsJSUtils.h"
-#include "nsContentUtils.h"
-#include "nsCxPusher.h"
-#include "nsIMobileMessageDatabaseService.h"
-#include "nsIXPConnect.h"
-#include "nsIPermissionManager.h"
-#include "GeneratedEvents.h"
-#include "MobileMessageCallback.h"
-#include "MobileMessageCursorCallback.h"
-#include "DOMCursor.h"
-
-#define RECEIVED_EVENT_NAME         NS_LITERAL_STRING("received")
-#define SENDING_EVENT_NAME          NS_LITERAL_STRING("sending")
-#define SENT_EVENT_NAME             NS_LITERAL_STRING("sent")
-#define FAILED_EVENT_NAME           NS_LITERAL_STRING("failed")
-#define DELIVERY_SUCCESS_EVENT_NAME NS_LITERAL_STRING("deliverysuccess")
-#define DELIVERY_ERROR_EVENT_NAME   NS_LITERAL_STRING("deliveryerror")
-
-using namespace mozilla::dom::mobilemessage;
-
-DOMCI_DATA(MozSmsManager, mozilla::dom::SmsManager)
-
-namespace mozilla {
-namespace dom {
-
-NS_INTERFACE_MAP_BEGIN(SmsManager)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMMozSmsManager)
-  NS_INTERFACE_MAP_ENTRY(nsIObserver)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozSmsManager)
-NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
-
-NS_IMPL_ADDREF_INHERITED(SmsManager, nsDOMEventTargetHelper)
-NS_IMPL_RELEASE_INHERITED(SmsManager, nsDOMEventTargetHelper)
-
-NS_IMPL_EVENT_HANDLER(SmsManager, received)
-NS_IMPL_EVENT_HANDLER(SmsManager, sending)
-NS_IMPL_EVENT_HANDLER(SmsManager, sent)
-NS_IMPL_EVENT_HANDLER(SmsManager, failed)
-NS_IMPL_EVENT_HANDLER(SmsManager, deliverysuccess)
-NS_IMPL_EVENT_HANDLER(SmsManager, deliveryerror)
-
-/* static */
-bool
-SmsManager::CreationIsAllowed(nsPIDOMWindow* aWindow)
-{
-  NS_ASSERTION(aWindow, "Null pointer!");
-
-#ifndef MOZ_WEBSMS_BACKEND
-  return false;
-#endif
-
-  // First of all, the general pref has to be turned on.
-  bool enabled = false;
-  Preferences::GetBool("dom.sms.enabled", &enabled);
-  NS_ENSURE_TRUE(enabled, false);
-
-  nsCOMPtr<nsIPermissionManager> permMgr =
-    do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
-  NS_ENSURE_TRUE(permMgr, false);
-
-  uint32_t permission = nsIPermissionManager::DENY_ACTION;
-  permMgr->TestPermissionFromWindow(aWindow, "sms", &permission);
-
-  if (permission != nsIPermissionManager::ALLOW_ACTION) {
-    return false;
-  }
-
-  // Check the Sms Service:
-  nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(smsService, false);
-
-  bool result = false;
-  smsService->HasSupport(&result);
-  if (!result) {
-    return false;
-  }
-
-  return true;
-}
-
-// static
-already_AddRefed<SmsManager>
-SmsManager::CreateInstance(nsPIDOMWindow* aWindow)
-{
-  nsRefPtr<SmsManager> smsMgr = new SmsManager();
-  smsMgr->Init(aWindow);
-
-  return smsMgr.forget();
-}
-
-void
-SmsManager::Init(nsPIDOMWindow *aWindow)
-{
-  BindToOwner(aWindow);
-
-  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-  // GetObserverService() can return null is some situations like shutdown.
-  if (!obs) {
-    return;
-  }
-
-  obs->AddObserver(this, kSmsReceivedObserverTopic, false);
-  obs->AddObserver(this, kSmsSendingObserverTopic, false);
-  obs->AddObserver(this, kSmsSentObserverTopic, false);
-  obs->AddObserver(this, kSmsFailedObserverTopic, false);
-  obs->AddObserver(this, kSmsDeliverySuccessObserverTopic, false);
-  obs->AddObserver(this, kSmsDeliveryErrorObserverTopic, false);
-}
-
-void
-SmsManager::Shutdown()
-{
-  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-  // GetObserverService() can return null is some situations like shutdown.
-  if (!obs) {
-    return;
-  }
-
-  obs->RemoveObserver(this, kSmsReceivedObserverTopic);
-  obs->RemoveObserver(this, kSmsSendingObserverTopic);
-  obs->RemoveObserver(this, kSmsSentObserverTopic);
-  obs->RemoveObserver(this, kSmsFailedObserverTopic);
-  obs->RemoveObserver(this, kSmsDeliverySuccessObserverTopic);
-  obs->RemoveObserver(this, kSmsDeliveryErrorObserverTopic);
-}
-
-NS_IMETHODIMP
-SmsManager::GetSegmentInfoForText(const nsAString& aText,
-                                  nsIDOMMozSmsSegmentInfo** aResult)
-{
-  nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(smsService, NS_ERROR_FAILURE);
-
-  return smsService->GetSegmentInfoForText(aText, aResult);
-}
-
-nsresult
-SmsManager::Send(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<JSString*> aNumber,
-                 const nsAString& aMessage, JS::Value* aRequest)
-{
-  nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(smsService, NS_ERROR_FAILURE);
-
-  nsDependentJSString number;
-  number.init(aCx, aNumber);
-
-  nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
-  nsCOMPtr<nsIMobileMessageCallback> msgCallback =
-    new MobileMessageCallback(request);
-
-  nsresult rv = smsService->Send(number, aMessage, msgCallback);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  JS::Rooted<JSObject*> global(aCx, aGlobal);
-  rv = nsContentUtils::WrapNative(aCx, global,
-                                  static_cast<nsIDOMDOMRequest*>(request.get()),
-                                  aRequest);
-  if (NS_FAILED(rv)) {
-    NS_ERROR("Failed to create the js value!");
-    return rv;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-SmsManager::Send(const JS::Value& aNumber, const nsAString& aMessage, JS::Value* aReturn)
-{
-  nsresult rv;
-  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
-  NS_ENSURE_STATE(sc);
-  AutoPushJSContext cx(sc->GetNativeContext());
-  NS_ASSERTION(cx, "Failed to get a context!");
-
-  if (!aNumber.isString() &&
-      !(aNumber.isObject() && JS_IsArrayObject(cx, &aNumber.toObject()))) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  JS::Rooted<JSObject*> global(cx, sc->GetNativeGlobal());
-  NS_ASSERTION(global, "Failed to get global object!");
-
-  JSAutoCompartment ac(cx, global);
-
-  if (aNumber.isString()) {
-    JS::Rooted<JSString*> number(cx, aNumber.toString());
-    return Send(cx, global, number, aMessage, aReturn);
-  }
-
-  // Must be an object then.
-  if (!aNumber.isObject()) {
-    return NS_ERROR_FAILURE;
-  }
-
-  JS::Rooted<JSObject*> numbers(cx, &aNumber.toObject());
-  uint32_t size;
-  if (!JS_GetArrayLength(cx, numbers, &size)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  JS::AutoValueVector requests(cx);
-  if (!requests.resize(size)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  JS::RootedString str(cx);
-  for (uint32_t i = 0; i < size; ++i) {
-    JS::Rooted<JS::Value> number(cx);
-    if (!JS_GetElement(cx, numbers, i, number.address())) {
-      return NS_ERROR_INVALID_ARG;
-    }
-
-    str = JS_ValueToString(cx, number);
-    if (!str) {
-      return NS_ERROR_FAILURE;
-    }
-
-    nsresult rv = Send(cx, global, str, aMessage, &requests[i]);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  JSObject* obj = JS_NewArrayObject(cx, requests.length(), requests.begin());
-  if (!obj) {
-    return NS_ERROR_FAILURE;
-  }
-
-  aReturn->setObject(*obj);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-SmsManager::GetMessageMoz(int32_t aId, nsIDOMDOMRequest** aRequest)
-{
-  nsCOMPtr<nsIMobileMessageDatabaseService> dbService =
-    do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(dbService, NS_ERROR_FAILURE);
-
-  nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
-  nsCOMPtr<nsIMobileMessageCallback> msgCallback =
-    new MobileMessageCallback(request);
-
-  nsresult rv = dbService->GetMessageMoz(aId, msgCallback);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  request.forget(aRequest);
-  return NS_OK;
-}
-
-nsresult
-SmsManager::GetSmsMessageId(AutoPushJSContext &aCx,
-                            const JS::Value &aSmsMessage, int32_t &aId)
-{
-  nsCOMPtr<nsIDOMMozSmsMessage> message =
-    do_QueryInterface(nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, &aSmsMessage.toObject()));
-  NS_ENSURE_TRUE(message, NS_ERROR_INVALID_ARG);
-
-  return message->GetId(&aId);
-}
-
-NS_IMETHODIMP
-SmsManager::Delete(const JS::Value& aParam, nsIDOMDOMRequest** aRequest)
-{
-  // We expect Int32, SmsMessage, Int32[], SmsMessage[]
-  if (!aParam.isObject() && !aParam.isInt32()) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  nsresult rv;
-  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
-  AutoPushJSContext cx(sc->GetNativeContext());
-  NS_ENSURE_STATE(sc);
-
-  int32_t id, *idArray;
-  uint32_t size;
-
-  if (aParam.isInt32()) {
-    // Single Integer Message ID
-    id = aParam.toInt32();
-
-    size = 1;
-    idArray = &id;
-  } else if (!JS_IsArrayObject(cx, &aParam.toObject())) {
-    // Single SmsMessage object
-    rv = GetSmsMessageId(cx, aParam, id);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    size = 1;
-    idArray = &id;
-  } else {
-    // Int32[] or SmsMessage[]
-    JS::Rooted<JSObject*> ids(cx, &aParam.toObject());
-
-    JS_ALWAYS_TRUE(JS_GetArrayLength(cx, ids, &size));
-    nsAutoArrayPtr<int32_t> idAutoArray(new int32_t[size]);
-
-    JS::Rooted<JS::Value> idJsValue(cx);
-    for (uint32_t i = 0; i < size; i++) {
-      if (!JS_GetElement(cx, ids, i, idJsValue.address())) {
-        return NS_ERROR_INVALID_ARG;
-      }
-
-      if (idJsValue.get().isInt32()) {
-        idAutoArray[i] = idJsValue.get().toInt32();
-      } else if (idJsValue.get().isObject()) {
-        rv = GetSmsMessageId(cx, idJsValue, id);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        idAutoArray[i] = id;
-      }
-    }
-
-    idArray = idAutoArray.forget();
-  }
-
-  nsCOMPtr<nsIMobileMessageDatabaseService> dbService =
-    do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(dbService, NS_ERROR_FAILURE);
-
-  nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
-  nsCOMPtr<nsIMobileMessageCallback> msgCallback =
-    new MobileMessageCallback(request);
-
-  rv = dbService->DeleteMessage(idArray, size, msgCallback);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  request.forget(aRequest);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-SmsManager::GetMessages(nsIDOMMozSmsFilter* aFilter,
-                        bool aReverse,
-                        nsIDOMDOMCursor** aCursor)
-{
-  nsCOMPtr<nsIMobileMessageDatabaseService> dbService =
-    do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(dbService, NS_ERROR_FAILURE);
-
-  nsCOMPtr<nsIDOMMozSmsFilter> filter = aFilter;
-  if (!filter) {
-    filter = new SmsFilter();
-  }
-
-  nsRefPtr<MobileMessageCursorCallback> cursorCallback =
-    new MobileMessageCursorCallback();
-
-  nsCOMPtr<nsICursorContinueCallback> continueCallback;
-  nsresult rv = dbService->CreateMessageCursor(filter, aReverse, cursorCallback,
-                                               getter_AddRefs(continueCallback));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  cursorCallback->mDOMCursor = new DOMCursor(GetOwner(), continueCallback);
-  NS_ADDREF(*aCursor = cursorCallback->mDOMCursor);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-SmsManager::MarkMessageRead(int32_t aId, bool aValue,
-                            nsIDOMDOMRequest** aRequest)
-{
-  nsCOMPtr<nsIMobileMessageDatabaseService> dbService =
-    do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(dbService, NS_ERROR_FAILURE);
-
-  nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
-  nsCOMPtr<nsIMobileMessageCallback> msgCallback =
-    new MobileMessageCallback(request);
-
-  nsresult rv = dbService->MarkMessageRead(aId, aValue, msgCallback);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  request.forget(aRequest);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-SmsManager::GetThreads(nsIDOMDOMCursor** aCursor)
-{
-  nsCOMPtr<nsIMobileMessageDatabaseService> dbService =
-    do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(dbService, NS_ERROR_FAILURE);
-
-  nsRefPtr<MobileMessageCursorCallback> cursorCallback =
-    new MobileMessageCursorCallback();
-
-  nsCOMPtr<nsICursorContinueCallback> continueCallback;
-  nsresult rv = dbService->CreateThreadCursor(cursorCallback,
-                                              getter_AddRefs(continueCallback));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  cursorCallback->mDOMCursor = new DOMCursor(GetOwner(), continueCallback);
-  NS_ADDREF(*aCursor = cursorCallback->mDOMCursor);
-
-  return NS_OK;
-}
-
-nsresult
-SmsManager::DispatchTrustedSmsEventToSelf(const nsAString& aEventName, nsIDOMMozSmsMessage* aMessage)
-{
-  nsCOMPtr<nsIDOMEvent> event;
-  NS_NewDOMMozSmsEvent(getter_AddRefs(event), this, nullptr, nullptr);
-  NS_ASSERTION(event, "This should never fail!");
-
-  nsCOMPtr<nsIDOMMozSmsEvent> se = do_QueryInterface(event);
-  MOZ_ASSERT(se);
-  nsresult rv = se->InitMozSmsEvent(aEventName, false, false, aMessage);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return DispatchTrustedEvent(event);
-}
-
-NS_IMETHODIMP
-SmsManager::Observe(nsISupports* aSubject, const char* aTopic,
-                    const PRUnichar* aData)
-{
-  if (!strcmp(aTopic, kSmsReceivedObserverTopic)) {
-    nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
-    if (!message) {
-      NS_ERROR("Got a 'sms-received' topic without a valid message!");
-      return NS_OK;
-    }
-
-    DispatchTrustedSmsEventToSelf(RECEIVED_EVENT_NAME, message);
-    return NS_OK;
-  }
-
-  if (!strcmp(aTopic, kSmsSendingObserverTopic)) {
-    nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
-    if (!message) {
-      NS_ERROR("Got a 'sms-sending' topic without a valid message!");
-      return NS_OK;
-    }
-
-    DispatchTrustedSmsEventToSelf(SENDING_EVENT_NAME, message);
-    return NS_OK;
-  }
-
-  if (!strcmp(aTopic, kSmsSentObserverTopic)) {
-    nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
-    if (!message) {
-      NS_ERROR("Got a 'sms-sent' topic without a valid message!");
-      return NS_OK;
-    }
-
-    DispatchTrustedSmsEventToSelf(SENT_EVENT_NAME, message);
-    return NS_OK;
-  }
-
-  if (!strcmp(aTopic, kSmsFailedObserverTopic)) {
-    nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
-    if (!message) {
-      NS_ERROR("Got a 'sms-failed' topic without a valid message!");
-      return NS_OK;
-    }
-
-    DispatchTrustedSmsEventToSelf(FAILED_EVENT_NAME, message);
-    return NS_OK;
-  }
-
-  if (!strcmp(aTopic, kSmsDeliverySuccessObserverTopic)) {
-    nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
-    if (!message) {
-      NS_ERROR("Got a 'sms-delivery-success' topic without a valid message!");
-      return NS_OK;
-    }
-
-    DispatchTrustedSmsEventToSelf(DELIVERY_SUCCESS_EVENT_NAME, message);
-    return NS_OK;
-  }
-
-  if (!strcmp(aTopic, kSmsDeliveryErrorObserverTopic)) {
-    nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
-    if (!message) {
-      NS_ERROR("Got a 'sms-delivery-error' topic without a valid message!");
-      return NS_OK;
-    }
-
-    DispatchTrustedSmsEventToSelf(DELIVERY_ERROR_EVENT_NAME, message);
-    return NS_OK;
-  }
-
-  return NS_OK;
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/mobilemessage/src/SmsManager.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_mobilemessage_SmsManager_h
-#define mozilla_dom_mobilemessage_SmsManager_h
-
-#include "nsIDOMSmsManager.h"
-#include "nsIObserver.h"
-#include "nsDOMEventTargetHelper.h"
-
-class nsIDOMMozSmsMessage;
-
-namespace mozilla {
-namespace dom {
-
-class SmsManager : public nsDOMEventTargetHelper
-                 , public nsIDOMMozSmsManager
-                 , public nsIObserver
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIOBSERVER
-  NS_DECL_NSIDOMMOZSMSMANAGER
-
-  NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
-
-  static already_AddRefed<SmsManager>
-  CreateInstance(nsPIDOMWindow *aWindow);
-
-  static bool
-  CreationIsAllowed(nsPIDOMWindow *aWindow);
-
-  void Init(nsPIDOMWindow *aWindow);
-  void Shutdown();
-
-private:
-  /**
-   * Internal Send() method used to send one message.
-   */
-  nsresult Send(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<JSString*> aNumber,
-                const nsAString& aMessage, JS::Value* aRequest);
-
-  nsresult DispatchTrustedSmsEventToSelf(const nsAString& aEventName,
-                                         nsIDOMMozSmsMessage* aMessage);
-
-  /**
-   * Helper to get message ID from SMS Message object
-   */
-  nsresult GetSmsMessageId(AutoPushJSContext &aCx, const JS::Value &aSmsMessage,
-                           int32_t &aId);
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_mobilemessage_SmsManager_h
--- a/dom/mobilemessage/src/moz.build
+++ b/dom/mobilemessage/src/moz.build
@@ -37,33 +37,31 @@ else:
         'MobileMessageDatabaseService.cpp',
         'MmsService.cpp',
     ]
 
 EXPORTS.mozilla.dom += [
     'MmsMessage.h',
     'MobileMessageManager.h',
     'SmsFilter.h',
-    'SmsManager.h',
     'SmsMessage.h',
     'SmsSegmentInfo.h',
 ]
 
 CPP_SOURCES += [
     'Constants.cpp',
     'MmsMessage.cpp',
     'MobileMessageCallback.cpp',
     'MobileMessageCursorCallback.cpp',
     'MobileMessageManager.cpp',
     'MobileMessageService.cpp',
     'MobileMessageThread.cpp',
     'SmsChild.cpp',
     'SmsFilter.cpp',
     'SmsIPCService.cpp',
-    'SmsManager.cpp',
     'SmsMessage.cpp',
     'SmsParent.cpp',
     'SmsSegmentInfo.cpp',
     'SmsService.cpp',
     'SmsServicesFactory.cpp',
 ]
 
 IPDL_SOURCES += [
--- a/dom/mobilemessage/tests/marionette/test_between_emulators.py
+++ b/dom/mobilemessage/tests/marionette/test_between_emulators.py
@@ -12,27 +12,27 @@ class SMSTest(MarionetteTestCase):
         receiver = self.marionette
 
         self.set_up_test_page(sender, "test.html", ["sms"])
         self.set_up_test_page(receiver, "test.html", ["sms"])
 
         # Setup the event listsener on the receiver, which should store
         # a global variable when an SMS is received.
         message = 'hello world!'
-        self.assertTrue(receiver.execute_script("return window.navigator.mozSms != null;"))
+        self.assertTrue(receiver.execute_script("return window.navigator.mozMobileMessage != null;"))
         receiver.execute_script("""
 global.smsreceived = null;
-window.navigator.mozSms.addEventListener("received", function(e) {
+window.navigator.mozMobileMessage.addEventListener("received", function(e) {
     global.smsreceived = e.message.body;
 });
 """, new_sandbox=False)
 
         # Send the SMS from the sender.
         sender.execute_script("""
-window.navigator.mozSms.send("%d", "%s");
+window.navigator.mozMobileMessage.send("%d", "%s");
 """ % (receiver.emulator.port, message))
 
         # On the receiver, wait up to 10s for an SMS to be received, by 
         # checking the value of the global var that the listener will change.
         receiver.set_script_timeout(0) # TODO no timeout for now since the test fails
         received = receiver.execute_async_script("""
         waitFor(function () {
             marionetteScriptFinished(global.smsreceived);
--- a/dom/mobilemessage/tests/marionette/test_bug814761.js
+++ b/dom/mobilemessage/tests/marionette/test_bug814761.js
@@ -1,22 +1,24 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
+ok(manager instanceof MozMobileMessageManager,
+   "manager is instance of " + manager.constructor);
 
 // Note: 378 chars and below is fine, but 379 and above will cause the issue.
 // Sending first message works, but second one we get emulator callback but
 // the actual SMS is never received, so script will timeout waiting for the
-// sms.onreceived event. Also note that a single larger message (i.e. 1600
+// onreceived event. Also note that a single larger message (i.e. 1600
 // characters) works; so it is not a compounded send limit.
 let fromNumber = "5551110000";
 let msgLength = 379;
 let msgText = new Array(msgLength + 1).join('a');
 
 let pendingEmulatorCmdCount = 0;
 function sendSmsToEmulator(from, text) {
   ++pendingEmulatorCmdCount;
@@ -36,19 +38,19 @@ function firstIncomingSms() {
 function secondIncomingSms() {
   simulateIncomingSms(cleanUp);
 }
 
 function simulateIncomingSms(nextFunction) {
   log("Simulating incoming multipart SMS (" + msgText.length
       + " chars total).");
 
-  sms.onreceived = function onreceived(event) {
-    log("Received 'onreceived' smsmanager event.");
-    sms.onreceived = null;
+  manager.onreceived = function onreceived(event) {
+    log("Received 'onreceived' event.");
+    manager.onreceived = null;
 
     let incomingSms = event.message;
     ok(incomingSms, "incoming sms");
     is(incomingSms.body, msgText, "msg body");
 
     window.setTimeout(nextFunction, 0);
   };
 
--- a/dom/mobilemessage/tests/marionette/test_emulator_loopback.js
+++ b/dom/mobilemessage/tests/marionette/test_emulator_loopback.js
@@ -9,18 +9,19 @@ SpecialPowers.setBoolPref("dom.sms.enabl
 SpecialPowers.addPermission("sms", true, document);
 
 function cleanUp() {
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   finish();
 }
 
-let sms = window.navigator.mozSms;
-ok(sms instanceof MozSmsManager);
+let manager = window.navigator.mozMobileMessage;
+ok(manager instanceof MozMobileMessageManager,
+   "manager is instance of " + manager.constructor);
 
 function randomString16() {
   return Math.random().toString(36).substr(2, 16);
 }
 
 function times(str, n) {
   return (new Array(n + 1)).join(str);
 }
@@ -28,26 +29,26 @@ function times(str, n) {
 function repeat(func, array, oncomplete) {
   (function do_call(index) {
     let next = index < (array.length - 1) ? do_call.bind(null, index + 1) : oncomplete;
     func.apply(null, [array[index], next]);
   })(0);
 }
 
 function doTest(body, callback) {
-  sms.addEventListener("received", function onReceived(event) {
+  manager.addEventListener("received", function onReceived(event) {
     event.target.removeEventListener(event.type, arguments.callee);
 
     let message = event.message;
     is(message.body, body, "message.body");
 
     window.setTimeout(callback, 0);
   });
 
-  let request = sms.send(SELF, body);
+  let request = manager.send(SELF, body);
   request.onerror = function onerror() {
     ok(false, "failed to send message '" + body + "' to '" + SELF + "'");
   };
 }
 
 repeat(doTest, [
   // Random alphanumeric string of 16 characters.
   randomString16(),
--- a/dom/mobilemessage/tests/marionette/test_filter_date.js
+++ b/dom/mobilemessage/tests/marionette/test_filter_date.js
@@ -1,32 +1,33 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.addPermission("sms", true, document);
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let numberMsgs = 10;
 let smsList = new Array();
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   // Ensure test is starting clean with no existing sms messages
   deleteAllMsgs(simulateIncomingSms);
 }
 
 function deleteAllMsgs(nextFunction) {
   let msgList = new Array();
   let filter = new MozSmsFilter;
 
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     // Check if message was found
     if (cursor.result) {
       msgList.push(cursor.result.id);
       // Now get next message in the list
@@ -41,51 +42,51 @@ function deleteAllMsgs(nextFunction) {
         nextFunction();
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function deleteMsgs(msgList, nextFunction) {
   let smsId = msgList.shift();
 
   log("Deleting SMS (id: " + smsId + ").");
-  let request = sms.delete(smsId);
+  let request = manager.delete(smsId);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       // Message deleted, continue until none are left
       if (msgList.length) {
         deleteMsgs(msgList, nextFunction);
       } else {
         log("Finished deleting SMS messages.");
         nextFunction();
       }
     } else {
       log("SMS delete failed.");
-      ok(false,"sms.delete request returned false");
+      ok(false,"manager.delete request returned false");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function simulateIncomingSms() {
   let text = "Incoming SMS number " + (smsList.length + 1);
   let remoteNumber = "5552229797";
@@ -97,17 +98,17 @@ function simulateIncomingSms() {
   rcvdEmulatorCallback = false;
   runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
     is(result[0], "OK", "emulator callback");
     rcvdEmulatorCallback = true;
   });
 }
 
 // Callback for incoming sms
-sms.onreceived = function onreceived(event) {
+manager.onreceived = function onreceived(event) {
   log("Received 'onreceived' sms event.");
   let incomingSms = event.message;
   log("Received SMS (id: " + incomingSms.id + ").");
 
   smsList.push(incomingSms);
 
   // Wait for emulator to catch up before continuing
   waitFor(nextRep,function() {
@@ -131,17 +132,17 @@ function getMsgs() {
   // Set filter for start date yesterday and end date tomorrow
   let yesterday = new Date(Date.now() - 86400000); // 24 hours = 86400000 ms
   let tomorrow = new Date(Date.now() + 86400000);
   filter.startDate = yesterday;
   filter.endDate = tomorrow;
 
   log("Getting SMS messages with dates between " + yesterday + " and "
       + tomorrow +".");
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     log("Received 'onsuccess' event.");
 
     if (cursor.result) {
       // Another message found
@@ -154,41 +155,41 @@ function getMsgs() {
       // No more messages; ensure correct number found
       if (foundSmsList.length == smsList.length) {
         log("SMS getMessages returned " + foundSmsList.length +
             " messages as expected.");
         verifyFoundMsgs(foundSmsList);
       } else {
         log("SMS getMessages returned " + foundSmsList.length +
             " messages, but expected " + smsList.length + ".");
-        ok(false, "Incorrect number of messages returned by sms.getMessages");
+        ok(false, "Incorrect number of messages returned by manager.getMessages");
         deleteAllMsgs(cleanUp);
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function verifyFoundMsgs(foundSmsList) {
   for (var x = 0; x < foundSmsList.length; x++) {
     is(foundSmsList[x].id, smsList[x].id, "id");
     is(foundSmsList[x].timestamp.getTime(), smsList[x].timestamp.getTime(),
         "timestmap");
   }
   deleteAllMsgs(cleanUp);
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_filter_date_notfound.js
+++ b/dom/mobilemessage/tests/marionette/test_filter_date_notfound.js
@@ -1,32 +1,33 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.addPermission("sms", true, document);
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let numberMsgs = 10;
 let smsList = new Array();
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   // Ensure test is starting clean with no existing sms messages
   deleteAllMsgs(simulateIncomingSms);
 }
 
 function deleteAllMsgs(nextFunction) {
   let msgList = new Array();
   let filter = new MozSmsFilter;
 
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     // Check if message was found
     if (cursor.result) {
       msgList.push(cursor.result.id);
       // Now get next message in the list
@@ -41,51 +42,51 @@ function deleteAllMsgs(nextFunction) {
         nextFunction();
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function deleteMsgs(msgList, nextFunction) {
   let smsId = msgList.shift();
 
   log("Deleting SMS (id: " + smsId + ").");
-  let request = sms.delete(smsId);
+  let request = manager.delete(smsId);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       // Message deleted, continue until none are left
       if (msgList.length) {
         deleteMsgs(msgList, nextFunction);
       } else {
         log("Finished deleting SMS messages.");
         nextFunction();
       }
     } else {
       log("SMS delete failed.");
-      ok(false,"sms.delete request returned false");
+      ok(false,"manager.delete request returned false");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function simulateIncomingSms() {
   let text = "Incoming SMS number " + (smsList.length + 1);
   let remoteNumber = "5552229797";
@@ -97,17 +98,17 @@ function simulateIncomingSms() {
   rcvdEmulatorCallback = false;
   runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
     is(result[0], "OK", "emulator callback");
     rcvdEmulatorCallback = true;
   });
 }
 
 // Callback for incoming sms
-sms.onreceived = function onreceived(event) {
+manager.onreceived = function onreceived(event) {
   log("Received 'onreceived' sms event.");
   let incomingSms = event.message;
   log("Received SMS (id: " + incomingSms.id + ").");
 
   smsList.push(incomingSms);
 
   // Wait for emulator to catch up before continuing
   waitFor(nextRep,function() {
@@ -131,17 +132,17 @@ function getMsgs() {
   // Set filter for start date 2 days ago and end date yesterday (so 0 found)
   let yesterday = new Date(Date.now() - 86400000); // 24 hours = 86400000 ms
   let twoDaysAgo = new Date(Date.now() - 172800000);
   filter.startDate = twoDaysAgo;
   filter.endDate = yesterday;
 
   log("Getting SMS messages with dates between " + twoDaysAgo + " and "
       + yesterday +".");
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     log("Received 'onsuccess' event.");
 
     if (cursor.result) {
       // Another message found
@@ -153,23 +154,23 @@ function getMsgs() {
       log("SMS getMessages returned zero messages as expected.");
     }
     deleteAllMsgs(cleanUp);
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_filter_mixed.js
+++ b/dom/mobilemessage/tests/marionette/test_filter_mixed.js
@@ -4,18 +4,19 @@
 MARIONETTE_TIMEOUT = 60000;
 
 const SELF = 5554;
 const NUM_THREADS = 10;
 
 SpecialPowers.addPermission("sms", true, document);
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 
-let sms = window.navigator.mozSms;
-ok(sms instanceof MozSmsManager);
+let manager = window.navigator.mozMobileMessage;
+ok(manager instanceof MozMobileMessageManager,
+   "manager is instance of " + manager.constructor);
 
 let pendingEmulatorCmdCount = 0;
 function sendSmsToEmulator(from, text) {
   ++pendingEmulatorCmdCount;
 
   let cmd = "sms send " + from + " " + text;
   runEmulatorCmd(cmd, function (result) {
     --pendingEmulatorCmdCount;
@@ -57,17 +58,17 @@ let tasks = {
   }
 };
 
 function getAllMessages(callback, filter, reverse) {
   if (!filter) {
     filter = new MozSmsFilter;
   }
   let messages = [];
-  let request = sms.getMessages(filter, reverse || false);
+  let request = manager.getMessages(filter, reverse || false);
   request.onsuccess = function(event) {
     if (request.result) {
       messages.push(request.result);
       request.continue();
       return;
     }
 
     window.setTimeout(callback.bind(null, messages), 0);
@@ -78,17 +79,17 @@ function deleteAllMessages(next) {
   getAllMessages(function deleteAll(messages) {
     let message = messages.shift();
     if (!message) {
       ok(true, "all messages deleted");
       tasks.next();
       return;
     }
 
-    let request = sms.delete(message.id);
+    let request = manager.delete(message.id);
     request.onsuccess = deleteAll.bind(null, messages);
     request.onerror = function (event) {
       ok(false, "failed to delete all messages");
       tasks.finish();
     }
   });
 }
 
@@ -119,41 +120,41 @@ tasks.push(deleteAllMessages);
  *   send    to   "+15555315559"
  *   receive from "5555315559", count = 10
  */
 let threadIds = [];
 tasks.push(function populateMessages() {
   let count = 0;
 
   function sendMessage(iter) {
-    let request = sms.send("+1555531555" + iter, "Nice to meet you");
+    let request = manager.send("+1555531555" + iter, "Nice to meet you");
     request.onsuccess = function onRequestSuccess(event) {
-      sms.addEventListener("received", onReceived);
+      manager.addEventListener("received", onReceived);
 
       threadIds.push(request.result.threadId);
 
       sendSmsToEmulator("555531555" + iter, "Nice to meet you, too");
     }
     request.onerror = function onRequestError(event) {
       tasks.finish();
     }
   }
 
   function onReceived(event) {
-    sms.removeEventListener("received", onReceived);
+    manager.removeEventListener("received", onReceived);
 
     if (event.message.threadId != threadIds[threadIds.length - 1]) {
       ok(false, "Thread IDs of sent and received message mismatch.");
       tasks.finish();
       return;
     }
 
     ++count;
     if (count % 2) {
-      let request = sms.markMessageRead(event.message.id, true);
+      let request = manager.markMessageRead(event.message.id, true);
       request.onsuccess = function onRequestSuccess(event) {
         if (count < NUM_THREADS) {
           sendMessage(count);
         } else {
           tasks.next();
         }
       }
       request.onerror = function onRequestError(event) {
--- a/dom/mobilemessage/tests/marionette/test_filter_number_multiple.js
+++ b/dom/mobilemessage/tests/marionette/test_filter_number_multiple.js
@@ -1,34 +1,35 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.addPermission("sms", true, document);
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let numberMsgs = 10;
 let smsList = new Array();
 let defaultRemoteNumber = "+15552227777";
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   // Ensure test is starting clean with no existing sms messages
   deleteAllMsgs(sendSms);
 }
 
 function deleteAllMsgs(nextFunction) {
   // Check for any existing SMS messages, if any are found delete them
   let msgList = new Array();
   let filter = new MozSmsFilter;
 
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     // Check if message was found
     if (cursor.result) {
       msgList.push(cursor.result.id);
       // Now get next message in the list
@@ -43,97 +44,97 @@ function deleteAllMsgs(nextFunction) {
         nextFunction();
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function deleteMsgs(msgList, nextFunction) {
   // Delete the SMS messages specified in the given list
   let smsId = msgList.shift();
 
   log("Deleting SMS (id: " + smsId + ").");
-  let request = sms.delete(smsId);
+  let request = manager.delete(smsId);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       // Message deleted, continue until none are left
       if (msgList.length) {
         deleteMsgs(msgList, nextFunction);
       } else {
         log("Finished deleting SMS messages.");
         nextFunction();
       }
     } else {
       log("SMS delete failed.");
-      ok(false,"sms.delete request returned false");
+      ok(false,"manager.delete request returned false");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function sendSms() {
   // Send an SMS to a unique number that will fall outside of the filter
   let gotSmsSent = false;
   let gotRequestSuccess = false;
   let remoteNumber = "+15558120649";
   let text = "Outgoing SMS brought to you by Firefox OS!";
 
   log("Sending an SMS.");
 
-  sms.onsent = function(event) {
-    log("Received 'onsent' smsmanager event.");
+  manager.onsent = function(event) {
+    log("Received 'onsent' event.");
     gotSmsSent = true;
     log("Sent SMS (id: " + event.message.id + ").");
     if (gotSmsSent && gotRequestSuccess) {
       simulateIncomingSms();
     }
   };
 
-  let request = sms.send(remoteNumber, text);
+  let request = manager.send(remoteNumber, text);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       gotRequestSuccess = true;
       if (gotSmsSent && gotRequestSuccess) {
         simulateIncomingSms();
       }
     } else {
-      log("smsrequest returned false for sms.send");
+      log("smsrequest returned false for manager.send");
       ok(false,"SMS send failed");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.send request returned unexpected error: "
+    ok(false, "manager.send request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function simulateIncomingSms(remoteNumber) {
   // Simulate incoming SMS messages from specified (or default) remote number
   let text = "Incoming SMS number " + (smsList.length + 1);
@@ -146,17 +147,17 @@ function simulateIncomingSms(remoteNumbe
   // Simulate incoming SMS sent from remoteNumber to our emulator
   rcvdEmulatorCallback = false;
   runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
     is(result[0], "OK", "emulator callback");
     rcvdEmulatorCallback = true;
   });
 }
 
-sms.onreceived = function onreceived(event) {
+manager.onreceived = function onreceived(event) {
   // Callback for incoming SMS
   log("Received 'onreceived' sms event.");
   let incomingSms = event.message;
   log("Received SMS (id: " + incomingSms.id + ").");
 
   smsList.push(incomingSms);
 
   // Wait for emulator to catch up before continuing
@@ -185,17 +186,17 @@ function getMsgs(secondNumber) {
   var filter = new MozSmsFilter();
   let foundSmsList = new Array();
 
   // Set filter for default and second number
   filter.numbers = new Array(defaultRemoteNumber, secondNumber);
 
   log("Getting the SMS messages with numbers " + defaultRemoteNumber + " and "
       + secondNumber + ".");
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     log("Received 'onsuccess' event.");
 
     if (cursor.result) {
       // Another message found
@@ -208,41 +209,41 @@ function getMsgs(secondNumber) {
       // No more messages; ensure correct number of SMS messages were found
       if (foundSmsList.length == smsList.length) {
         log("SMS getMessages returned " + foundSmsList.length +
             " messages as expected.");
         verifyFoundMsgs(foundSmsList);
       } else {
         log("SMS getMessages returned " + foundSmsList.length +
             " messages, but expected " + smsList.length + ".");
-        ok(false, "Incorrect number of messages returned by sms.getMessages");
+        ok(false, "Incorrect number of messages returned by manager.getMessages");
         deleteAllMsgs(cleanUp);
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function verifyFoundMsgs(foundSmsList) {
   // Verify the SMS messages returned by getMessages are the correct ones
   for (var x = 0; x < foundSmsList.length; x++) {
     is(foundSmsList[x].id, smsList[x].id, "id");
     is(foundSmsList[x].sender, smsList[x].sender, "number");
   }
   deleteAllMsgs(cleanUp);
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_filter_number_single.js
+++ b/dom/mobilemessage/tests/marionette/test_filter_number_single.js
@@ -1,34 +1,35 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.addPermission("sms", true, document);
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let numberMsgs = 10;
 let smsList = new Array();
 let defaultRemoteNumber = "+15552227777";
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   // Ensure test is starting clean with no existing sms messages
   deleteAllMsgs(simulateIncomingSms);
 }
 
 function deleteAllMsgs(nextFunction) {
   // Check for any existing SMS messages, if any are found delete them
   let msgList = new Array();
   let filter = new MozSmsFilter;
 
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     // Check if message was found
     if (cursor.result) {
       msgList.push(cursor.result.id);
       // Now get next message in the list
@@ -43,52 +44,52 @@ function deleteAllMsgs(nextFunction) {
         nextFunction();
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function deleteMsgs(msgList, nextFunction) {
   // Delete the SMS messages specified in the given list
   let smsId = msgList.shift();
 
   log("Deleting SMS (id: " + smsId + ").");
-  let request = sms.delete(smsId);
+  let request = manager.delete(smsId);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       // Message deleted, continue until none are left
       if (msgList.length) {
         deleteMsgs(msgList, nextFunction);
       } else {
         log("Finished deleting SMS messages.");
         nextFunction();
       }
     } else {
       log("SMS delete failed.");
-      ok(false,"sms.delete request returned false");
+      ok(false,"manager.delete request returned false");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function simulateIncomingSms(remoteNumber) {
   // Simulate incoming SMS messages from specified (or default) remote number
   let text = "Incoming SMS number " + (smsList.length + 1);
@@ -101,17 +102,17 @@ function simulateIncomingSms(remoteNumbe
   // Simulate incoming sms sent from remoteNumber to our emulator
   rcvdEmulatorCallback = false;
   runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
     is(result[0], "OK", "emulator callback");
     rcvdEmulatorCallback = true;
   });
 }
 
-sms.onreceived = function onreceived(event) {
+manager.onreceived = function onreceived(event) {
   // Callback for incoming SMS
   log("Received 'onreceived' sms event.");
   let incomingSms = event.message;
   log("Received SMS (id: " + incomingSms.id + ").");
 
   smsList.push(incomingSms);
 
   // Wait for emulator to catch up before continuing
@@ -143,17 +144,17 @@ function getMsgs() {
   smsList = smsList.filter(function(i) {
     return i.sender != defaultRemoteNumber ? false: true;
   });
 
   // Set filter for default remote number
   filter.numbers = new Array(defaultRemoteNumber);
 
   log("Getting the SMS messages from sender " + defaultRemoteNumber + ".");
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     log("Received 'onsuccess' event.");
 
     if (cursor.result) {
       // Another message found
@@ -166,41 +167,41 @@ function getMsgs() {
       // No more messages; ensure correct number of SMS messages were found
       if (foundSmsList.length == smsList.length) {
         log("SMS getMessages returned " + foundSmsList.length +
             " messages as expected.");
         verifyFoundMsgs(foundSmsList);
       } else {
         log("SMS getMessages returned " + foundSmsList.length +
             " messages, but expected " + smsList.length + ".");
-        ok(false, "Incorrect number of messages returned by sms.getMessages");
+        ok(false, "Incorrect number of messages returned by manager.getMessages");
         deleteAllMsgs(cleanUp);
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function verifyFoundMsgs(foundSmsList) {
   // Verify the SMS messages returned by getMessages are the correct ones
   for (var x = 0; x < foundSmsList.length; x++) {
     is(foundSmsList[x].id, smsList[x].id, "id");
     is(foundSmsList[x].sender, smsList[x].sender, "number");
   }
   deleteAllMsgs(cleanUp);
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_filter_read.js
+++ b/dom/mobilemessage/tests/marionette/test_filter_read.js
@@ -1,32 +1,33 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.addPermission("sms", true, document);
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let numberMsgs = 10;
 let smsList = new Array();
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   // Ensure test is starting clean with no existing sms messages
   deleteAllMsgs(simulateIncomingSms);
 }
 
 function deleteAllMsgs(nextFunction) {
   let msgList = new Array();
   let filter = new MozSmsFilter;
 
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     // Check if message was found
     if (cursor.result) {
       msgList.push(cursor.result.id);
       // Now get next message in the list
@@ -41,51 +42,51 @@ function deleteAllMsgs(nextFunction) {
         nextFunction();
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function deleteMsgs(msgList, nextFunction) {
   let smsId = msgList.shift();
 
   log("Deleting SMS (id: " + smsId + ").");
-  let request = sms.delete(smsId);
+  let request = manager.delete(smsId);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       // Message deleted, continue until none are left
       if (msgList.length) {
         deleteMsgs(msgList, nextFunction);
       } else {
         log("Finished deleting SMS messages.");
         nextFunction();
       }
     } else {
       log("SMS delete failed.");
-      ok(false,"sms.delete request returned false");
+      ok(false,"manager.delete request returned false");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function simulateIncomingSms() {
   let text = "Incoming SMS number " + (smsList.length + 1);
   let remoteNumber = "5552229797";
@@ -97,17 +98,17 @@ function simulateIncomingSms() {
   rcvdEmulatorCallback = false;
   runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
     is(result[0], "OK", "emulator callback");
     rcvdEmulatorCallback = true;
   });
 }
 
 // Callback for incoming sms
-sms.onreceived = function onreceived(event) {
+manager.onreceived = function onreceived(event) {
   log("Received 'onreceived' sms event.");
   let incomingSms = event.message;
   log("Received SMS (id: " + incomingSms.id + ").");
 
   // Add newly received message to array of received msgs
   smsList.push(incomingSms);
 
   // Wait for emulator to catch up before continuing
@@ -125,55 +126,55 @@ function nextRep() {
     smsList.shift();
     markMsgRead(smsList.slice(0));
   }
 }
 
 function markMsgRead(smsMsgs) {  
   nextSms = smsMsgs.shift();
   log("Marking SMS (id: " + nextSms.id + ") as read.");
-  let request = sms.markMessageRead(nextSms.id, true);
+  let request = manager.markMessageRead(nextSms.id, true);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       // Message marked as read, continue until none are left
       if (smsMsgs.length) {
         markMsgRead(smsMsgs);
       } else {
         // Done, now test the filter
         getMsgs();
       }
     } else {
       log("SMS markMessageRead failed.");
-      ok(false,"sms.markMessageRead request returned false");
+      ok(false,"manager.markMessageRead request returned false");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.markMessageRead request returned unexpected error: "
+    ok(false, "manager.markMessageRead request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function getMsgs() {
   var filter = new MozSmsFilter();
   let foundSmsList = new Array();
 
   // Set filter for read messages
   filter.read = true;
 
   log("Getting the read SMS messages.");
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     log("Received 'onsuccess' event.");
 
     if (cursor.result) {
       // Another message found
@@ -186,40 +187,40 @@ function getMsgs() {
       // No more messages; ensure correct number found
       if (foundSmsList.length == smsList.length) {
         log("SMS getMessages returned " + foundSmsList.length +
             " messages as expected.");
         verifyFoundMsgs(foundSmsList);
       } else {
         log("SMS getMessages returned " + foundSmsList.length +
             " messages, but expected " + smsList.length + ".");
-        ok(false, "Incorrect number of messages returned by sms.getMessages");
+        ok(false, "Incorrect number of messages returned by manager.getMessages");
         deleteAllMsgs(cleanUp);
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function verifyFoundMsgs(foundSmsList) {
   for (var x = 0; x < foundSmsList.length; x++) {
     is(foundSmsList[x].id, smsList[x].id, "id");
     is(foundSmsList[x].read, true, "read");
   }
   deleteAllMsgs(cleanUp);
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_filter_received.js
+++ b/dom/mobilemessage/tests/marionette/test_filter_received.js
@@ -1,32 +1,33 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.addPermission("sms", true, document);
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let numberMsgs = 10;
 let smsList = new Array();
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   // Ensure test is starting clean with no existing sms messages
   deleteAllMsgs(simulateIncomingSms);
 }
 
 function deleteAllMsgs(nextFunction) {
   let msgList = new Array();
   let filter = new MozSmsFilter;
 
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     // Check if message was found
     if (cursor.result) {
       msgList.push(cursor.result.id);
       // Now get next message in the list
@@ -41,51 +42,51 @@ function deleteAllMsgs(nextFunction) {
         nextFunction();
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function deleteMsgs(msgList, nextFunction) {
   let smsId = msgList.shift();
 
   log("Deleting SMS (id: " + smsId + ").");
-  let request = sms.delete(smsId);
+  let request = manager.delete(smsId);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       // Message deleted, continue until none are left
       if (msgList.length) {
         deleteMsgs(msgList, nextFunction);
       } else {
         log("Finished deleting SMS messages.");
         nextFunction();
       }
     } else {
       log("SMS delete failed.");
-      ok(false,"sms.delete request returned false");
+      ok(false,"manager.delete request returned false");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function simulateIncomingSms() {
   let text = "Incoming SMS number " + (smsList.length + 1);
   let remoteNumber = "5552229797";
@@ -97,17 +98,17 @@ function simulateIncomingSms() {
   rcvdEmulatorCallback = false;
   runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
     is(result[0], "OK", "emulator callback");
     rcvdEmulatorCallback = true;
   });
 }
 
 // Callback for incoming sms
-sms.onreceived = function onreceived(event) {
+manager.onreceived = function onreceived(event) {
   log("Received 'onreceived' sms event.");
   let incomingSms = event.message;
   log("Received SMS (id: " + incomingSms.id + ").");
 
   smsList.push(incomingSms);
 
   // Wait for emulator to catch up before continuing
   waitFor(nextRep,function() {
@@ -127,65 +128,65 @@ function nextRep() {
 function sendSms() {  
   let gotSmsSent = false;
   let gotRequestSuccess = false;
   let remoteNumber = "5557779999";
   let text = "Outgoing SMS brought to you by Firefox OS!";
 
   log("Sending an SMS.");
 
-  sms.onsent = function(event) {
-    log("Received 'onsent' smsmanager event.");
+  manager.onsent = function(event) {
+    log("Received 'onsent' event.");
     gotSmsSent = true;
     let sentSms = event.message;
     log("Sent SMS (id: " + sentSms.id + ").");
     is(sentSms.delivery, "sent", "delivery");
     if (gotSmsSent && gotRequestSuccess) {
       // Test the filter
       getMsgs();
     }
   };
 
-  let request = sms.send(remoteNumber, text);
+  let request = manager.send(remoteNumber, text);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if(event.target.result) {
       gotRequestSuccess = true;
       if (gotSmsSent && gotRequestSuccess) {
         // Test the filter
         getMsgs(); 
       }
     } else {
-      log("smsrequest returned false for sms.send");
+      log("smsrequest returned false for manager.send");
       ok(false,"SMS send failed");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.send request returned unexpected error: "
+    ok(false, "manager.send request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function getMsgs() {
   var filter = new MozSmsFilter();
   let foundSmsList = new Array();
 
   // Set filter for received messages
   filter.delivery = "received";
 
   log("Getting the received SMS messages.");
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     log("Received 'onsuccess' event.");
 
     if (cursor.result) {
       // Another message found
@@ -198,40 +199,40 @@ function getMsgs() {
       // No more messages; ensure correct number found
       if (foundSmsList.length == smsList.length) {
         log("SMS getMessages returned " + foundSmsList.length +
             " messages as expected.");
         verifyFoundMsgs(foundSmsList);
       } else {
         log("SMS getMessages returned " + foundSmsList.length +
             " messages, but expected " + smsList.length + ".");
-        ok(false, "Incorrect number of messages returned by sms.getMessages");
+        ok(false, "Incorrect number of messages returned by manager.getMessages");
         deleteAllMsgs(cleanUp);
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function verifyFoundMsgs(foundSmsList) {
   for (var x = 0; x < foundSmsList.length; x++) {
     is(foundSmsList[x].id, smsList[x].id, "id");
     is(foundSmsList[x].delivery, "received", "delivery");
   }
   deleteAllMsgs(cleanUp);
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_filter_sent.js
+++ b/dom/mobilemessage/tests/marionette/test_filter_sent.js
@@ -1,32 +1,33 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.addPermission("sms", true, document);
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let numberMsgs = 10;
 let smsList = new Array();
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   // Ensure test is starting clean with no existing sms messages
   deleteAllMsgs(sendSms);
 }
 
 function deleteAllMsgs(nextFunction) {
   let msgList = new Array();
   let filter = new MozSmsFilter;
 
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     // Check if message was found
     if (cursor.result) {
       msgList.push(cursor.result.id);
       // Now get next message in the list
@@ -41,99 +42,99 @@ function deleteAllMsgs(nextFunction) {
         nextFunction();
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function deleteMsgs(msgList, nextFunction) {
   let smsId = msgList.shift();
 
   log("Deleting SMS (id: " + smsId + ").");
-  let request = sms.delete(smsId);
+  let request = manager.delete(smsId);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       // Message deleted, continue until none are left
       if (msgList.length) {
         deleteMsgs(msgList, nextFunction);
       } else {
         log("Finished deleting SMS messages.");
         nextFunction();
       }
     } else {
       log("SMS delete failed.");
-      ok(false,"sms.delete request returned false");
+      ok(false,"manager.delete request returned false");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function sendSms() {  
   let gotSmsSent = false;
   let gotRequestSuccess = false;
   let remoteNumber = "5557779999";
   let text = "Outgoing SMS brought to you by Firefox OS!";
 
   log("Sending SMS " + (smsList.length + 1) + " of "
       + (numberMsgs - 1) + ".");
 
-  sms.onsent = function(event) {
-    log("Received 'onsent' smsmanager event.");
+  manager.onsent = function(event) {
+    log("Received 'onsent' event.");
     gotSmsSent = true;
     let sentSms = event.message;
     log("Sent SMS (id: " + sentSms.id + ").");
     is(sentSms.delivery, "sent", "delivery");
     smsList.push(sentSms);
     if (gotSmsSent && gotRequestSuccess) {
       nextRep();
     }
   };
 
-  let request = sms.send(remoteNumber, text);
+  let request = manager.send(remoteNumber, text);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if(event.target.result) {
       gotRequestSuccess = true;
       if (gotSmsSent && gotRequestSuccess) {
         nextRep(); 
       }
     } else {
-      log("smsrequest returned false for sms.send");
+      log("smsrequest returned false for manager.send");
       ok(false,"SMS send failed");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.send request returned unexpected error: "
+    ok(false, "manager.send request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function nextRep() {
   if (smsList.length < (numberMsgs - 1)) {
     sendSms();
@@ -153,17 +154,17 @@ function simulateIncomingSms() {
   rcvdEmulatorCallback = false;
   runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
     is(result[0], "OK", "emulator callback");
     rcvdEmulatorCallback = true;
   });
 }
 
 // Callback for incoming sms
-sms.onreceived = function onreceived(event) {
+manager.onreceived = function onreceived(event) {
   log("Received 'onreceived' sms event.");
   let incomingSms = event.message;
   log("Received SMS (id: " + incomingSms.id + ").");
 
   // Wait for emulator to catch up before continuing
   waitFor(getMsgs,function() {
     return(rcvdEmulatorCallback);
   });
@@ -172,17 +173,17 @@ sms.onreceived = function onreceived(eve
 function getMsgs() {
   var filter = new MozSmsFilter();
   let foundSmsList = new Array();
 
   // Set filter for sent messages
   filter.delivery = "sent";
 
   log("Getting the sent SMS messages.");
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     log("Received 'onsuccess' event.");
 
     if (cursor.result) {
       // Another message found
@@ -195,40 +196,40 @@ function getMsgs() {
       // No more messages; ensure correct number found
       if (foundSmsList.length == smsList.length) {
         log("SMS getMessages returned " + foundSmsList.length +
             " messages as expected.");
         verifyFoundMsgs(foundSmsList);
       } else {
         log("SMS getMessages returned " + foundSmsList.length +
             " messages, but expected " + smsList.length + ".");
-        ok(false, "Incorrect number of messages returned by sms.getMessages");
+        ok(false, "Incorrect number of messages returned by manager.getMessages");
         deleteAllMsgs(cleanUp);
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function verifyFoundMsgs(foundSmsList) {
   for (var x = 0; x < foundSmsList.length; x++) {
     is(foundSmsList[x].id, smsList[x].id, "id");
     is(foundSmsList[x].delivery, "sent", "delivery");
   }
   deleteAllMsgs(cleanUp);
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_filter_unread.js
+++ b/dom/mobilemessage/tests/marionette/test_filter_unread.js
@@ -1,32 +1,33 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.addPermission("sms", true, document);
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let numberMsgs = 10;
 let smsList = new Array();
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   // Ensure test is starting clean with no existing sms messages
   deleteAllMsgs(simulateIncomingSms);
 }
 
 function deleteAllMsgs(nextFunction) {
   let msgList = new Array();
   let filter = new MozSmsFilter;
 
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     // Check if message was found
     if (cursor.result) {
       msgList.push(cursor.result.id);
       // Now get next message in the list
@@ -41,51 +42,51 @@ function deleteAllMsgs(nextFunction) {
         nextFunction();
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function deleteMsgs(msgList, nextFunction) {
   let smsId = msgList.shift();
 
   log("Deleting SMS (id: " + smsId + ").");
-  let request = sms.delete(smsId);
+  let request = manager.delete(smsId);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       // Message deleted, continue until none are left
       if (msgList.length) {
         deleteMsgs(msgList, nextFunction);
       } else {
         log("Finished deleting SMS messages.");
         nextFunction();
       }
     } else {
       log("SMS delete failed.");
-      ok(false,"sms.delete request returned false");
+      ok(false,"manager.delete request returned false");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function simulateIncomingSms() {
   let text = "Incoming SMS number " + (smsList.length + 1);
   let remoteNumber = "5552229797";
@@ -97,17 +98,17 @@ function simulateIncomingSms() {
   rcvdEmulatorCallback = false;
   runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
     is(result[0], "OK", "emulator callback");
     rcvdEmulatorCallback = true;
   });
 }
 
 // Callback for incoming sms
-sms.onreceived = function onreceived(event) {
+manager.onreceived = function onreceived(event) {
   log("Received 'onreceived' sms event.");
   let incomingSms = event.message;
   log("Received SMS (id: " + incomingSms.id + ").");
 
   // Add newly received message to array of received msgs
   smsList.push(incomingSms);
 
   // Wait for emulator to catch up before continuing
@@ -122,52 +123,52 @@ function nextRep() {
   } else {
     markMsgRead();
   }
 }
 
 function markMsgRead() {
   // Mark first message read so not all will be found by filter
   log("Marking SMS (id: " + smsList[0].id + ") as read.");
-  let request = sms.markMessageRead(smsList[0].id, true);
+  let request = manager.markMessageRead(smsList[0].id, true);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       // First message was marked read, so remove from expected smsList
       smsList.shift();
       // Now test the filter
       getMsgs();
     } else {
       log("SMS markMessageRead failed.");
-      ok(false,"sms.markMessageRead request returned false");
+      ok(false,"manager.markMessageRead request returned false");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.markMessageRead request returned unexpected error: "
+    ok(false, "manager.markMessageRead request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function getMsgs() {
   var filter = new MozSmsFilter();
   let foundSmsList = new Array();
 
   // Set filter for read messages
   filter.read = false;
 
   log("Getting the unread SMS messages.");
-  let cursor = sms.getMessages(filter, false);
+  let cursor = manager.getMessages(filter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     log("Received 'onsuccess' event.");
 
     if (cursor.result) {
       // Another message found
@@ -180,40 +181,40 @@ function getMsgs() {
       // No more messages; ensure correct number found
       if (foundSmsList.length == smsList.length) {
         log("SMS getMessages returned " + foundSmsList.length +
             " messages as expected.");
         verifyFoundMsgs(foundSmsList);
       } else {
         log("SMS getMessages returned " + foundSmsList.length +
             " messages, but expected " + smsList.length + ".");
-        ok(false, "Incorrect number of messages returned by sms.getMessages");
+        ok(false, "Incorrect number of messages returned by manager.getMessages");
         deleteAllMsgs(cleanUp);
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function verifyFoundMsgs(foundSmsList) {
   for (var x = 0; x < foundSmsList.length; x++) {
     is(foundSmsList[x].id, smsList[x].id, "id");
     is(foundSmsList[x].read, false, "read");
   }
   deleteAllMsgs(cleanUp);
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_getmessage.js
+++ b/dom/mobilemessage/tests/marionette/test_getmessage.js
@@ -5,39 +5,40 @@ MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.setBoolPref("dom.sms.requestStatusReport", true);
 SpecialPowers.addPermission("sms", true, document);
 
 const REMOTE = "5559997777"; // the remote number
 const EMULATOR = "15555215554"; // the emulator's number
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let inText = "Incoming SMS message. Mozilla Firefox OS!";
 let outText = "Outgoing SMS message. Mozilla Firefox OS!";
 let gotSmsOnsent = false;
 let gotReqOnsuccess = false;
 let inSmsId = 0;
 let outSmsId = 0;
 let inThreadId = 0;
 let outThreadId = 0;
 let inSmsTimeStamp;
 let outSmsTimeStamp;
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   simulateIncomingSms();  
 }
 
 function simulateIncomingSms() {
   log("Simulating incoming SMS.");
 
-  sms.onreceived = function onreceived(event) {
-    log("Received 'onreceived' smsmanager event.");
+  manager.onreceived = function onreceived(event) {
+    log("Received 'onreceived' event.");
     let incomingSms = event.message;
     ok(incomingSms, "incoming sms");
     ok(incomingSms.id, "sms id");
     inSmsId = incomingSms.id;
     log("Received SMS (id: " + inSmsId + ").");
     ok(incomingSms.threadId, "thread id");
     inThreadId = incomingSms.threadId;
     is(incomingSms.body, inText, "msg body");
@@ -54,18 +55,18 @@ function simulateIncomingSms() {
   // Simulate incoming sms sent from remoteNumber to our emulator
   runEmulatorCmd("sms send " + REMOTE + " " + inText, function(result) {
     is(result[0], "OK", "emulator output");
   });
 }
 
 function sendSms() {
   log("Sending an SMS.");
-  sms.onsent = function(event) {
-    log("Received 'onsent' smsmanager event.");
+  manager.onsent = function(event) {
+    log("Received 'onsent' event.");
     gotSmsOnsent = true;
     let sentSms = event.message;
     ok(sentSms, "outgoing sms");
     ok(sentSms.id, "sms id");
     outSmsId = sentSms.id;
     log("Sent SMS (id: " + outSmsId + ").");
     ok(sentSms.threadId, "thread id");
     outThreadId = sentSms.threadId;
@@ -77,44 +78,44 @@ function sendSms() {
     is(sentSms.sender, EMULATOR, "sender");
     is(sentSms.messageClass, "normal", "messageClass");
     ok(sentSms.timestamp instanceof Date, "timestamp is instanceof date");  
     outSmsTimeStamp = sentSms.timestamp;
 
     if (gotSmsOnsent && gotReqOnsuccess) { getReceivedSms(); }
   };
 
-  let requestRet = sms.send(REMOTE, outText);
+  let requestRet = manager.send(REMOTE, outText);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     gotReqOnsuccess = true;
     if(event.target.result){
       if (gotSmsOnsent && gotReqOnsuccess) { getReceivedSms(); }
     } else {
-      log("smsrequest returned false for sms.send");
+      log("smsrequest returned false for manager.send");
       ok(false,"SMS send failed");
       cleanUp();
     }
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.send request returned unexpected error: "
+    ok(false, "manager.send request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function getReceivedSms() {
   log("Getting the received SMS message (id: " + inSmsId + ").");
 
-  let requestRet = sms.getMessage(inSmsId);
+  let requestRet = manager.getMessage(inSmsId);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, inSmsId, "SMS id matches");
     log("Got SMS (id: " + foundSms.id + ").");
@@ -138,17 +139,17 @@ function getReceivedSms() {
     log("Could not get SMS (id: " + inSmsId + ") but should have.");
     ok(false,"Could not get received SMS");
     cleanUp();
   };
 }
 
 function getSentSms() {
   log("Getting the sent SMS message (id: " + outSmsId + ").");
-  let requestRet = sms.getMessage(outSmsId);
+  let requestRet = manager.getMessage(outSmsId);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, outSmsId, "SMS id matches");
     log("Got SMS (id: " + foundSms.id + ").");
@@ -172,52 +173,52 @@ function getSentSms() {
     log("Could not get SMS (id: " + outSmsId + ") but should have.");
     ok(false,"Could not get sent SMS");
     cleanUp();
   };
 }
 
 function deleteMsgs() {
   log("Deleting SMS (id: " + inSmsId + ").");
-  let requestRet = sms.delete(inSmsId);
+  let requestRet = manager.delete(inSmsId);
   ok(requestRet,"smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if(event.target.result){
       log("Deleting SMS (id: " + outSmsId + ").");
-      let nextReqRet = sms.delete(outSmsId);
+      let nextReqRet = manager.delete(outSmsId);
       ok(nextReqRet,"smsrequest obj returned");
 
       nextReqRet.onsuccess = function(event) {
         log("Received 'onsuccess' smsrequest event.");
         if(event.target.result) {
           cleanUp();
         } else {
-          log("smsrequest returned false for sms.delete");
+          log("smsrequest returned false for manager.delete");
           ok(false,"SMS delete failed");
         }
       };
     } else {
-      log("smsrequest returned false for sms.delete");
+      log("smsrequest returned false for manager.delete");
       ok(false,"SMS delete failed");
     }
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   SpecialPowers.clearUserPref("dom.sms.requestStatusReport");
 
   finish();
 }
 
 // Start the test
--- a/dom/mobilemessage/tests/marionette/test_getmessage_notfound.js
+++ b/dom/mobilemessage/tests/marionette/test_getmessage_notfound.js
@@ -1,33 +1,34 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let myNumber = "15555215554";
 let inText = "Incoming SMS message. Mozilla Firefox OS!";
 let remoteNumber = "5559997777";
 let inSmsId = 0;
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   simulateIncomingSms();  
 }
 
 function simulateIncomingSms() {
   log("Simulating incoming SMS.");
 
-  sms.onreceived = function onreceived(event) {
-    log("Received 'onreceived' smsmanager event.");
+  manager.onreceived = function onreceived(event) {
+    log("Received 'onreceived' event.");
     let incomingSms = event.message;
     ok(incomingSms, "incoming sms");
     ok(incomingSms.id, "sms id");
     inSmsId = incomingSms.id;
     log("Received SMS (id: " + inSmsId + ").");
     is(incomingSms.body, inText, "msg body");
     is(incomingSms.delivery, "received", "delivery");
     getNonExistentMsg();
@@ -36,17 +37,17 @@ function simulateIncomingSms() {
   runEmulatorCmd("sms send " + remoteNumber + " " + inText, function(result) {
     is(result[0], "OK", "emulator output");
   });
 }
 
 function getNonExistentMsg() {
   let msgIdNoExist = inSmsId + 1;
   log("Attempting to get non-existent message (id: " + msgIdNoExist + ").");
-  let requestRet = sms.getMessage(msgIdNoExist);
+  let requestRet = manager.getMessage(msgIdNoExist);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     log("Got SMS (id: " + foundSms.id + ") but should not have.");
     ok(false, "Smsrequest successful when tried to get non-existent sms");
@@ -60,17 +61,17 @@ function getNonExistentMsg() {
     log("Could not get SMS (id: " + msgIdNoExist + ") as expected.");
     getMsgInvalidId();
   };
 }  
 
 function getMsgInvalidId() {
   invalidId = -1;
   log("Attempting to get sms with invalid id (id: " + invalidId + ").");
-  let requestRet = sms.getMessage(invalidId);
+  let requestRet = manager.getMessage(invalidId);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     log("Got SMS (id: " + foundSms.id + ") but should not have.");
     ok(false, "Smsrequest successful when tried to get message with " +
@@ -84,36 +85,36 @@ function getMsgInvalidId() {
     is(event.target.error.name, "NotFoundError", "error returned");
     log("Could not get SMS (id: -1) as expected.");
     deleteMsg();
   };
 }
 
 function deleteMsg() {
   log("Deleting SMS (id: " + inSmsId + ").");
-  let requestRet = sms.delete(inSmsId);
+  let requestRet = manager.delete(inSmsId);
   ok(requestRet,"smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if(event.target.result){
       cleanUp();
     }
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.setBoolPref("dom.sms.enabled", false);
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_getmessages.js
+++ b/dom/mobilemessage/tests/marionette/test_getmessages.js
@@ -1,36 +1,37 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.addPermission("sms", true, document);
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let numberMsgs = 10;
 let smsList = new Array();
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   // Ensure test is starting clean with no existing sms messages
   deleteAllMsgs(simulateIncomingSms);
 }
 
 function isIn(aVal, aArray, aMsg) {
   ok(aArray.indexOf(aVal) >= 0, aMsg);
 }
 
 function deleteAllMsgs(nextFunction) {
   let msgList = new Array();
   let smsFilter = new MozSmsFilter;
 
-  let cursor = sms.getMessages(smsFilter, false);
+  let cursor = manager.getMessages(smsFilter, false);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     // Check if message was found
     if (cursor.result) {
       msgList.push(cursor.result.id);
       // Now get next message in the list
@@ -45,51 +46,51 @@ function deleteAllMsgs(nextFunction) {
         nextFunction();
       }
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function deleteMsgs(msgList, nextFunction) {
   let smsId = msgList.shift();
 
   log("Deleting SMS (id: " + smsId + ").");
-  let request = sms.delete(smsId);
+  let request = manager.delete(smsId);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       // Message deleted, continue until none are left
       if (msgList.length) {
         deleteMsgs(msgList, nextFunction);
       } else {
         log("Finished deleting SMS messages.");
         nextFunction();
       }
     } else {
       log("SMS delete failed.");
-      ok(false,"sms.delete request returned false");
+      ok(false,"manager.delete request returned false");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function simulateIncomingSms() {
   let text = "Incoming SMS number " + (smsList.length + 1);
   let remoteNumber = "5552229797";
@@ -101,17 +102,17 @@ function simulateIncomingSms() {
   rcvdEmulatorCallback = false;
   runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
     is(result[0], "OK", "emulator callback");
     rcvdEmulatorCallback = true;
   });
 }
 
 // Callback for incoming sms
-sms.onreceived = function onreceived(event) {
+manager.onreceived = function onreceived(event) {
   log("Received 'onreceived' sms event.");
   let incomingSms = event.message;
   log("Received SMS (id: " + incomingSms.id + ").");
 
   // Add newly received message to array of received msgs
   smsList.push(incomingSms);
 
   // Wait for emulator to catch up before continuing
@@ -137,17 +138,17 @@ function getMsgs(reverse) {
   if (!reverse) {
     log("Getting the sms messages.");
   } else {
     log("Getting the sms messages in reverse order.");
   }
 
   // Note: This test is intended for getMessages, so just a basic test with
   // no filter (default); separate tests will be written for sms filtering
-  let cursor = sms.getMessages(smsFilter, reverse);
+  let cursor = manager.getMessages(smsFilter, reverse);
   ok(cursor instanceof DOMCursor,
       "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function(event) {
     log("Received 'onsuccess' event.");
 
     if (cursor.result) {
       // Another message found
@@ -160,26 +161,26 @@ function getMsgs(reverse) {
     } else {
       // No more messages; ensure correct number found
       if (foundSmsCount == numberMsgs) {
         log("SMS getMessages returned " + foundSmsCount +
             " messages as expected.");  
       } else {
         log("SMS getMessages returned " + foundSmsCount +
             " messages, but expected " + numberMsgs + ".");
-        ok(false, "Incorrect number of messages returned by sms.getMessages");
+        ok(false, "Incorrect number of messages returned by manager.getMessages");
       }
       verifyFoundMsgs(foundSmsList, reverse);
     }
   };
 
   cursor.onerror = function(event) {
     log("Received 'onerror' event.");
     ok(event.target.error, "domerror obj");
-    log("sms.getMessages error: " + event.target.error.name);
+    log("manager.getMessages error: " + event.target.error.name);
     ok(false,"Could not get SMS messages");
     cleanUp();
   };
 }
 
 function verifyFoundMsgs(foundSmsList, reverse) {
   if (reverse) {
     smsList.reverse();
@@ -211,16 +212,16 @@ function verifyFoundMsgs(foundSmsList, r
     getMsgs(true);
   } else {
     // Finished, delete all messages
     deleteAllMsgs(cleanUp);
   };
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_getsegmentinfofortext.js
+++ b/dom/mobilemessage/tests/marionette/test_getsegmentinfofortext.js
@@ -4,18 +4,19 @@
 MARIONETTE_TIMEOUT = 60000;
 
 // Copied from dom/system/gonk/ril_consts.js.
 const PDU_MAX_USER_DATA_7BIT = 160;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
-let sms = window.navigator.mozSms;
-ok(sms instanceof MozSmsManager, "mozSmsManager");
+let manager = window.navigator.mozMobileMessage;
+ok(manager instanceof MozMobileMessageManager,
+   "manager is instance of " + manager.constructor);
 
 let tasks = {
   // List of test fuctions. Each of them should call |tasks.next()| when
   // completed or |tasks.finish()| to jump to the last one.
   _tasks: [],
   _nextTaskIndex: 0,
 
   push: function push(func) {
@@ -43,31 +44,31 @@ let tasks = {
   run: function run() {
     this.next();
   }
 };
 
 function addTest(text, segments, charsPerSegment, charsAvailableInLastSegment) {
   tasks.push(function () {
     log("Testing '" + text + "' ...");
-    let info = sms.getSegmentInfoForText(text);
+    let info = manager.getSegmentInfoForText(text);
     is(info.segments, segments, "info.segments");
     is(info.charsPerSegment, charsPerSegment, "info.charsPerSegment");
     is(info.charsAvailableInLastSegment, charsAvailableInLastSegment,
        "info.charsAvailableInLastSegment");
 
     tasks.next();
   });
 }
 
 function addTestThrows(text) {
   tasks.push(function () {
     log("Testing '" + text + "' ...");
     try {
-      let info = sms.getSegmentInfoForText(text);
+      let info = manager.getSegmentInfoForText(text);
 
       ok(false, "Not thrown");
       tasks.finish();
     } catch (e) {
       tasks.next();
     }
   });
 }
--- a/dom/mobilemessage/tests/marionette/test_getthreads.js
+++ b/dom/mobilemessage/tests/marionette/test_getthreads.js
@@ -1,18 +1,19 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 40000;
 
 SpecialPowers.addPermission("sms", true, document);
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 
-let sms = window.navigator.mozSms;
-ok(sms instanceof MozSmsManager);
+let manager = window.navigator.mozMobileMessage;
+ok(manager instanceof MozMobileMessageManager,
+   "manager is instance of " + manager.constructor);
 
 let pendingEmulatorCmdCount = 0;
 function sendSmsToEmulator(from, text, callback) {
   ++pendingEmulatorCmdCount;
 
   let cmd = "sms send " + from + " " + text;
   runEmulatorCmd(cmd, function (result) {
     --pendingEmulatorCmdCount;
@@ -54,17 +55,17 @@ let tasks = {
   }
 };
 
 function getAllMessages(callback, filter, reverse) {
   if (!filter) {
     filter = new MozSmsFilter;
   }
   let messages = [];
-  let request = sms.getMessages(filter, reverse || false);
+  let request = manager.getMessages(filter, reverse || false);
   request.onsuccess = function(event) {
     if (!request.done) {
       messages.push(request.result);
       request.continue();
       return;
     }
 
     window.setTimeout(callback.bind(null, messages), 0);
@@ -75,50 +76,50 @@ function deleteAllMessages() {
   getAllMessages(function deleteAll(messages) {
     let message = messages.shift();
     if (!message) {
       ok(true, "all messages deleted");
       tasks.next();
       return;
     }
 
-    let request = sms.delete(message.id);
+    let request = manager.delete(message.id);
     request.onsuccess = deleteAll.bind(null, messages);
     request.onerror = function (event) {
       ok(false, "failed to delete all messages");
       tasks.finish();
     }
   });
 }
 
 function sendMessage(to, body) {
-  sms.onsent = function () {
-    sms.onsent = null;
+  manager.onsent = function () {
+    manager.onsent = null;
     tasks.next();
   };
-  let request = sms.send(to, body);
+  let request = manager.send(to, body);
   request.onerror = tasks.finish.bind(tasks);
 }
 
 function receiveMessage(from, body) {
-  sms.onreceived = function () {
-    sms.onreceived = null;
+  manager.onreceived = function () {
+    manager.onreceived = null;
     tasks.next();
   };
   sendSmsToEmulator(from, body, function (success) {
     if (!success) {
       tasks.finish();
     }
   });
 }
 
 function getAllThreads(callback) {
   let threads = [];
 
-  let cursor = sms.getThreads();
+  let cursor = manager.getThreads();
   ok(cursor instanceof DOMCursor,
      "cursor is instanceof " + cursor.constructor);
 
   cursor.onsuccess = function (event) {
     if (!cursor.done) {
       threads.push(cursor.result);
       cursor.continue();
       return;
--- a/dom/mobilemessage/tests/marionette/test_incoming.js
+++ b/dom/mobilemessage/tests/marionette/test_incoming.js
@@ -4,27 +4,30 @@
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
 const SENDER = "5555552368"; // the remote number
 const RECEIVER = "15555215554"; // the emulator's number
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
+ok(manager instanceof MozMobileMessageManager,
+   "manager is instance of " + manager.constructor);
+
 let body = "Hello SMS world!";
 
 let completed = false;
 runEmulatorCmd("sms send " + SENDER + " " + body, function(result) {
   log("Sent fake SMS: " + result);
   is(result[0], "OK", "Emulator command result");
   completed = true;
 });
 
-sms.onreceived = function onreceived(event) {
+manager.onreceived = function onreceived(event) {
   log("Received an SMS!");
 
   let message = event.message;
   ok(message instanceof MozSmsMessage, "Message is instanceof MozSmsMessage");
 
   ok(message.threadId, "thread id");
   is(message.delivery, "received", "Message delivery");
   is(message.deliveryStatus, "success", "Delivery status");
--- a/dom/mobilemessage/tests/marionette/test_incoming_delete.js
+++ b/dom/mobilemessage/tests/marionette/test_incoming_delete.js
@@ -4,30 +4,31 @@
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
 const SENDER = "5555552368"; // the remote number
 const RECEIVER = "15555215554"; // the emulator's number
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let msgText = "Mozilla Firefox OS!";
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   simulateIncomingSms();  
 }
 
 function simulateIncomingSms() {
   log("Simulating incoming SMS.");
 
-  sms.onreceived = function onreceived(event) {
-    log("Received 'onreceived' smsmanager event.");
+  manager.onreceived = function onreceived(event) {
+    log("Received 'onreceived' event.");
     let incomingSms = event.message;
     ok(incomingSms, "incoming sms");
     ok(incomingSms.id, "sms id");
     log("Received SMS (id: " + incomingSms.id + ").");
     ok(incomingSms.threadId, "thread id");
     is(incomingSms.body, msgText, "msg body");
     is(incomingSms.delivery, "received", "delivery");
     is(incomingSms.deliveryStatus, "success", "deliveryStatus");
@@ -41,17 +42,17 @@ function simulateIncomingSms() {
   };
   runEmulatorCmd("sms send " + SENDER + " " + msgText, function(result) {
     is(result[0], "OK", "emulator output");
   });
 }
 
 function verifySmsExists(incomingSms) {
   log("Getting SMS (id: " + incomingSms.id + ").");
-  let requestRet = sms.getMessage(incomingSms.id);
+  let requestRet = manager.getMessage(incomingSms.id);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, incomingSms.id, "found SMS id matches");
     is(foundSms.threadId, incomingSms.threadId, "found SMS thread id matches");
@@ -73,42 +74,42 @@ function verifySmsExists(incomingSms) {
     log("Could not get SMS (id: " + incomingSms.id + ") but should have.");
     ok(false,"SMS was not found");
     cleanUp();
   };
 }
 
 function deleteSms(smsMsgObj){
   log("Deleting SMS (id: " + smsMsgObj.id + ") using smsmsg obj parameter.");
-  let requestRet = sms.delete(smsMsgObj);
+  let requestRet = manager.delete(smsMsgObj);
   ok(requestRet,"smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if(event.target.result){
       verifySmsDeleted(smsMsgObj.id);
     } else {
-      log("smsrequest returned false for sms.delete");
+      log("smsrequest returned false for manager.delete");
       ok(false,"SMS delete failed");
       cleanUp();
     }
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function verifySmsDeleted(smsId) {
   log("Getting SMS (id: " + smsId + ").");
-  let requestRet = sms.getMessage(smsId);
+  let requestRet = manager.getMessage(smsId);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, smsId, "found SMS id matches");
     is(foundSms.body, msgText, "found SMS msg text matches");
@@ -122,16 +123,16 @@ function verifySmsDeleted(smsId) {
     ok(event.target.error, "domerror obj");
     is(event.target.error.name, "NotFoundError", "error returned");
     log("Could not get SMS (id: " + smsId + ") as expected.");
     cleanUp();
   };
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.setBoolPref("dom.sms.enabled", false);
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_incoming_max_segments.js
+++ b/dom/mobilemessage/tests/marionette/test_incoming_max_segments.js
@@ -1,41 +1,42 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 // https://developer.mozilla.org/en-US/docs/DOM/SmsManager
 let maxCharsPerSms = 160;
 let maxSegments = 10; // 10 message segments concatenated into 1 multipart SMS
 
 const REMOTE = "5551234567"; // the remote number
 const EMULATOR = "15555215554"; // the emulator's number
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   simulateIncomingSms();
 }
 
 function simulateIncomingSms() {
   let msgText = "";
 
   // Build the message text
   msgText = new Array((maxCharsPerSms * maxSegments) + 1).join('a');
   log("Simulating incoming multipart SMS (" + msgText.length +
       " chars total).");
 
-  sms.onreceived = function onreceived(event) {
-    sms.onreceived = null;
-    log("Received 'onreceived' smsmanager event.");
+  manager.onreceived = function onreceived(event) {
+    manager.onreceived = null;
+    log("Received 'onreceived' event.");
 
     let incomingSms = event.message;
     ok(incomingSms, "incoming sms");
     ok(incomingSms.id, "sms id");
     log("Received SMS (id: " + incomingSms.id + ").");
     ok(incomingSms.threadId, "thread id");
     is(incomingSms.body.length, msgText.length, "msg body length");
     is(incomingSms.body, msgText, "msg body");
@@ -49,17 +50,17 @@ function simulateIncomingSms() {
   };
   runEmulatorCmd("sms send " + REMOTE + " " + msgText, function(result) {
     is(result[0], "OK", "emulator output");
   });
 }
 
 function verifySmsExists(incomingSms) {
   log("Getting SMS (id: " + incomingSms.id + ").");
-  let requestRet = sms.getMessage(incomingSms.id);
+  let requestRet = manager.getMessage(incomingSms.id);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, incomingSms.id, "found SMS id matches");
     is(foundSms.body.length, incomingSms.body.length, "SMS text length");
@@ -75,34 +76,34 @@ function verifySmsExists(incomingSms) {
     log("Could not get SMS (id: " + incomingSms.id + ") but should have.");
     ok(false, "SMS was not found");
     cleanUp();
   };
 }
 
 function deleteSms(smsMsgObj){
   log("Deleting SMS (id: " + smsMsgObj.id + ") using smsmsg obj parameter.");
-  let requestRet = sms.delete(smsMsgObj);
+  let requestRet = manager.delete(smsMsgObj);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       cleanUp();
     } else {
-      log("smsrequest returned false for sms.delete");
+      log("smsrequest returned false for manager.delete");
       ok(false, "SMS delete failed");
       cleanUp();
     }
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: " +
+    ok(false, "manager.delete request returned unexpected error: " +
               event.target.error.name);
     cleanUp();
   };
 }
 
 function cleanUp() {
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
--- a/dom/mobilemessage/tests/marionette/test_incoming_multipart.js
+++ b/dom/mobilemessage/tests/marionette/test_incoming_multipart.js
@@ -4,36 +4,37 @@
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
 const SENDER = "5555552368"; // the remote number
 const RECEIVER = "15555215554"; // the emulator's number
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   simulateIncomingSms();  
 }
 
 function simulateIncomingSms() {
   let msgText = "";
 
   log("Simulating incoming SMS.");
 
   // Have message text > max SMS size (160 char) so will be a multi-part SMS
   for (var x = 1; x <= 24; x++) {
     msgText += 'FirefoxOS ';
   }
 
-  sms.onreceived = function onreceived(event) {
-    log("Received 'onreceived' smsmanager event.");
+  manager.onreceived = function onreceived(event) {
+    log("Received 'onreceived' event.");
     let incomingSms = event.message;
     ok(incomingSms, "incoming sms");
     ok(incomingSms.id, "sms id");
     log("Received SMS (id: " + incomingSms.id + ").");
     ok(incomingSms.threadId, "thread id");
     is(incomingSms.body, msgText, "msg body");
     is(incomingSms.delivery, "received", "delivery");
     is(incomingSms.read, false, "read");
@@ -45,17 +46,17 @@ function simulateIncomingSms() {
   };
   runEmulatorCmd("sms send " + SENDER + " " + msgText, function(result) {
     is(result[0], "OK", "emulator output");
   });
 }
 
 function verifySmsExists(incomingSms) {
   log("Getting SMS (id: " + incomingSms.id + ").");
-  let requestRet = sms.getMessage(incomingSms.id);
+  let requestRet = manager.getMessage(incomingSms.id);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, incomingSms.id, "found SMS id matches");
     is(foundSms.threadId, incomingSms.threadId, "found SMS thread id matches");
@@ -75,40 +76,40 @@ function verifySmsExists(incomingSms) {
     log("Could not get SMS (id: " + incomingSms.id + ") but should have.");
     ok(false,"SMS was not found");
     cleanUp();
   };
 }
 
 function deleteSms(smsMsgObj){
   log("Deleting SMS (id: " + smsMsgObj.id + ") using smsmsg obj parameter.");
-  let requestRet = sms.delete(smsMsgObj);
+  let requestRet = manager.delete(smsMsgObj);
   ok(requestRet,"smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if(event.target.result){
       cleanUp();
     } else {
-      log("smsrequest returned false for sms.delete");
+      log("smsrequest returned false for manager.delete");
       ok(false,"SMS delete failed");
       cleanUp();
     }
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_invalid_address.js
+++ b/dom/mobilemessage/tests/marionette/test_invalid_address.js
@@ -36,24 +36,24 @@ let tasks = {
     this._tasks[this._tasks.length - 1]();
   },
 
   run: function run() {
     this.next();
   }
 };
 
-let mozMobileMessage;
+let manager;
 
 function getAllMessages(callback, filter, reverse) {
   if (!filter) {
     filter = new MozSmsFilter;
   }
   let messages = [];
-  let request = mozMobileMessage.getMessages(filter, reverse || false);
+  let request = manager.getMessages(filter, reverse || false);
   request.onsuccess = function(event) {
     if (request.result) {
       messages.push(request.result);
       request.continue();
       return;
     }
 
     window.setTimeout(callback.bind(null, messages), 0);
@@ -64,45 +64,45 @@ function deleteAllMessages() {
   getAllMessages(function deleteAll(messages) {
     let message = messages.shift();
     if (!message) {
       ok(true, "all messages deleted");
       tasks.next();
       return;
     }
 
-    let request = mozMobileMessage.delete(message.id);
+    let request = manager.delete(message.id);
     request.onsuccess = deleteAll.bind(null, messages);
     request.onerror = function (event) {
       ok(false, "failed to delete all messages");
       tasks.finish();
     }
   });
 }
 
 function testInvalidAddressForSMS(aInvalidAddr)  {
-  log("mozMobileMessage.send(...) should get 'InvalidAddressError' error " +
+  log("manager.send(...) should get 'InvalidAddressError' error " +
       "when attempting to send SMS to: " + aInvalidAddr);
 
-  let request = mozMobileMessage.send(aInvalidAddr, "Test");
+  let request = manager.send(aInvalidAddr, "Test");
 
   request.onerror = function(event) {
     log("Received 'onerror' DOMRequest event.");
     let error = event.target.error;
     ok(error instanceof DOMError, "should be a valid DOMError object");
     ok(error.name === "InvalidAddressError", "should be 'InvalidAddressError'");
     tasks.next();
   };
 }
 
 function testInvalidAddressForMMS(aInvalidAddrs)  {
-  log("mozMobileMessage.sendMMS(...) should get 'InvalidAddressError' error " +
+  log("manager.sendMMS(...) should get 'InvalidAddressError' error " +
       "when attempting to send MMS to: " + aInvalidAddrs);
 
-  let request = mozMobileMessage.sendMMS({
+  let request = manager.sendMMS({
     subject: "Test",
     receivers: aInvalidAddrs,
     attachments: [],
   });
 
   request.onerror = function(event) {
     log("Received 'onerror' DOMRequest event.");
     let error = event.target.error;
@@ -110,18 +110,19 @@ function testInvalidAddressForMMS(aInval
     ok(error.name === "InvalidAddressError", "should be 'InvalidAddressError'");
     tasks.next();
   };
 }
 
 tasks.push(function () {
   log("Verifying initial state.");
 
-  mozMobileMessage = window.navigator.mozMobileMessage;
-  ok(mozMobileMessage instanceof MozMobileMessageManager);
+  manager = window.navigator.mozMobileMessage;
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
 
   tasks.next();
 });
 
 // Test sending SMS to invalid addresses.
 tasks.push(testInvalidAddressForSMS.bind(this, "&%&"));
 tasks.push(testInvalidAddressForSMS.bind(this, ""));
 
--- a/dom/mobilemessage/tests/marionette/test_mark_msg_read.js
+++ b/dom/mobilemessage/tests/marionette/test_mark_msg_read.js
@@ -1,22 +1,23 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.addPermission("sms", true, document);
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let smsList = new Array();
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   simulateIncomingSms();
 }
 
 function simulateIncomingSms() {
   let text = "Incoming SMS courtesy of Firefox OS";
   let remoteNumber = "5557779999";
 
   log("Simulating incoming SMS.");
@@ -25,17 +26,17 @@ function simulateIncomingSms() {
   rcvdEmulatorCallback = false;
   runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
     is(result[0], "OK", "emulator callback");
     rcvdEmulatorCallback = true;
   });
 }
 
 // Callback for incoming SMS
-sms.onreceived = function onreceived(event) {
+manager.onreceived = function onreceived(event) {
   log("Received 'onreceived' sms event.");
   let incomingSms = event.message;
   log("Received SMS (id: " + incomingSms.id + ").");
   is(incomingSms.read, false, "incoming message read");
   log("SMS read attribute: " + incomingSms.read + ".");
 
   // Add newly received message id to array of msgs
   smsList.push(incomingSms.id);
@@ -49,71 +50,71 @@ sms.onreceived = function onreceived(eve
 function sendSms() {
   let gotSmsSent = false;
   let gotRequestSuccess = false;
   let remoteNumber = "5557779999";
   let text = "Mo Mo Mo Zilla Zilla Zilla!";
 
   log("Sending an SMS.");
 
-  sms.onsent = function(event) {
-    log("Received 'onsent' smsmanager event.");
+  manager.onsent = function(event) {
+    log("Received 'onsent' event.");
     gotSmsSent = true;
     let sentSms = event.message;
     log("Sent SMS (id: " + sentSms.id + ").");
     is(sentSms.read, true, "sent sms read");
     log("SMS read attribute: " + sentSms.read + ".");
 
     // Add newly received message id to array of msgs
     smsList.push(sentSms.id);
 
     if (gotSmsSent && gotRequestSuccess) {
       test1();
     }
   };
 
-  let request = sms.send(remoteNumber, text);
+  let request = manager.send(remoteNumber, text);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if(event.target.result) {
       gotRequestSuccess = true;
       if (gotSmsSent && gotRequestSuccess) {
         test1();
       }
     } else {
-      log("smsrequest returned false for sms.send");
+      log("smsrequest returned false for manager.send");
       ok(false, "SMS send failed");
       deleteMsgs();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.send request returned unexpected error: "
+    ok(false, "manager.send request returned unexpected error: "
         + event.target.error.name );
     deleteMsgs();
   };
 }
 
 function markMessageAndVerify(smsId, readBool, nextFunction) {
-  let request = sms.markMessageRead(smsId, readBool);
+  let request = manager.markMessageRead(smsId, readBool);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
 
     // Success from MarkMessageRead, the result should match what we set
     is(event.target.result, readBool, "result matches what was set");
 
     // Message marked read/unread, now verify
     log("Getting SMS message (id: " + smsId + ").");
-    let requestRet = sms.getMessage(smsId);
+    let requestRet = manager.getMessage(smsId);
     ok(requestRet, "smsrequest obj returned");
 
     requestRet.onsuccess = function(event) {
       log("Received 'onsuccess' smsrequest event.");
       ok(event.target.result, "smsrequest event.target.result");
       let foundSms = event.target.result;
       is(foundSms.id, smsId, "SMS id matches");
       log("SMS read attribute: " + foundSms.read + ".");
@@ -136,17 +137,17 @@ function markMessageAndVerify(smsId, rea
       ok(false, "Could not get SMS");
       deleteMsgs();
     };
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.markMessageRead request returned unexpected error: "
+    ok(false, "manager.markMessageRead request returned unexpected error: "
         + event.target.error.name );
     nextFunction();
   };
 }
 
 function test1() {
   rcvdSms = smsList[0];
   log("Test 1: Marking received SMS (id: " + rcvdSms + ") read.");
@@ -182,46 +183,46 @@ function test6() {
   log("Test 6: Marking an already unread SMS (id: " + rcvdSms + ") unread.");
   markMessageAndVerify(rcvdSms, false, deleteMsgs);
 }
 
 function deleteMsgs() {
   let smsId = smsList.shift();
 
   log("Deleting SMS (id: " + smsId + ").");
-  let request = sms.delete(smsId);
+  let request = manager.delete(smsId);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       // Message deleted, continue until none are left
       if (smsList.length) {
         deleteMsgs();
       } else {
         cleanUp();
       }
     } else {
       log("SMS delete failed.");
-      ok(false, "sms.delete request returned false");
+      ok(false, "manager.delete request returned false");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_mark_msg_read_error.js
+++ b/dom/mobilemessage/tests/marionette/test_mark_msg_read_error.js
@@ -1,22 +1,23 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.addPermission("sms", true, document);
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let smsId;
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   simulateIncomingSms();
 }
 
 function simulateIncomingSms() {
   let text = "Incoming SMS courtesy of Firefox OS";
   let remoteNumber = "5557779999";
 
   log("Simulating incoming SMS.");
@@ -25,31 +26,31 @@ function simulateIncomingSms() {
   rcvdEmulatorCallback = false;
   runEmulatorCmd("sms send " + remoteNumber + " " + text, function(result) {
     is(result[0], "OK", "emulator callback");
     rcvdEmulatorCallback = true;
   });
 }
 
 // Callback for incoming SMS
-sms.onreceived = function onreceived(event) {
+manager.onreceived = function onreceived(event) {
   log("Received 'onreceived' sms event.");
   let incomingSms = event.message;
   log("Received SMS (id: " + incomingSms.id + ").");
   is(incomingSms.read, false, "incoming message read");
   smsId = incomingSms.id;
 
   // Wait for emulator to catch up before continuing
   waitFor(test1, function() {
     return(rcvdEmulatorCallback);
   });
 };
 
 function markMsgError(invalidId, readBool, nextFunction) {
-  let requestRet = sms.markMessageRead(invalidId, readBool);
+  let requestRet = manager.markMessageRead(invalidId, readBool);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event, but expected error.");
     ok(false, "Smsrequest should have returned error but did not");
     nextFunction();
   };
 
@@ -74,42 +75,42 @@ function test2() {
   invalidId = -1;
   log("Attempting to mark sms unread using an invalid id (id: " + invalidId
       + "), expect error.");
   markMsgError(invalidId, false, deleteMsg);
 }
 
 function deleteMsg() {
   log("Deleting SMS (id: " + smsId + ").");
-  let request = sms.delete(smsId);
+  let request = manager.delete(smsId);
   ok(request instanceof DOMRequest,
       "request is instanceof " + request.constructor);
 
   request.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       // Message deleted
       cleanUp();
     } else {
       log("SMS delete failed.");
-      ok(false,"sms.delete request returned false");
+      ok(false,"manager.delete request returned false");
       cleanUp();
     }
   };
 
   request.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function cleanUp() {
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_massive_incoming_delete.js
+++ b/dom/mobilemessage/tests/marionette/test_massive_incoming_delete.js
@@ -4,17 +4,17 @@
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
 const SENDER = "5555552368"; // the remote number
 const RECEIVER = "15555215554"; // the emulator's number
 
-let sms = window.navigator.mozMobileMessage;
+let manager = window.navigator.mozMobileMessage;
 let MSG_TEXT = "Mozilla Firefox OS!";
 let SMS_NUMBER = 100;
 
 let SmsList = [];
 let checkDone = true;
 let emulatorReady = true;
 
 let pendingEmulatorCmdCount = 0;
@@ -63,17 +63,17 @@ let tasks = {
 };
 
 function taskNextWrapper() {
   tasks.next();
 }
 
 function verifySmsExists(incomingSms) {
   log("Getting SMS (id: " + incomingSms.id + ").");
-  let requestRet = sms.getMessage(incomingSms.id);
+  let requestRet = manager.getMessage(incomingSms.id);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, incomingSms.id, "found SMS id matches");
     is(foundSms.threadId, incomingSms.threadId, "found SMS thread id matches");
@@ -97,17 +97,17 @@ function verifySmsExists(incomingSms) {
     ok(false,"SMS was not found");
     tasks.finish();
   };
 }
 
 let verifDeletedCount = 0;
 function verifySmsDeleted(smsId) {
   log("Getting SMS (id: " + smsId + ").");
-  let requestRet = sms.getMessage(smsId);
+  let requestRet = manager.getMessage(smsId);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, smsId, "found SMS id matches");
     is(foundSms.body, MSG_TEXT, "found SMS msg text matches");
@@ -122,21 +122,22 @@ function verifySmsDeleted(smsId) {
     is(event.target.error.name, "NotFoundError", "error returned");
     log("Could not get SMS (id: " + smsId + ") as expected.");
     verifDeletedCount++;
   };
 }
 
 tasks.push(function init() {
   log("Initialize test object.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
 
   // Callback for incoming sms
-  sms.onreceived = function onreceived(event) {
-    log("Received 'onreceived' smsmanager event.");
+  manager.onreceived = function onreceived(event) {
+    log("Received 'onreceived' event.");
     let incomingSms = event.message;
     ok(incomingSms, "incoming sms");
     ok(incomingSms.id, "sms id");
     log("Received SMS (id: " + incomingSms.id + ").");
     ok(incomingSms.threadId, "thread id");
     is(incomingSms.body, MSG_TEXT, "msg body");
     is(incomingSms.delivery, "received", "delivery");
     is(incomingSms.deliveryStatus, "success", "deliveryStatus");
@@ -163,54 +164,54 @@ tasks.push(function sendAllSms() {
   });
 });
 
 tasks.push(function deleteAllSms() {
   log("Deleting SMS using smsmsg obj array parameter.");
   let deleteStart = Date.now();
   log("deleteStart: " + deleteStart);
   log("SmsList: " + JSON.stringify(SmsList));
-  let requestRet = sms.delete(SmsList);
+  let requestRet = manager.delete(SmsList);
   ok(requestRet,"smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     let deleteDone = Date.now();
     log("Delete " + SMS_NUMBER + " SMS takes " + (deleteDone - deleteStart) + " ms.");
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       for (let i = 0; i < SmsList.length; i++) {
         verifySmsDeleted(SmsList[i].id);
       }
     } else {
-      log("smsrequest returned false for sms.delete");
+      log("smsrequest returned false for manager.delete");
       ok(false, "SMS delete failed");
     }
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name);
     tasks.finish();
   };
 
   waitFor(taskNextWrapper, function() {
     return verifDeletedCount === SMS_NUMBER;
   });
 });
 
 // WARNING: All tasks should be pushed before this!!!
 tasks.push(function cleanUp() {
   if (pendingEmulatorCmdCount) {
     window.setTimeout(cleanUp, 100);
     return;
   }
 
-  sms.onreceived = null;
+  manager.onreceived = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.setBoolPref("dom.sms.enabled", false);
   log("Finish!!!");
   finish();
 });
 
 // Start the test
 tasks.run();
--- a/dom/mobilemessage/tests/marionette/test_message_classes.js
+++ b/dom/mobilemessage/tests/marionette/test_message_classes.js
@@ -10,18 +10,19 @@ const PDU_PID_NORMAL = "00";
 const PDU_PID_ANSI_136_R_DATA = "7C";
 const PDU_PID_USIM_DATA_DOWNLOAD = "7F";
 const PDU_TIMESTAMP = "00101000000000"; // 2000/01/01
 const PDU_UDL = "01";
 const PDU_UD = "41";
 
 SpecialPowers.addPermission("sms", true, document);
 
-let sms = window.navigator.mozSms;
-ok(sms instanceof MozSmsManager);
+let manager = window.navigator.mozMobileMessage;
+ok(manager instanceof MozMobileMessageManager,
+   "manager is instance of " + manager.constructor);
 
 let pendingEmulatorCmdCount = 0;
 function sendSmsPduToEmulator(pdu) {
   ++pendingEmulatorCmdCount;
 
   let cmd = "sms pdu " + pdu;
   runEmulatorCmd(cmd, function (result) {
     --pendingEmulatorCmdCount;
@@ -56,28 +57,28 @@ function checkMessage(message, id, threa
 function test_message_class_0() {
   let allDCSs = [
     "10", // General Group: 00xx
     "50", // Automatica Deletion Group: 01xx
     "F0"  // (no name) Group: 1111
   ];
 
   function do_test(dcsIndex) {
-    sms.addEventListener("received", function onReceived(event) {
-      sms.removeEventListener("received", onReceived);
+    manager.addEventListener("received", function onReceived(event) {
+      manager.removeEventListener("received", onReceived);
 
       let message = event.message;
       checkMessage(message, -1, 0, "class-0");
       ok(event.message.timestamp.getTime() >= timeBeforeSend,
          "Message's timestamp should be greater then the timetamp of sending");
       ok(event.message.timestamp.getTime() <= Date.now(),
          "Message's timestamp should be lesser than the timestamp of now");
 
       // Make sure the message is not stored.
-      let cursor = sms.getMessages(null, false);
+      let cursor = manager.getMessages(null, false);
       cursor.onsuccess = function onsuccess() {
         if (cursor.result) {
           // Here we check whether there is any message of the same sender.
           isnot(cursor.result.sender, message.sender, "cursor.result.sender");
 
           cursor.continue();
           return;
         }
@@ -104,18 +105,18 @@ function test_message_class_0() {
   }
 
   log("Checking Message Class 0");
   do_test(0);
 }
 
 function doTestMessageClassGeneric(allDCSs, messageClass, next) {
   function do_test(dcsIndex) {
-    sms.addEventListener("received", function onReceived(event) {
-      sms.removeEventListener("received", onReceived);
+    manager.addEventListener("received", function onReceived(event) {
+      manager.removeEventListener("received", onReceived);
 
       // Make sure we can correctly receive the message
       checkMessage(event.message, null, null, messageClass);
       ok(event.message.timestamp.getTime() >= timeBeforeSend,
          "Message's timestamp should be greater then the timetamp of sending");
       ok(event.message.timestamp.getTime() <= Date.now(),
          "Message's timestamp should be lesser than the timestamp of now");
 
@@ -182,32 +183,32 @@ function test_message_class_2() {
         // Since we have "data download via SMS Point-to-Point" service enabled
         // but no working implementation in emulator SIM, all class 2 messages
         // bug normal ones should goto `dataDownloadViaSMSPP()` and we should
         // not receive the message in content page.
         ok(false, "SMS-PP messages shouldn't be sent to content");
       }
 
       function next() {
-        sms.removeEventListener("received", onReceived);
+        manager.removeEventListener("received", onReceived);
 
         ++pidIndex;
         if (pidIndex >= allPIDs.length) {
           ++dcsIndex;
           if (dcsIndex >= allDCSs.length) {
             window.setTimeout(test_message_class_3, 0);
           } else {
             window.setTimeout(do_test_dcs.bind(null, dcsIndex), 0);
           }
         } else {
           window.setTimeout(do_test_pid.bind(null, pidIndex), 0);
         }
       }
 
-      sms.addEventListener("received", onReceived);
+      manager.addEventListener("received", onReceived);
 
       if (pidIndex != 0) {
         // Wait for three seconds to ensure we don't receive the message.
         window.setTimeout(next, 3000);
       }
 
       let pid = allPIDs[pidIndex];
       log("    Testing PID " + pid);
--- a/dom/mobilemessage/tests/marionette/test_mmsmessage_attachments.js
+++ b/dom/mobilemessage/tests/marionette/test_mmsmessage_attachments.js
@@ -36,24 +36,24 @@ let tasks = {
     this._tasks[this._tasks.length - 1]();
   },
 
   run: function run() {
     this.next();
   }
 };
 
-let mozMobileMessage;
+let manager;
 
 function getAllMessages(callback, filter, reverse) {
   if (!filter) {
     filter = new MozSmsFilter;
   }
   let messages = [];
-  let request = mozMobileMessage.getMessages(filter, reverse || false);
+  let request = manager.getMessages(filter, reverse || false);
   request.onsuccess = function(event) {
     if (request.result) {
       messages.push(request.result);
       request.continue();
       return;
     }
 
     window.setTimeout(callback.bind(null, messages), 0);
@@ -64,50 +64,51 @@ function deleteAllMessages() {
   getAllMessages(function deleteAll(messages) {
     let message = messages.shift();
     if (!message) {
       ok(true, "all messages deleted");
       tasks.next();
       return;
     }
 
-    let request = mozMobileMessage.delete(message.id);
+    let request = manager.delete(message.id);
     request.onsuccess = deleteAll.bind(null, messages);
     request.onerror = function (event) {
       ok(false, "failed to delete all messages");
       tasks.finish();
     }
   });
 }
 
 tasks.push(function () {
   log("Verifying initial state.");
 
-  mozMobileMessage = window.navigator.mozMobileMessage;
-  ok(mozMobileMessage instanceof MozMobileMessageManager);
+  manager = window.navigator.mozMobileMessage;
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
 
   tasks.next();
 });
 
 tasks.push(function () {
   log("MmsMessage.attachments should be an empty array.");
 
-  mozMobileMessage.onfailed = function (event) {
-    mozMobileMessage.onfailed = null;
+  manager.onfailed = function (event) {
+    manager.onfailed = null;
 
     let message = event.message;
     ok(Array.isArray(message.attachments) && message.attachments.length === 0,
        "message.attachments should be an empty array.");
 
     tasks.next();
   };
 
   // Have a long long subject causes the send fails, so we don't need
   // networking here.
-  mozMobileMessage.sendMMS({
+  manager.sendMMS({
     subject: new Array(MMS_MAX_LENGTH_SUBJECT + 2).join("a"),
     receivers: ["1", "2"],
     attachments: [],
   });
 });
 
 tasks.push(deleteAllMessages);
 
--- a/dom/mobilemessage/tests/marionette/test_outgoing.js
+++ b/dom/mobilemessage/tests/marionette/test_outgoing.js
@@ -5,17 +5,20 @@ MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.setBoolPref("dom.sms.strict7BitEncoding", false);
 SpecialPowers.setBoolPref("dom.sms.requestStatusReport", true);
 SpecialPowers.addPermission("sms", true, document);
 
 const SENDER = "15555215554"; // the emulator's number
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
+ok(manager instanceof MozMobileMessageManager,
+   "manager is instance of " + manager.constructor);
+
 const SHORT_BODY = "Hello SMS world!";
 const LONG_BODY = "Let me not to the marriage of true minds\n"
                 + "Admit impediments. Love is not love\n"
                 + "Which alters when it alteration finds,\n"
                 + "Or bends with the remover to remove:\n\n"
                 + "O, no! it is an ever-fix`ed mark,\n"
                 + "That looks on tempests and is never shaken;\n"
                 + "It is the star to every wand'ring bark,\n"
@@ -54,18 +57,18 @@ function doSendMessageAndCheckSuccess(re
     // Make sure we've send a message to each distinct receiver.
     for (let i = 0; i < rs.length; i++) {
       let opt = options[rs[i]];
       if (!(opt && opt.onSentCalled && opt.onRequestSuccessCalled)) {
         return;
       }
     }
 
-    sms.removeEventListener("sending", onSmsSending);
-    sms.removeEventListener("sent", onSmsSent);
+    manager.removeEventListener("sending", onSmsSending);
+    manager.removeEventListener("sent", onSmsSent);
 
     log("Done!");
     window.setTimeout(callback, 0);
   }
 
   function checkSentMessage(message, mark) {
     checkMessage(message, "sent", body);
 
@@ -99,17 +102,17 @@ function doSendMessageAndCheckSuccess(re
     ok(event.target instanceof DOMRequest,
        "event.target is instanceof " + event.target.constructor);
     event.target.removeEventListener("success", onRequestSuccess);
 
     checkSentMessage(event.target.result, "onRequestSuccessCalled");
   }
 
   function onSmsSending(event) {
-    log("SmsManager.onsending event received.");
+    log("onsending event received.");
 
     // Bug 838542: following check throws an exception and fails this case.
     // ok(event instanceof MozSmsEvent,
     //    "event is instanceof " + event.constructor)
     ok(event, "event is valid");
 
     let message = event.message;
     checkMessage(message, "sending", body);
@@ -130,30 +133,30 @@ function doSendMessageAndCheckSuccess(re
     options[receiver] = {
       saved: message,
       onSentCalled: false,
       onRequestSuccessCalled: false
     };
   }
 
   function onSmsSent(event) {
-    log("SmsManager.onsent event received.");
+    log("onsent event received.");
 
     // Bug 838542: following check throws an exception and fails this case.
     // ok(event instanceof MozSmsEvent,
     //    "event is instanceof " + event.constructor)
     ok(event, "event is valid");
 
     checkSentMessage(event.message, "onSentCalled");
   }
 
-  sms.addEventListener("sending", onSmsSending);
-  sms.addEventListener("sent", onSmsSent);
+  manager.addEventListener("sending", onSmsSending);
+  manager.addEventListener("sent", onSmsSent);
 
-  let result = sms.send(receivers, body);
+  let result = manager.send(receivers, body);
   is(Array.isArray(result), Array.isArray(receivers),
      "send() returns an array of requests if receivers is an array");
   if (Array.isArray(receivers)) {
     is(result.length, receivers.length, "returned array length");
   } else {
     result = [result];
   }
 
@@ -173,17 +176,17 @@ function testSendMessage() {
 function testSendMultipartMessage() {
   log("Testing sending message to one receiver:");
   doSendMessageAndCheckSuccess("1", LONG_BODY,
                                testSendMessageToMultipleRecipients);
 }
 
 function testSendMessageToMultipleRecipients() {
   log("Testing sending message to multiple receivers:");
-  // TODO: bug 788928 - add test cases for nsIDOMSmsManager.ondelivered event
+  // TODO: bug 788928 - add test cases for ondelivered event.
   doSendMessageAndCheckSuccess(["1", "2"], SHORT_BODY, cleanUp);
 }
 
 function cleanUp() {
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   SpecialPowers.clearUserPref("dom.sms.strict7BitEncoding");
   SpecialPowers.clearUserPref("dom.sms.requestStatusReport");
--- a/dom/mobilemessage/tests/marionette/test_outgoing_delete.js
+++ b/dom/mobilemessage/tests/marionette/test_outgoing_delete.js
@@ -5,33 +5,34 @@ MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.setBoolPref("dom.sms.requestStatusReport", true);
 SpecialPowers.addPermission("sms", true, document);
 
 const SENDER = "15555215554"; // the emulator's number
 const RECEIVER = "5551117777"; // the destination number
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 let msgText = "Mozilla Firefox OS!";
 let gotSmsOnsent = false;
 let gotReqOnsuccess = false;
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   sendSms();
 }
 
 function sendSms() {
   let smsId = 0;
 
   log("Sending an SMS.");
-  sms.onsent = function(event) {
-    log("Received 'onsent' smsmanager event.");
+  manager.onsent = function(event) {
+    log("Received 'onsent' event.");
     gotSmsOnsent = true;
     let sentSms = event.message;
     ok(sentSms, "outgoing sms");
     ok(sentSms.id, "sms id");
     smsId = sentSms.id;
     log("Sent SMS (id: " + smsId + ").");
     ok(sentSms.threadId, "thread id");
     is(sentSms.body, msgText, "msg body");
@@ -41,43 +42,43 @@ function sendSms() {
     is(sentSms.receiver, RECEIVER, "receiver");
     is(sentSms.sender, SENDER, "sender");
     is(sentSms.messageClass, "normal", "messageClass");
     ok(sentSms.timestamp instanceof Date, "timestamp is istanceof date");
 
     if (gotSmsOnsent && gotReqOnsuccess) { verifySmsExists(smsId); }
   };
 
-  let requestRet = sms.send(RECEIVER, msgText);
+  let requestRet = manager.send(RECEIVER, msgText);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     gotReqOnsuccess = true;
     if(event.target.result){
       if (gotSmsOnsent && gotReqOnsuccess) { verifySmsExists(smsId); }
     } else {
-      log("smsrequest returned false for sms.send");
+      log("smsrequest returned false for manager.send");
       ok(false,"SMS send failed");
       cleanUp();
     }
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.send request returned unexpected error: "
+    ok(false, "manager.send request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function verifySmsExists(smsId) {
   log("Getting SMS (id: " + smsId + ").");
-  let requestRet = sms.getMessage(smsId);
+  let requestRet = manager.getMessage(smsId);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, smsId, "found SMS id matches");
     is(foundSms.body, msgText, "found SMS msg text matches");
@@ -97,42 +98,42 @@ function verifySmsExists(smsId) {
     log("Could not get SMS (id: " + smsId + ") but should have.");
     ok(false,"SMS was not found");
     cleanUp();
   };
 }
 
 function deleteSms(smsId){
   log("Deleting SMS (id: " + smsId + ") using sms id parameter.");
-  let requestRet = sms.delete(smsId);
+  let requestRet = manager.delete(smsId);
   ok(requestRet,"smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if(event.target.result){
       verifySmsDeleted(smsId);
     } else {
-      log("smsrequest returned false for sms.delete");
+      log("smsrequest returned false for manager.delete");
       ok(false,"SMS delete failed");
       cleanUp();
     }
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: "
+    ok(false, "manager.delete request returned unexpected error: "
         + event.target.error.name );
     cleanUp();
   };
 }
 
 function verifySmsDeleted(smsId) {
   log("Getting SMS (id: " + smsId + ").");
-  let requestRet = sms.getMessage(smsId);
+  let requestRet = manager.getMessage(smsId);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, smsId, "found SMS id matches");
     is(foundSms.body, msgText, "found SMS msg text matches");
@@ -146,17 +147,17 @@ function verifySmsDeleted(smsId) {
     ok(event.target.error, "domerror obj");
     is(event.target.error.name, "NotFoundError", "error returned");
     log("Could not get SMS (id: " + smsId + ") as expected.");
     cleanUp();
   };
 }
 
 function cleanUp() {
-  sms.onsent = null;
+  manager.onsent = null;
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   SpecialPowers.clearUserPref("dom.sms.requestStatusReport");
   finish();
 }
 
 // Start the test
 verifyInitialState();
--- a/dom/mobilemessage/tests/marionette/test_outgoing_max_segments.js
+++ b/dom/mobilemessage/tests/marionette/test_outgoing_max_segments.js
@@ -1,82 +1,83 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
-let sms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 // https://developer.mozilla.org/en-US/docs/DOM/SmsManager
 let maxCharsPerSms = 160;
 let maxSegments = 10; // 10 message segments concatenated into 1 multipart SMS
 
 function verifyInitialState() {
   log("Verifying initial state.");
-  ok(sms, "mozSms");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   sendSms();
 }
 
 function sendSms() {
   let destNumber = "5551234567";
   let msgText = "";
   let gotReqOnSuccess = false;
   let gotSmsOnSent = false;
   let sentSms;
 
   // Build the message text
   msgText = new Array((maxCharsPerSms * maxSegments) + 1).join('a');
   log("Sending multipart SMS (" + msgText.length + " chars total).");
 
-  sms.onsent = function(event) {
-    sms.onsent = null;
-    log("Received 'onsent' smsmanager event.");
+  manager.onsent = function(event) {
+    manager.onsent = null;
+    log("Received 'onsent' event.");
 
     gotSmsOnSent = true;
     sentSms = event.message;
     ok(sentSms, "outgoing sms");
     ok(sentSms.id, "sms id");
     log("Sent SMS (id: " + sentSms.id + ").");
     ok(sentSms.threadId, "thread id");
     is(sentSms.body.length, msgText.length, "text length");
     is(sentSms.body, msgText, "msg body");
     is(sentSms.delivery, "sent", "delivery");
 
     if (gotReqOnSuccess) { verifySmsExists(sentSms); }
   };
 
-  let requestRet = sms.send(destNumber, msgText);
+  let requestRet = manager.send(destNumber, msgText);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     gotReqOnSuccess = true;
     if (event.target.result) {
       if (gotSmsOnSent) { verifySmsExists(sentSms); }
     } else {
-      log("smsrequest returned false for sms.send");
+      log("smsrequest returned false for manager.send");
       ok(false, "SMS send failed");
       cleanUp();
     }
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.send request returned unexpected error: " +
+    ok(false, "manager.send request returned unexpected error: " +
               event.target.error.name);
     cleanUp();
   };
 }
 
 function verifySmsExists(sentSms) {
   log("Getting SMS (id: " + sentSms.id + ").");
-  let requestRet = sms.getMessage(sentSms.id);
+  let requestRet = manager.getMessage(sentSms.id);
   ok(requestRet, "smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, sentSms.id, "found SMS id matches");
     is(foundSms.threadId, sentSms.threadId, "found SMS thread id matches");
@@ -93,34 +94,34 @@ function verifySmsExists(sentSms) {
     log("Could not get SMS (id: " + sentSms.id + ") but should have.");
     ok(false, "SMS was not found");
     cleanUp();
   };
 }
 
 function deleteSms(smsMsgObj) {
   log("Deleting SMS (id: " + smsMsgObj.id + ") using smsmsg obj parameter.");
-  let requestRet = sms.delete(smsMsgObj);
+  let requestRet = manager.delete(smsMsgObj);
   ok(requestRet,"smsrequest obj returned");
 
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     if (event.target.result) {
       cleanUp();
     } else {
-      log("smsrequest returned false for sms.delete");
+      log("smsrequest returned false for manager.delete");
       ok(false, "SMS delete failed");
       cleanUp();
     }
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
-    ok(false, "sms.delete request returned unexpected error: " +
+    ok(false, "manager.delete request returned unexpected error: " +
               event.target.error.name);
     cleanUp();
   };
 }
 
 function cleanUp() {
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
--- a/dom/mobilemessage/tests/marionette/test_phone_number_normalization.js
+++ b/dom/mobilemessage/tests/marionette/test_phone_number_normalization.js
@@ -51,17 +51,17 @@ let tasks = {
   }
 };
 
 function getAllMessages(callback, filter, reverse) {
   if (!filter) {
     filter = new MozSmsFilter;
   }
   let messages = [];
-  let request = mozSms.getMessages(filter, reverse || false);
+  let request = manager.getMessages(filter, reverse || false);
   request.onsuccess = function(event) {
     if (request.result) {
       messages.push(request.result);
       request.continue();
       return;
     }
 
     window.setTimeout(callback.bind(null, messages), 0);
@@ -72,51 +72,52 @@ function deleteAllMessages() {
   getAllMessages(function deleteAll(messages) {
     let message = messages.shift();
     if (!message) {
       ok(true, "all messages deleted");
       tasks.next();
       return;
     }
 
-    let request = mozSms.delete(message.id);
+    let request = manager.delete(message.id);
     request.onsuccess = deleteAll.bind(null, messages);
     request.onerror = function (event) {
       ok(false, "failed to delete all messages");
       tasks.finish();
     }
   });
 }
 
 function validate(number, normalizedNumber) {
   log("Checking ('" + number + "', '" + normalizedNumber + "')");
 
-  let sendRequest = mozSms.send(number, "ping");
+  let sendRequest = manager.send(number, "ping");
   sendRequest.onsuccess = function onSendSuccess(event) {
     let sentMessage = event.target.result;
 
-    mozSms.onreceived = function onreceived(event) {
+    manager.onreceived = function onreceived(event) {
       let receivedMessage = event.message;
       is(sentMessage.threadId, receivedMessage.threadId,
          "message threadIds are supposed to be matched");
 
       tasks.next();
     };
     sendSmsToEmulator(normalizedNumber, "pong");
   };
   sendRequest.onerror = function onSendError(event) {
     ok(false, "failed to send message.");
     tasks.finish();
   };
 }
 
-let mozSms = window.navigator.mozSms;
+let manager = window.navigator.mozMobileMessage;
 tasks.push(function () {
-  log("Checking mozSms.");
-  ok(mozSms instanceof MozSmsManager);
+  log("Verifying initial state.");
+  ok(manager instanceof MozMobileMessageManager,
+     "manager is instance of " + manager.constructor);
   tasks.next();
 });
 
 tasks.push(deleteAllMessages);
 
 tasks.push(validate.bind(null, "+886-9-87-654-321", "+886987654321"));
 tasks.push(validate.bind(null, "+886 9 87654321", "+886987654321"));
 tasks.push(validate.bind(null, "+886(9)87654321", "+886987654321"));
--- a/dom/mobilemessage/tests/marionette/test_segment_info.js
+++ b/dom/mobilemessage/tests/marionette/test_segment_info.js
@@ -10,30 +10,31 @@ const LEN_UCS2 = 70;
 const LEN_UCS2_WITH_8BIT_REF = 67;
 const LEN_UCS2_WITH_16BIT_REF = 66;
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 let currentStrict7BitEncoding = false;
 SpecialPowers.setBoolPref("dom.sms.strict7BitEncoding", currentStrict7BitEncoding);
 SpecialPowers.addPermission("sms", true, document);
 
-let sms = window.navigator.mozSms;
-ok(sms instanceof MozSmsManager);
+let manager = window.navigator.mozMobileMessage;
+ok(manager instanceof MozMobileMessageManager,
+   "manager is instance of " + manager.constructor);
 
 function times(str, n) {
   return (new Array(n + 1)).join(str);
 }
 
 function doTest(text, strict7BitEncoding, expected) {
   if (strict7BitEncoding != currentStrict7BitEncoding) {
     currentStrict7BitEncoding = strict7BitEncoding;
     SpecialPowers.setBoolPref("dom.sms.strict7BitEncoding", currentStrict7BitEncoding);
   }
 
-  let result = sms.getSegmentInfoForText(text);
+  let result = manager.getSegmentInfoForText(text);
   ok(result, "result of GetSegmentInfoForText is valid");
   is(result.segments, expected[0], "segments");
   is(result.charsPerSegment, expected[1], "charsPerSegment");
   is(result.charsAvailableInLastSegment, expected[2], "charsAvailableInLastSegment");
 }
 
 function cleanUp() {
   SpecialPowers.removePermission("sms", document);
--- a/dom/mobilemessage/tests/marionette/test_strict_7bit_encoding.js
+++ b/dom/mobilemessage/tests/marionette/test_strict_7bit_encoding.js
@@ -122,18 +122,19 @@ const GSM_SMS_STRICT_7BIT_CHARMAP = {
 
 // Emulator will loop back the outgoing SMS if the phone number equals to its
 // control port, which is 5554 for the first emulator instance.
 const SELF = "5554";
 
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 SpecialPowers.addPermission("sms", true, document);
 
-let sms = window.navigator.mozSms;
-ok(sms instanceof MozSmsManager);
+let manager = window.navigator.mozMobileMessage;
+ok(manager instanceof MozMobileMessageManager,
+   "manager is instance of " + manager.constructor);
 
 let tasks = {
   // List of test fuctions. Each of them should call |tasks.next()| when
   // completed or |tasks.finish()| to jump to the last one.
   _tasks: [],
   _nextTaskIndex: 0,
 
   push: function push(func) {
@@ -173,26 +174,26 @@ function testStrict7BitEncodingHelper(se
   let count = 0;
   function done(step) {
     count += step;
     if (count >= 2) {
       window.setTimeout(tasks.next.bind(tasks), 0);
     }
   }
 
-  sms.addEventListener("received", function onReceived(event) {
+  manager.addEventListener("received", function onReceived(event) {
     event.target.removeEventListener("received", onReceived);
 
     let message = event.message;
     is(message.body, received, "received message.body");
 
     done(1);
   });
 
-  let request = sms.send(SELF, sent);
+  let request = manager.send(SELF, sent);
   request.addEventListener("success", function onRequestSuccess(event) {
     let message = event.target.result;
     is(message.body, sent, "sent message.body");
 
     done(1);
   });
   request.addEventListener("error", function onRequestError(event) {
     ok(false, "Can't send message out!!!");
--- a/dom/mobilemessage/tests/marionette/test_update_thread_record_in_delete.js
+++ b/dom/mobilemessage/tests/marionette/test_update_thread_record_in_delete.js
@@ -5,18 +5,19 @@ MARIONETTE_TIMEOUT = 60000;
 
 const FROM = "09123456789";
 const PREFIX = "msg_";
 const MSGS = 3;
 
 SpecialPowers.addPermission("sms", true, document);
 SpecialPowers.setBoolPref("dom.sms.enabled", true);
 
-let mozSms = window.navigator.mozSms;
-ok(mozSms instanceof MozSmsManager);
+let manager = window.navigator.mozMobileMessage;
+ok(manager instanceof MozMobileMessageManager,
+   "manager is instance of " + manager.constructor);
 
 let pendingEmulatorCmdCount = 0;
 function sendSmsToEmulator(from, text) {
   ++pendingEmulatorCmdCount;
 
   let cmd = "sms send " + from + " " + text;
   runEmulatorCmd(cmd, function (result) {
     --pendingEmulatorCmdCount;
@@ -58,31 +59,31 @@ let tasks = {
   }
 };
 
 function getAllMessages(callback, filter, reverse) {
   if (!filter) {
     filter = new MozSmsFilter;
   }
   let messages = [];
-  let cursor = mozSms.getMessages(filter, reverse || false);
+  let cursor = manager.getMessages(filter, reverse || false);
   cursor.onsuccess = function(event) {
     if (!this.done) {
       messages.push(this.result);
       this.continue();
       return;
     }
 
     window.setTimeout(callback.bind(null, messages), 0);
   }
 }
 
 function getAllThreads(callback) {
   let threads = [];
-  let cursor = mozSms.getThreads();
+  let cursor = manager.getThreads();
   cursor.onsuccess = function(event) {
     if (!this.done) {
       threads.push(this.result);
       this.continue();
       return;
     }
 
     window.setTimeout(callback.bind(null, threads), 0);
@@ -93,17 +94,17 @@ function deleteAllMessages() {
   getAllMessages(function deleteAll(messages) {
     let message = messages.shift();
     if (!message) {
       ok(true, "all messages deleted");
       tasks.next();
       return;
     }
 
-    let request = mozSms.delete(message.id);
+    let request = manager.delete(message.id);
     request.onsuccess = deleteAll.bind(null, messages);
     request.onerror = function (event) {
       ok(false, "failed to delete all messages");
       tasks.finish();
     }
   });
 }
 
@@ -120,17 +121,17 @@ tasks.push(deleteAllMessages);
 
 tasks.push(getAllThreads.bind(null, function (threads) {
   is(threads.length, 0, "Threads are cleared");
   tasks.next();
 }));
 
 let gotMessagesCount = 0;
 tasks.push(function () {
-  mozSms.onreceived = function () {
+  manager.onreceived = function () {
     ++gotMessagesCount;
   };
   tasks.next();
 });
 
 tasks.push(function () {
   for (let i = 1; i <= MSGS; i++) {
     sendSmsToEmulator(FROM, PREFIX + i);
@@ -164,17 +165,17 @@ tasks.push(getAllThreads.bind(null, func
               lastMessage.body,
               allMessages.length,
               lastMessage.timestamp);
 
   tasks.next();
 }));
 
 tasks.push(function DeleteFirstMessage() {
-  let request = mozSms.delete(allMessages[0].id);
+  let request = manager.delete(allMessages[0].id);
   request.onsuccess = function () {
     getAllThreads(function (threads) {
       is(threads.length, 1, "Should have only one thread");
 
       allMessages = allMessages.slice(1);
       let lastMessage = allMessages[allMessages.length - 1];
 
       checkThread(threads[0],
@@ -184,17 +185,17 @@ tasks.push(function DeleteFirstMessage()
                   lastMessage.timestamp);
 
       tasks.next();
     });
   };
 });
 
 tasks.push(function DeleteLastMessage() {
-  let request = mozSms.delete(allMessages[allMessages.length - 1].id);
+  let request = manager.delete(allMessages[allMessages.length - 1].id);
   request.onsuccess = function () {
     getAllThreads(function (threads) {
       is(threads.length, 1, "Should have only one thread");
 
       allMessages = allMessages.slice(0, -1);
       let lastMessage = allMessages[allMessages.length - 1];
 
       checkThread(threads[0],
@@ -217,16 +218,16 @@ tasks.push(getAllThreads.bind(null, func
 
 // WARNING: All tasks should be pushed before this!!!
 tasks.push(function cleanUp() {
   if (pendingEmulatorCmdCount) {
     window.setTimeout(cleanUp, 100);
     return;
   }
 
-  mozSms.onreceived = null;
+  manager.onreceived = null;
 
   SpecialPowers.removePermission("sms", document);
   SpecialPowers.clearUserPref("dom.sms.enabled");
   finish();
 });
 
 tasks.run();
--- a/dom/mobilemessage/tests/test_sms_basics.html
+++ b/dom/mobilemessage/tests/test_sms_basics.html
@@ -11,42 +11,42 @@
 <iframe></iframe>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for WebSMS **/
 
 function checkSmsDisabled() {
-  ok(!('mozSms' in frames[0].navigator), "navigator.mozSms should not exist");
-  ok(frames[0].navigator.mozSms === undefined,
-     "navigator.mozSms should return undefined");
+  ok(!('mozMobileMessage' in frames[0].navigator), "navigator.mozMobileMessage should not exist");
+  ok(frames[0].navigator.mozMobileMessage === undefined,
+     "navigator.mozMobileMessage should return undefined");
 }
 
 function checkSmsEnabled() {
   // Bug 784617: WebSms is disabled on all platforms except Android for the moment.
   if (navigator.appVersion.indexOf("Android") == -1) {
     checkSmsDisabled();
     return;
   }
 
-  ok('mozSms' in frames[0].navigator, "navigator.mozSms should exist");
-  ok(frames[0].navigator.mozSms, "navigator.mozSms returns an object");
-  ok(frames[0].navigator.mozSms instanceof MozSmsManager, "navigator.mozSms is an SmsManager object");
+  ok('mozMobileMessage' in frames[0].navigator, "navigator.mozMobileMessage should exist");
+  ok(frames[0].navigator.mozMobileMessage, "navigator.mozMobileMessage returns an object");
+  ok(frames[0].navigator.mozMobileMessage instanceof MozMobileMessageManager,
+     "navigator.mozMobileMessage is an MobileMessageManager object");
 }
 
 function checkInterface(aInterface) {
   ok(!(aInterface in window), aInterface + " should be prefixed");
   ok(("Moz" + aInterface) in window, aInterface + " should be prefixed");
 }
 
 function test() {
   var gSmsEnabled = SpecialPowers.getBoolPref("dom.sms.enabled");
 
-  checkInterface("SmsManager");
   checkInterface("SmsMessage");
   checkInterface("SmsEvent");
   checkInterface("SmsFilter");
 
   // If sms is disabled and permission is removed, sms is disabled.
   SpecialPowers.setBoolPref("dom.sms.enabled", false);
   SpecialPowers.removePermission("sms", document);
   checkSmsDisabled();
--- a/dom/permission/tests/test_sms.html
+++ b/dom/permission/tests/test_sms.html
@@ -15,18 +15,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="content" style="display: none"></div>
 <pre id="test">
 <script type="application/javascript;version=1.8" src="file_framework.js"></script>
 <script type="application/javascript;version=1.8">
 var gData = [
   {
     perm: ["sms"],
     needParentPerm: true,
-    obj: "mozSms",
-    idl: "nsIDOMMozSmsManager",
+    obj: "mozMobileMessage",
+    idl: "nsIDOMMozMobileMessageManager",
     settings: [["dom.sms.enabled", true]],
   },
 ]
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -782,18 +782,17 @@ nsJSObjWrapper::NP_SetProperty(NPObject 
   pusher.Push(cx);
   AutoJSExceptionReporter reporter(cx);
   JSAutoCompartment ac(cx, npjsobj->mJSObj);
 
   JS::Rooted<JS::Value> v(cx, NPVariantToJSVal(npp, cx, value));
 
   NS_ASSERTION(NPIdentifierIsInt(id) || NPIdentifierIsString(id),
                "id must be either string or int!\n");
-  ok = ::JS_SetPropertyById(cx, npjsobj->mJSObj, NPIdentifierToJSId(id),
-                            &v);
+  ok = ::JS_SetPropertyById(cx, npjsobj->mJSObj, NPIdentifierToJSId(id), v);
 
   // return ok == JS_TRUE to quiet down compiler warning, even if
   // return ok is what we really want.
   return ok == JS_TRUE;
 }
 
 // static
 bool
--- a/dom/plugins/test/reftest/reftest.list
+++ b/dom/plugins/test/reftest/reftest.list
@@ -22,9 +22,9 @@ random-if(/^Windows\x20NT\x206\.1/.test(
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background-1-step.html plugin-background-ref.html
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background-2-step.html plugin-background-ref.html
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background-5-step.html plugin-background-ref.html
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background-10-step.html plugin-background-ref.html
 random-if(!haveTestPlugin) == plugin-transform-1.html plugin-transform-1-ref.html
 fails-if(!haveTestPlugin) == plugin-transform-2.html plugin-transform-2-ref.html
 skip-if(!haveTestPlugin) == shrink-1.html shrink-1-ref.html
 skip-if(!haveTestPlugin) == update-1.html update-1-ref.html
-fails-if(!haveTestPlugin) == windowless-layers.html windowless-layers-ref.html
+skip-if(!haveTestPlugin) == windowless-layers.html windowless-layers-ref.html
--- a/dom/src/events/Makefile.in
+++ b/dom/src/events/Makefile.in
@@ -12,9 +12,10 @@ FAIL_ON_WARNINGS := 1
 include $(DEPTH)/config/autoconf.mk
 
 MSVC_ENABLE_PGO := 1
 LIBXUL_LIBRARY	= 1
 
 include $(topsrcdir)/config/rules.mk
 
 INCLUDES	+= -I$(topsrcdir)/dom/base
+INCLUDES	+= -I$(topsrcdir)/content/base/src
 
--- a/dom/system/OSFileConstants.cpp
+++ b/dom/system/OSFileConstants.cpp
@@ -629,17 +629,17 @@ bool SetStringProperty(JSContext *cx, JS
                        const nsString aValue)
 {
   if (aValue.IsVoid()) {
     return true;
   }
   JSString* strValue = JS_NewUCStringCopyZ(cx, aValue.get());
   NS_ENSURE_TRUE(strValue, false);
   JS::Rooted<JS::Value> valValue(cx, STRING_TO_JSVAL(strValue));
-  return JS_SetProperty(cx, aObject, aProperty, &valValue);
+  return JS_SetProperty(cx, aObject, aProperty, valValue);
 }
 
 /**
  * Define OS-specific constants.
  *
  * This function creates or uses JS object |OS.Constants| to store
  * all its constants.
  */
@@ -702,24 +702,24 @@ bool DefineOSFileConstants(JSContext *cx
     MOZ_ASSERT(NS_SUCCEEDED(rv));
 
     JSString* strVersion = JS_NewStringCopyZ(cx, os.get());
     if (!strVersion) {
       return false;
     }
 
     JS::Rooted<JS::Value> valVersion(cx, STRING_TO_JSVAL(strVersion));
-    if (!JS_SetProperty(cx, objSys, "Name", &valVersion)) {
+    if (!JS_SetProperty(cx, objSys, "Name", valVersion)) {
       return false;
     }
   }
 
 #if defined(DEBUG)
   JS::Rooted<JS::Value> valDebug(cx, JSVAL_TRUE);
-  if (!JS_SetProperty(cx, objSys, "DEBUG", &valDebug)) {
+  if (!JS_SetProperty(cx, objSys, "DEBUG", valDebug)) {
     return false;
   }
 #endif
 
   // Build OS.Constants.Path
 
   JS::Rooted<JSObject*> objPath(cx);
   if (!(objPath = GetOrCreateObjectProperty(cx, objConstants, "Path"))) {
--- a/dom/tests/mochitest/bugs/Makefile.in
+++ b/dom/tests/mochitest/bugs/Makefile.in
@@ -141,11 +141,12 @@ MOCHITEST_FILES	= \
 		test_bug817476.html \
 		test_bug823173.html \
 		test_bug850517.html \
 		test_bug848088.html \
 		test_resize_move_windows.html \
 		test_bug862540.html \
 		test_bug857555.html \
 		test_bug876098.html \
+		test_toJSON.html \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/test_toJSON.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=760851
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 760851</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug 760851 **/
+  SimpleTest.waitForExplicitFinish();
+
+  // We need to skip all the interface constants.
+  var keysToSkip = ["TYPE_NAVIGATE", "TYPE_RELOAD", "TYPE_RESERVED",
+                    "TYPE_BACK_FORWARD"];
+
+  // Testing window.performance is sufficient, because checkAttributesMatch is
+  // recursive, so window.performance.navigation and window.performance.timing
+  // get tested as well.
+  var toTest = [window.performance];
+
+  function checkAttributesMatch(obj, jsonObj) {
+    if (typeof(obj) !== "object") {
+      throw "Expected obj to be of type \"object\". Test failed.";
+    }
+    if (typeof(jsonObj) !== "object") {
+      is(false, "Expected object " + jsonObj + " to be of type object, but gotten otherwise");
+    }
+    for (key in obj) {
+      if (typeof(obj[key]) === "function" || keysToSkip.indexOf(key) > -1)
+        continue;
+      if (typeof(obj[key]) === "object") {
+        checkAttributesMatch(obj[key], jsonObj[key]);
+        continue;
+      }
+      is(jsonObj[key], obj[key], "values for " + obj + " key " + key + " should match");
+    }
+  }
+
+  function runTest() {
+    toTest.forEach(function(testObj) {
+      var jsonCopy = JSON.parse(JSON.stringify(testObj));
+      checkAttributesMatch(testObj, jsonCopy);
+    });
+    SimpleTest.finish();
+  }
+
+  </script>
+</head>
+<body onload="runTest();">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=760851">Mozilla Bug 760851</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <p></p>
+  <p></p>
+  <p></p>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -265,17 +265,16 @@ var interfaceNamesInGlobalScope =
     "MozNamedAttrMap",
     "MozNetworkStats",
     "MozNetworkStatsData",
     "MozNetworkStatsManager",
     "MozPowerManager",
     "MozSettingsEvent",
     "MozSmsEvent",
     "MozSmsFilter",
-    "MozSmsManager",
     "MozSmsMessage",
     "MozSmsSegmentInfo",
     "MozTimeManager",
     "MozTouchEvent",
     "MozWakeLock",
     "MozWakeLockListener",
     "MutationEvent",
     "MutationObserver",
--- a/dom/tests/mochitest/geolocation/Makefile.in
+++ b/dom/tests/mochitest/geolocation/Makefile.in
@@ -13,16 +13,17 @@ include $(DEPTH)/config/autoconf.mk
 MOCHITEST_FILES	= \
 		test_allowCurrent.html \
 		test_allowWatch.html \
 		test_cachedPosition.html \
 		test_cancelCurrent.html \
 		test_cancelWatch.html \
 		test_clearWatch.html \
 		test_clearWatch_invalid.html \
+		test_geolocation_is_undefined_when_pref_is_off.html \
 		test_manyCurrentConcurrent.html \
 		test_manyCurrentSerial.html \
 		test_manyWatchConcurrent.html \
 		test_manyWatchSerial.html \
 		test_manyWindows.html \
 		test_optional_api_params.html \
 		test_shutdown.html \
 		test_windowClose.html \
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/geolocation/test_geolocation_is_undefined_when_pref_is_off.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=884921
+-->
+<head>
+  <title>Test for getCurrentPosition </title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="geolocation_common.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=884921">Mozilla Bug 884921</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+SpecialPowers.pushPrefEnv({set: [["geo.enabled", false]]}, function() {
+  is(navigator.geolocation, undefined);
+  is("geolocation" in navigator, false);
+  SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
+
--- a/dom/webidl/CanvasRenderingContext2D.webidl
+++ b/dom/webidl/CanvasRenderingContext2D.webidl
@@ -41,20 +41,18 @@ interface CanvasRenderingContext2D {
 // NOT IMPLEMENTED  void resetTransform();
 
   // compositing
            attribute unrestricted double globalAlpha; // (default 1.0)
            [Throws]
            attribute DOMString globalCompositeOperation; // (default source-over)
 
   // colors and styles (see also the CanvasDrawingStyles interface)
-           [GetterThrows]
-           attribute any strokeStyle; // (default black)
-           [GetterThrows]
-           attribute any fillStyle; // (default black)
+           attribute (DOMString or CanvasGradient or CanvasPattern) strokeStyle; // (default black)
+           attribute (DOMString or CanvasGradient or CanvasPattern) fillStyle; // (default black)
   [Creator]
   CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1);
   [Creator, Throws]
   CanvasGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1);
   [Creator, Throws]
   CanvasPattern createPattern((HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) image, [TreatNullAs=EmptyString] DOMString repetition);
 
   // shadows
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -89,22 +89,18 @@ partial interface Navigator {
 // http://www.w3.org/TR/tracking-dnt/ sort of
 partial interface Navigator {
   readonly attribute DOMString doNotTrack;
 };
 
 // http://www.w3.org/TR/geolocation-API/#geolocation_interface
 [NoInterfaceObject]
 interface NavigatorGeolocation {
-  // XXXbz This should perhaps be controleld by the "geo.enabled" pref, instead
-  // of checking it in the C++.  Let's not for now to reduce risk.
-  // Also, we violate the spec as a result, since we can return null.  See bug
-  // 884921.
-  [Throws]
-  readonly attribute Geolocation? geolocation;
+  [Throws, Pref="geo.enabled"]
+  readonly attribute Geolocation geolocation;
 };
 Navigator implements NavigatorGeolocation;
 
 // http://www.w3.org/TR/battery-status/#navigatorbattery-interface
 [NoInterfaceObject]
 interface NavigatorBattery {
     // XXXbz Per spec this should be non-nullable, but we return null in
     // torn-down windows.  See bug 884925.
@@ -220,23 +216,16 @@ partial interface Navigator {
 };
 
 // nsIDOMClientInformation
 partial interface Navigator {
   [Throws]
   boolean mozIsLocallyAvailable(DOMString uri, boolean whenOffline);
 };
 
-// nsIDOMMozNavigatorSms
-interface MozSmsManager;
-partial interface Navigator {
-  [Func="Navigator::HasSmsSupport"]
-  readonly attribute MozSmsManager? mozSms;
-};
-
 // nsIDOMMozNavigatorMobileMessage
 interface MozMobileMessageManager;
 partial interface Navigator {
   [Func="Navigator::HasMobileMessageSupport"]
   readonly attribute MozMobileMessageManager? mozMobileMessage;
 };
 
 // nsIDOMMozNavigatorNetwork
--- a/dom/webidl/Performance.webidl
+++ b/dom/webidl/Performance.webidl
@@ -14,9 +14,11 @@ typedef double DOMHighResTimeStamp;
 
 interface Performance {
   DOMHighResTimeStamp now();
 
   [Constant]
   readonly attribute PerformanceTiming timing;
   [Constant]
   readonly attribute PerformanceNavigation navigation;
+
+  jsonifier;
 };
--- a/dom/webidl/PerformanceNavigation.webidl
+++ b/dom/webidl/PerformanceNavigation.webidl
@@ -13,9 +13,11 @@
 interface PerformanceNavigation {
   const unsigned short TYPE_NAVIGATE = 0;
   const unsigned short TYPE_RELOAD = 1;
   const unsigned short TYPE_BACK_FORWARD = 2;
   const unsigned short TYPE_RESERVED = 255;
 
   readonly attribute unsigned short type;
   readonly attribute unsigned short redirectCount;
+
+  jsonifier;
 };
--- a/dom/webidl/PerformanceTiming.webidl
+++ b/dom/webidl/PerformanceTiming.webidl
@@ -28,9 +28,11 @@ interface PerformanceTiming {
   readonly attribute unsigned long long responseEnd;
   readonly attribute unsigned long long domLoading;
   readonly attribute unsigned long long domInteractive;
   readonly attribute unsigned long long domContentLoadedEventStart;
   readonly attribute unsigned long long domContentLoadedEventEnd;
   readonly attribute unsigned long long domComplete;
   readonly attribute unsigned long long loadEventStart;
   readonly attribute unsigned long long loadEventEnd;
+
+  jsonifier;
 };
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -671,16 +671,21 @@ RasterImage::GetDrawableImgFrame(uint32_
   if (!frame) {
     frame = GetImgFrame(framenum);
   }
 
   // We will return a paletted frame if it's not marked as compositing failed
   // so we can catch crashes for reasons we haven't investigated.
   if (frame && frame->GetCompositingFailed())
     return nullptr;
+
+  if (frame) {
+    frame->ApplyDirtToSurfaces();
+  }
+
   return frame;
 }
 
 uint32_t
 RasterImage::GetCurrentImgFrameIndex() const
 {
   if (mAnim)
     return mAnim->GetCurrentAnimationFrameIndex();
@@ -2315,49 +2320,49 @@ RasterImage::RequestDecodeCore(RequestDe
 
   return NS_OK;
 }
 
 // Synchronously decodes as much data as possible
 nsresult
 RasterImage::SyncDecode()
 {
-  MutexAutoLock imgLock(mDecodingMutex);
-
-  if (mDecodeRequest) {
-    // If the image is waiting for decode work to be notified, go ahead and do that.
-    if (mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE) {
-      nsresult rv = FinishedSomeDecoding();
-      CONTAINER_ENSURE_SUCCESS(rv);
-    }
-  }
-
-  nsresult rv;
-
   PROFILER_LABEL_PRINTF("RasterImage", "SyncDecode", "%s", GetURIString().get());;
 
-  // We really have no good way of forcing a synchronous decode if we're being
-  // called in a re-entrant manner (ie, from an event listener fired by a
-  // decoder), because the decoding machinery is already tied up. We thus explicitly
-  // disallow this type of call in the API, and check for it in API methods.
-  NS_ABORT_IF_FALSE(!mInDecoder, "Yikes, forcing sync in reentrant call!");
-
   // If we have a size decoder open, make sure we get the size
   if (mDecoder && mDecoder->IsSizeDecode()) {
     nsresult rv = DecodePool::Singleton()->DecodeUntilSizeAvailable(this);
     CONTAINER_ENSURE_SUCCESS(rv);
 
     // If we didn't get the size out of the image, we won't until we get more
     // data, so signal that we want a full decode and give up for now.
     if (!mHasSize) {
       mWantFullDecode = true;
       return NS_ERROR_NOT_AVAILABLE;
     }
   }
 
+  MutexAutoLock imgLock(mDecodingMutex);
+
+  // We really have no good way of forcing a synchronous decode if we're being
+  // called in a re-entrant manner (ie, from an event listener fired by a
+  // decoder), because the decoding machinery is already tied up. We thus explicitly
+  // disallow this type of call in the API, and check for it in API methods.
+  NS_ABORT_IF_FALSE(!mInDecoder, "Yikes, forcing sync in reentrant call!");
+
+  if (mDecodeRequest) {
+    // If the image is waiting for decode work to be notified, go ahead and do that.
+    if (mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE) {
+      nsresult rv = FinishedSomeDecoding();
+      CONTAINER_ENSURE_SUCCESS(rv);
+    }
+  }
+
+  nsresult rv;
+
   // If we're decoded already, or decoding until the size was available
   // finished us as a side-effect, no worries
   if (mDecoded)
     return NS_OK;
 
   // If we don't have any bytes to flush to the decoder, we can't do anything.
   // mBytesDecoded can be bigger than mSourceData.Length() if we're not storing
   // the source data.
@@ -2465,24 +2470,26 @@ void
 RasterImage::ScalingDone(ScaleRequest* request, ScaleStatus status)
 {
   MOZ_ASSERT(status == SCALE_DONE || status == SCALE_INVALID);
   MOZ_ASSERT(request);
 
   if (status == SCALE_DONE) {
     MOZ_ASSERT(request->done);
 
+    imgFrame *scaledFrame = request->dstFrame.forget();
+    scaledFrame->ImageUpdated(scaledFrame->GetRect());
+    scaledFrame->ApplyDirtToSurfaces();
+
     if (mStatusTracker) {
-      imgFrame *scaledFrame = request->dstFrame.get();
-      scaledFrame->ImageUpdated(scaledFrame->GetRect());
       mStatusTracker->FrameChanged(&request->srcRect);
     }
 
     mScaleResult.status = SCALE_DONE;
-    mScaleResult.frame = request->dstFrame;
+    mScaleResult.frame = scaledFrame;
     mScaleResult.scale = request->scale;
   } else {
     mScaleResult.status = SCALE_INVALID;
     mScaleResult.frame = nullptr;
   }
 
   // If we were waiting for this scale to come through, forget the scale
   // request. Otherwise, we still have a scale outstanding that it's possible
@@ -2549,18 +2556,16 @@ RasterImage::DrawWithPreDownscaleIfNeede
     }
   }
 
   nsIntMargin padding(framerect.y,
                       mSize.width - framerect.XMost(),
                       mSize.height - framerect.YMost(),
                       framerect.x);
 
-  frame->ApplyDirtToSurfaces();
-
   frame->Draw(aContext, aFilter, userSpaceToImageSpace, aFill, padding, subimage,
               aFlags);
 }
 
 //******************************************************************************
 /* [noscript] void draw(in gfxContext aContext,
  *                      in gfxGraphicsFilter aFilter,
  *                      [const] in gfxMatrix aUserSpaceToImageSpace,
--- a/image/src/RasterImage.h
+++ b/image/src/RasterImage.h
@@ -637,19 +637,19 @@ private: // data
   mozilla::Mutex             mDecodingMutex;
 
   FallibleTArray<char>       mSourceData;
 
   // Decoder and friends
   nsRefPtr<Decoder>          mDecoder;
   nsRefPtr<DecodeRequest>    mDecodeRequest;
   uint32_t                   mBytesDecoded;
-  // END LOCKED MEMBER VARIABLES
 
   bool                       mInDecoder;
+  // END LOCKED MEMBER VARIABLES
 
   // Boolean flags (clustered together to conserve space):
   bool                       mHasSize:1;       // Has SetSize() been called?
   bool                       mDecodeOnDraw:1;  // Decoding on draw?
   bool                       mMultipart:1;     // Multipart?
   bool                       mDiscardable:1;   // Is container discardable?
   bool                       mHasSourceData:1; // Do we have source data?
 
--- a/js/ipc/JavaScriptChild.cpp
+++ b/js/ipc/JavaScriptChild.cpp
@@ -409,17 +409,17 @@ JavaScriptChild::AnswerSet(const ObjectI
         return fail(cx, rs);
 
     MOZ_ASSERT(obj == receiver);
 
     RootedValue val(cx);
     if (!toValue(cx, value, &val))
         return fail(cx, rs);
 
-    if (!JS_SetPropertyById(cx, obj, internedId, &val))
+    if (!JS_SetPropertyById(cx, obj, internedId, val))
         return fail(cx, rs);
 
     if (!toVariant(cx, val, result))
         return fail(cx, rs);
 
     return ok(rs);
 }
 
--- a/js/ipc/JavaScriptParent.cpp
+++ b/js/ipc/JavaScriptParent.cpp
@@ -431,17 +431,17 @@ JavaScriptParent::call(JSContext *cx, Ha
             continue;
 
         // Take the value the child process returned, and set it on the XPC
         // object.
         if (!toValue(cx, outparams[i], &v))
             return false;
 
         JSObject *obj = &outobjects[i].toObject();
-        if (!JS_SetProperty(cx, obj, "value", &v))
+        if (!JS_SetProperty(cx, obj, "value", v))
             return false;
     }
 
     if (!toValue(cx, result, args.rval()))
         return false;
 
     return true;
 }
--- a/js/src/builtin/BinaryData.cpp
+++ b/js/src/builtin/BinaryData.cpp
@@ -1,13 +1,13 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- */
-/* 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/. */
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "builtin/BinaryData.h"
 
 #include <vector>
 
 #include "mozilla/FloatingPoint.h"
 
 #include "jscompartment.h"
@@ -38,22 +38,25 @@ static bool Reify(JSContext *cx, HandleO
 
 /*
  * ConvertAndCopyTo() converts `from` to type `type` and stores the result in
  * `mem`, which MUST be pre-allocated to the appropriate size for instances of
  * `type`.
  */
 static bool ConvertAndCopyTo(JSContext *cx, HandleObject type,
                              HandleValue from, uint8_t *mem);
-JSBool TypeThrowError(JSContext *cx, unsigned argc, Value *vp)
+
+static JSBool
+TypeThrowError(JSContext *cx, unsigned argc, Value *vp)
 {
     return ReportIsNotFunction(cx, *vp);
 }
 
-JSBool DataThrowError(JSContext *cx, unsigned argc, Value *vp)
+static JSBool
+DataThrowError(JSContext *cx, unsigned argc, Value *vp)
 {
     return ReportIsNotFunction(cx, *vp);
 }
 
 static void
 ReportTypeError(JSContext *cx, Value fromValue, const char *toType)
 {
     char *valueStr = JS_EncodeString(cx, JS_ValueToString(cx, fromValue));
@@ -178,16 +181,44 @@ GetAlign(JSContext *cx, HandleObject typ
 
 struct FieldInfo
 {
     jsid name;
     JSObject *type;
     size_t offset;
 };
 
+Class js::DataClass = {
+    "Data",
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Data),
+    JS_PropertyStub,
+    JS_DeletePropertyStub,
+    JS_PropertyStub,
+    JS_StrictPropertyStub,
+    JS_EnumerateStub,
+    JS_ResolveStub,
+    JS_ConvertStub
+};
+
+Class js::TypeClass = {
+    "Type",
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Type),
+    JS_PropertyStub,
+    JS_DeletePropertyStub,
+    JS_PropertyStub,
+    JS_StrictPropertyStub,
+    JS_EnumerateStub,
+    JS_ResolveStub,
+    JS_ConvertStub
+};
+
+Class js::NumericTypeClasses[NUMERICTYPES] = {
+    BINARYDATA_FOR_EACH_NUMERIC_TYPES(BINARYDATA_NUMERIC_CLASSES)
+};
+
 typedef std::vector<FieldInfo> FieldList;
 
 static
 bool
 LookupFieldList(FieldList *list, jsid fieldName, FieldInfo *out)
 {
     for (FieldList::const_iterator it = list->begin(); it != list->end(); ++it) {
         if ((*it).name == fieldName) {
@@ -782,17 +813,17 @@ ArrayType::repeat(JSContext *cx, unsigne
                              NULL, JSMSG_MORE_ARGS_NEEDED,
                              "repeat()", "0", "s");
         return false;
     }
 
     RootedObject thisObj(cx, args.thisv().toObjectOrNull());
     if (!IsArrayType(thisObj)) {
         JSString *valueStr = JS_ValueToString(cx, args.thisv());
-        char *valueChars = "(unknown type)";
+        char *valueChars = const_cast<char*>("(unknown type)");
         if (valueStr)
             valueChars = JS_EncodeString(cx, valueStr);
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, "ArrayType", "repeat", valueChars);
         if (valueStr)
             JS_free(cx, valueChars);
         return false;
     }
 
@@ -1310,17 +1341,17 @@ BinaryArray::obj_getGenericAttributes(JS
         return true;
     }
 
     if (JSID_IS_ATOM(id, cx->names().length)) {
         *attrsp = JSPROP_READONLY | JSPROP_PERMANENT;
         return true;
     }
 
-	return false;
+    return false;
 }
 
 JSBool
 BinaryArray::obj_getPropertyAttributes(JSContext *cx, HandleObject obj,
                                         HandlePropertyName name,
                                         unsigned *attrsp)
 {
     RootedId id(cx, NameToId(name));
@@ -1419,46 +1450,46 @@ Class BinaryStruct::class_ = {
     BinaryStruct::finalize,
     NULL,           /* checkAccess */
     NULL,           /* call        */
     NULL,           /* construct   */
     NULL,           /* hasInstance */
     BinaryStruct::obj_trace,
     JS_NULL_CLASS_EXT,
     {
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
+        NULL, /* lookupGeneric */
+        NULL, /* lookupProperty */
+        NULL, /* lookupElement */
+        NULL, /* lookupSpecial */
+        NULL, /* defineGeneric */
+        NULL, /* defineProperty */
+        NULL, /* defineElement */
+        NULL, /* defineSpecial */
         BinaryStruct::obj_getGeneric,
         BinaryStruct::obj_getProperty,
-        NULL,
-        NULL,
+        NULL, /* getElement */
+        NULL, /* getElementIfPresent */
         BinaryStruct::obj_getSpecial,
         BinaryStruct::obj_setGeneric,
         BinaryStruct::obj_setProperty,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
+        NULL, /* setElement */
+        NULL, /* setSpecial */
+        NULL, /* getGenericAttributes */
+        NULL, /* getPropertyAttributes */
+        NULL, /* getElementAttributes */
+        NULL, /* getSpecialAttributes */
+        NULL, /* setGenericAttributes */
+        NULL, /* setPropertyAttributes */
+        NULL, /* setElementAttributes */
+        NULL, /* setSpecialAttributes */
+        NULL, /* deleteProperty */
+        NULL, /* deleteElement */
+        NULL, /* deleteSpecial */
+        BinaryStruct::obj_enumerate,
+        NULL, /* thisObject */
     }
 };
 
 /*
  * NOTE: layout() does not check for duplicates in fields since the arguments
  * to StructType are currently passed as an object literal. Fix this if it
  * changes to taking an array of arrays.
  */
@@ -1782,16 +1813,55 @@ BinaryStruct::obj_trace(JSTracer *tracer
         MarkObject(tracer, &owner, "binarystruct.blockRefOwner");
     }
 
     HeapPtrObject type(obj->getFixedSlot(SLOT_DATATYPE).toObjectOrNull());
     MarkObject(tracer, &type, "binarystruct.type");
 }
 
 JSBool
+BinaryStruct::obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
+                            MutableHandleValue statep, MutableHandleId idp)
+{
+    JS_ASSERT(IsBinaryStruct(obj));
+
+    RootedObject type(cx, GetType(obj));
+
+    FieldList *fieldList = static_cast<FieldList *>(type->getPrivate());
+    JS_ASSERT(fieldList);
+
+    uint32_t index;
+    switch (enum_op) {
+        case JSENUMERATE_INIT_ALL:
+        case JSENUMERATE_INIT:
+            statep.setInt32(0);
+            idp.set(INT_TO_JSID(fieldList->size()));
+            break;
+
+        case JSENUMERATE_NEXT:
+            index = static_cast<uint32_t>(statep.toInt32());
+
+            if (index < fieldList->size()) {
+                idp.set(fieldList->at(index).name);
+                statep.setInt32(index + 1);
+            } else {
+                statep.setNull();
+            }
+
+            break;
+
+        case JSENUMERATE_DESTROY:
+            statep.setNull();
+            break;
+    }
+
+    return true;
+}
+
+JSBool
 BinaryStruct::obj_getGeneric(JSContext *cx, HandleObject obj,