Merge last PGO-green changeset of mozilla-inbound to mozilla-central
authorEd Morley <emorley@mozilla.com>
Wed, 31 Oct 2012 14:06:39 +0000
changeset 112017 3393586a210b
parent 111919 de98ab14e746 (current diff)
parent 112016 de25c9c57c53 (diff)
child 112018 6c4dcc6a6cfc
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
milestone19.0a1
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_sslsite_transition.js
dom/indexedDB/test/test_webapp_clearBrowserData.html
dom/interfaces/css/nsIDOMCSS2Properties.idl
js/src/jit-test/tests/gc/bug-787703.js
js/src/jsapi-tests/testUTF8.cpp
mfbt/double-conversion/more-architectures.patch
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -354,37 +354,32 @@ nsAccDocManager::CreateDocOrRootAccessib
       aDocument->IsResourceDoc() || !aDocument->IsActive())
     return nullptr;
 
   // Ignore documents without presshell and not having root frame.
   nsIPresShell* presShell = aDocument->GetShell();
   if (!presShell || !presShell->GetRootFrame() || presShell->IsDestroying())
     return nullptr;
 
-  // Do not create document accessible until role content is loaded, otherwise
-  // we get accessible document with wrong role.
-  nsIContent *rootElm = nsCoreUtils::GetRoleContent(aDocument);
-  if (!rootElm)
-    return nullptr;
-
   bool isRootDoc = nsCoreUtils::IsRootDocument(aDocument);
 
   DocAccessible* parentDocAcc = nullptr;
   if (!isRootDoc) {
     // XXXaaronl: ideally we would traverse the presshell chain. Since there's
     // no easy way to do that, we cheat and use the document hierarchy.
     parentDocAcc = GetDocAccessible(aDocument->GetParentDocument());
     NS_ASSERTION(parentDocAcc,
                  "Can't create an accessible for the document!");
     if (!parentDocAcc)
       return nullptr;
   }
 
   // We only create root accessibles for the true root, otherwise create a
   // doc accessible.
+  nsIContent *rootElm = nsCoreUtils::GetRoleContent(aDocument);
   nsRefPtr<DocAccessible> docAcc = isRootDoc ?
     new RootAccessibleWrap(aDocument, rootElm, presShell) :
     new DocAccessibleWrap(aDocument, rootElm, presShell);
 
   // Cache the document accessible into document cache.
   mDocAccessibleCache.Put(aDocument, docAcc);
 
   // Initialize the document accessible.
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -78,17 +78,17 @@ nsAccessNode::Shutdown()
   mContent = nullptr;
   mDoc = nullptr;
 }
 
 RootAccessible*
 nsAccessNode::RootAccessible() const
 {
   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
-    nsCoreUtils::GetDocShellTreeItemFor(mContent);
+    nsCoreUtils::GetDocShellTreeItemFor(GetNode());
   NS_ASSERTION(docShellTreeItem, "No docshell tree item for mContent");
   if (!docShellTreeItem) {
     return nullptr;
   }
   nsCOMPtr<nsIDocShellTreeItem> root;
   docShellTreeItem->GetRootTreeItem(getter_AddRefs(root));
   NS_ASSERTION(root, "No root content tree item");
   if (!root) {
@@ -116,13 +116,13 @@ nsAccessNode::Language(nsAString& aLangu
 {
   aLanguage.Truncate();
 
   if (!mDoc)
     return;
 
   nsCoreUtils::GetLanguageFor(mContent, nullptr, aLanguage);
   if (aLanguage.IsEmpty()) { // Nothing found, so use document's language
-    mContent->OwnerDoc()->GetHeaderData(nsGkAtoms::headerContentLanguage,
+    mDoc->DocumentNode()->GetHeaderData(nsGkAtoms::headerContentLanguage,
                                         aLanguage);
   }
 }
 
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -245,17 +245,16 @@ nsAccessibilityService::ContentRangeInse
   if (logging::IsEnabled(logging::eTree)) {
     logging::MsgBegin("TREE", "content inserted");
     logging::Node("container", aContainer);
     for (nsIContent* child = aStartChild; child != aEndChild;
          child = child->GetNextSibling()) {
       logging::Node("content", child);
     }
     logging::MsgEnd();
-    logging::Stack();
   }
 #endif
 
   DocAccessible* docAccessible = GetDocAccessible(aPresShell);
   if (docAccessible)
     docAccessible->ContentInserted(aContainer, aStartChild, aEndChild);
 }
 
@@ -265,17 +264,16 @@ nsAccessibilityService::ContentRemoved(n
                                        nsIContent* aChild)
 {
 #ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eTree)) {
     logging::MsgBegin("TREE", "content removed");
     logging::Node("container", aContainer);
     logging::Node("content", aChild);
     logging::MsgEnd();
-    logging::Stack();
   }
 #endif
 
   DocAccessible* docAccessible = GetDocAccessible(aPresShell);
   if (docAccessible)
     docAccessible->ContentRemoved(aContainer, aChild);
 }
 
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -1373,16 +1373,18 @@ Accessible::NativeAttributes()
 
   return attributes.forget();
 }
 
 GroupPos
 Accessible::GroupPosition()
 {
   GroupPos groupPos;
+  if (!HasOwnContent())
+    return groupPos;
 
   // Get group position from ARIA attributes.
   nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_level, &groupPos.level);
   nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_setsize, &groupPos.setSize);
   nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_posinset, &groupPos.posInSet);
 
   // If ARIA is missed and the accessible is visible then calculate group
   // position from hierarchy.
@@ -1896,16 +1898,19 @@ Accessible::GetRelationByType(uint32_t a
   Relation rel = RelationByType(aType);
   NS_ADDREF(*aRelation = new nsAccessibleRelation(aType, &rel));
   return *aRelation ? NS_OK : NS_ERROR_FAILURE;
 }
 
 Relation
 Accessible::RelationByType(uint32_t aType)
 {
+  if (!HasOwnContent())
+    return Relation();
+
   // Relationships are defined on the same content node that the role would be
   // defined on.
   switch (aType) {
     case nsIAccessibleRelation::RELATION_LABEL_FOR: {
       Relation rel(new RelatedAccIterator(Document(), mContent,
                                           nsGkAtoms::aria_labelledby));
       if (mContent->Tag() == nsGkAtoms::label)
         rel.AppendIter(new IDRefsIterator(mDoc, mContent, mContent->IsHTML() ?
@@ -2873,28 +2878,30 @@ Accessible::IsActiveWidget() const
   }
 
   return false;
 }
 
 bool
 Accessible::AreItemsOperable() const
 {
-  return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant);
+  return HasOwnContent() &&
+    mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant);
 }
 
 Accessible*
 Accessible::CurrentItem()
 {
   // Check for aria-activedescendant, which changes which element has focus.
   // For activedescendant, the ARIA spec does not require that the user agent
   // checks whether pointed node is actually a DOM descendant of the element
   // with the aria-activedescendant attribute.
   nsAutoString id;
-  if (mContent->GetAttr(kNameSpaceID_None,
+  if (HasOwnContent() &&
+      mContent->GetAttr(kNameSpaceID_None,
                         nsGkAtoms::aria_activedescendant, id)) {
     nsIDocument* DOMDoc = mContent->OwnerDoc();
     dom::Element* activeDescendantElm = DOMDoc->GetElementById(id);
     if (activeDescendantElm) {
       DocAccessible* document = Document();
       if (document)
         return document->GetAccessible(activeDescendantElm);
     }
--- a/accessible/src/generic/BaseAccessibles.cpp
+++ b/accessible/src/generic/BaseAccessibles.cpp
@@ -259,8 +259,13 @@ DummyAccessible::NativeLinkState() const
   return 0;
 }
 
 bool
 DummyAccessible::NativelyUnavailable() const
 {
   return false;
 }
+
+void
+DummyAccessible::ApplyARIAState(uint64_t* aState) const
+{
+}
--- a/accessible/src/generic/BaseAccessibles.h
+++ b/accessible/src/generic/BaseAccessibles.h
@@ -117,14 +117,15 @@ class DummyAccessible : public Accessibl
 public:
   DummyAccessible() : AccessibleWrap(nullptr, nullptr) { }
   virtual ~DummyAccessible() { }
 
   virtual uint64_t NativeState() MOZ_OVERRIDE MOZ_FINAL;
   virtual uint64_t NativeInteractiveState() const MOZ_OVERRIDE MOZ_FINAL;
   virtual uint64_t NativeLinkState() const MOZ_OVERRIDE MOZ_FINAL;
   virtual bool NativelyUnavailable() const MOZ_OVERRIDE MOZ_FINAL;
+  virtual void ApplyARIAState(uint64_t* aState) const MOZ_OVERRIDE MOZ_FINAL;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -255,23 +255,18 @@ DocAccessible::Description(nsString& aDe
                              aDescription);
   }
 }
 
 // Accessible public method
 uint64_t
 DocAccessible::NativeState()
 {
-  // The root content of the document might be removed so that mContent is
-  // out of date.
-  uint64_t state = (mContent->GetCurrentDoc() == mDocument) ?
-    0 : states::STALE;
-
   // Document is always focusable.
-  state |= states::FOCUSABLE; // keep in sync with NativeIteractiveState() impl
+  uint64_t state = states::FOCUSABLE; // keep in sync with NativeInteractiveState() impl
   if (FocusMgr()->IsFocused(this))
     state |= states::FOCUSED;
 
   // Expose stale state until the document is ready (DOM is loaded and tree is
   // constructed).
   if (!HasLoadState(eReady))
     state |= states::STALE;
 
@@ -304,21 +299,21 @@ DocAccessible::NativelyUnavailable() con
 {
   return false;
 }
 
 // Accessible public method
 void
 DocAccessible::ApplyARIAState(uint64_t* aState) const
 {
-  // Combine with states from outer doc
-  // 
-  Accessible::ApplyARIAState(aState);
+  // Grab states from content element.
+  if (mContent)
+    Accessible::ApplyARIAState(aState);
 
-  // Allow iframe/frame etc. to have final state override via ARIA
+  // Allow iframe/frame etc. to have final state override via ARIA.
   if (mParent)
     mParent->ApplyARIAState(aState);
 }
 
 already_AddRefed<nsIPersistentProperties>
 DocAccessible::Attributes()
 {
   nsCOMPtr<nsIPersistentProperties> attributes =
@@ -535,17 +530,17 @@ DocAccessible::GetVirtualCursor(nsIAcces
 
 // HyperTextAccessible method
 already_AddRefed<nsIEditor>
 DocAccessible::GetEditor() const
 {
   // Check if document is editable (designMode="on" case). Otherwise check if
   // the html:body (for HTML document case) or document element is editable.
   if (!mDocument->HasFlag(NODE_IS_EDITABLE) &&
-      !mContent->HasFlag(NODE_IS_EDITABLE))
+      (!mContent || !mContent->HasFlag(NODE_IS_EDITABLE)))
     return nullptr;
 
   nsCOMPtr<nsISupports> container = mDocument->GetContainer();
   nsCOMPtr<nsIEditingSession> editingSession(do_GetInterface(container));
   if (!editingSession)
     return nullptr; // No editing session interface
 
   nsCOMPtr<nsIEditor> editor;
@@ -1555,17 +1550,17 @@ void
 DocAccessible::DoInitialUpdate()
 {
   mLoadState |= eTreeConstructed;
 
   // The content element may be changed before the initial update and then we
   // miss the notification (since content tree change notifications are ignored
   // prior to initial update). Make sure the content element is valid.
   nsIContent* contentElm = nsCoreUtils::GetRoleContent(mDocument);
-  if (contentElm && mContent != contentElm)
+  if (mContent != contentElm)
     mContent = contentElm;
 
   // Build initial tree.
   CacheChildrenInSubtree(this);
 
   // Fire reorder event after the document tree is constructed. Note, since
   // this reorder event is processed by parent document then events targeted to
   // this document may be fired prior to this reorder event. If this is
@@ -1820,17 +1815,17 @@ DocAccessible::ProcessContentInserted(Ac
 {
   // Process the notification if the container accessible is still in tree.
   if (!HasAccessible(aContainer->GetNode()))
     return;
 
   if (aContainer == this) {
     // If new root content has been inserted then update it.
     nsIContent* rootContent = nsCoreUtils::GetRoleContent(mDocument);
-    if (rootContent && rootContent != mContent)
+    if (rootContent != mContent)
       mContent = rootContent;
 
     // Continue to update the tree even if we don't have root content.
     // For example, elements may be inserted under the document element while
     // there is no HTML body element.
   }
 
   // XXX: Invalidate parent-child relations for container accessible and its
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -1154,16 +1154,19 @@ HyperTextAccessible::NativeAttributes()
     int32_t lineNumber = CaretLineNumber();
     if (lineNumber >= 1) {
       nsAutoString strLineNumber;
       strLineNumber.AppendInt(lineNumber);
       nsAccUtils::SetAccAttr(attributes, nsGkAtoms::lineNumber, strLineNumber);
     }
   }
 
+  if (!HasOwnContent())
+    return attributes.forget();
+
   // For the html landmark elements we expose them like we do aria landmarks to
   // make AT navigation schemes "just work". Note html:header is redundant as
   // a landmark since it usually contains headings. We're not yet sure how the
   // web will use html:footer but our best bet right now is as contentinfo.
   if (mContent->Tag() == nsGkAtoms::nav)
     nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("navigation"));
   else if (mContent->Tag() == nsGkAtoms::section) 
--- a/accessible/tests/mochitest/actions/test_media.html
+++ b/accessible/tests/mochitest/actions/test_media.html
@@ -19,16 +19,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript"
           src="../role.js"></script>
   <script type="application/javascript"
           src="../states.js"></script>
 
   <script type="application/javascript">
 
     // gA11yEventDumpID = "eventDump";
+    //gA11yEventDumpToConsole = true; // debug stuff
 
     function focusChecker(aAcc)
     {
       this.type = EVENT_FOCUS;
       this.target = aAcc;
       this.getID = function focusChecker_getID()
       {
         return "focus handling";
--- a/accessible/tests/mochitest/events/test_aria_objattr.html
+++ b/accessible/tests/mochitest/events/test_aria_objattr.html
@@ -38,18 +38,18 @@
       this.getID = function updateAttribute_getID()
       {
         return aAttr + " for " + aID + " " + aValue;
       }
     }
 
     // Debug stuff.
     // gA11yEventDumpID = "eventdump";
-    // gA11yEventDumpToConsole = true;
-    
+    //gA11yEventDumpToConsole = true;
+
     function doTests()
     {
       gQueue = new eventQueue();
 
       gQueue.push(new updateAttribute("hideable", "aria-hidden", "true"));
 
       gQueue.push(new updateAttribute("sortable", "aria-sort", "ascending"));
 
--- a/accessible/tests/mochitest/name/markup.js
+++ b/accessible/tests/mochitest/name/markup.js
@@ -9,17 +9,17 @@ var gRuleDoc = null;
 var gDumpToConsole = true;
 
 /**
  * Start name tests. Run through markup elements and test names for test
  * element (see namerules.xml for details).
  */
 function testNames()
 {
-  enableLogging("tree,stack");
+  enableLogging("tree");
 
   var request = new XMLHttpRequest();
   request.open("get", gNameRulesFileURL, false);
   request.send();
 
   gRuleDoc = request.responseXML;
 
   var markupElms = evaluateXPath(gRuleDoc, "//rules/rulesample/markup");
--- a/accessible/tests/mochitest/treeupdate/test_doc.html
+++ b/accessible/tests/mochitest/treeupdate/test_doc.html
@@ -67,21 +67,16 @@
         var text = getAccessible(getAccessible(getDocNode(aID)).firstChild);
         this.eventSeq[0].target = text;
       }
 
       this.finalCheck = function rootContentRemoved_finalCheck()
       {
         var tree = {
           role: ROLE_DOCUMENT,
-          states: {
-            // Out of date root content involves stale state presence.
-            states: 0,
-            extraStates: EXT_STATE_STALE
-          },
           children: [ ]
         };
         testAccessibleTree(getDocNode(aID), tree);
       }
     }
 
     function rootContentInserted(aID, aTextName)
     {
@@ -89,22 +84,16 @@
         new invokerChecker(EVENT_SHOW, getDocChildNode, aID),
         new invokerChecker(EVENT_REORDER, getDocNode, aID)
       ];
 
       this.finalCheck = function rootContentInserted_finalCheck()
       {
         var tree = {
           role: ROLE_DOCUMENT,
-          states: {
-            states: 0,
-            extraStates: 0,
-            absentStates: 0,
-            absentExtraStates: EXT_STATE_STALE
-          },
           children: [
             {
               role: ROLE_TEXT_LEAF,
               name: aTextName
             }
           ]
         };
         testAccessibleTree(getDocNode(aID), tree);
--- a/b2g/locales/jar.mn
+++ b/b2g/locales/jar.mn
@@ -9,8 +9,10 @@
   locale/@AB_CD@/browser/about.dtd                (%chrome/about.dtd)
   locale/@AB_CD@/browser/aboutCertError.dtd       (%chrome/aboutCertError.dtd)
   locale/@AB_CD@/browser/notification.dtd         (%chrome/notification.dtd)
   locale/@AB_CD@/browser/webapps.dtd              (%chrome/webapps.dtd)
   locale/@AB_CD@/browser/phishing.dtd             (%chrome/phishing.dtd)
 
 * locale/@AB_CD@/browser/netError.dtd             (%chrome/overrides/netError.dtd)
 % override chrome://global/locale/netError.dtd    chrome://browser/locale/netError.dtd
+* locale/@AB_CD@/browser/appstrings.properties    (%chrome/overrides/appstrings.properties)
+% override chrome://global/locale/appstrings.properties chrome://browser/locale/appstrings.properties
--- a/browser/base/content/aboutSocialError.xhtml
+++ b/browser/base/content/aboutSocialError.xhtml
@@ -59,16 +59,19 @@
         case "tryAgain":
           let urlMatch = queryString.match(/url=([^&]+)/);
           let encodedURL = urlMatch && urlMatch[1] ? urlMatch[1] : "";
           let url = decodeURIComponent(encodedURL);
 
           config.tryAgainCallback = loadQueryURL;
           config.queryURL = url;
           break;
+        case "workerFailure":
+          config.tryAgainCallback = reloadProvider;
+          break;
         default:
           break;
       }
     }
 
     function setUpStrings() {
       let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
       let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
@@ -98,15 +101,18 @@
       config.tryAgainCallback();
     }
 
     function loadQueryURL() {
       window.location.href = config.queryURL;
     }
 
     function reloadProvider() {
-      Social.provider.reload();
+      Social.enabled = false;
+      Services.tm.mainThread.dispatch(function() {
+        Social.enabled = true;
+      }, Components.interfaces.nsIThread.DISPATCH_NORMAL);
     }
 
     parseQueryString();
     setUpStrings();
   ]]></script>
 </html>
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -7,16 +7,17 @@ const PANEL_MIN_HEIGHT = 100;
 const PANEL_MIN_WIDTH = 330;
 
 let SocialUI = {
   // Called on delayed startup to initialize UI
   init: function SocialUI_init() {
     Services.obs.addObserver(this, "social:pref-changed", false);
     Services.obs.addObserver(this, "social:ambient-notification-changed", false);
     Services.obs.addObserver(this, "social:profile-changed", false);
+    Services.obs.addObserver(this, "social:frameworker-error", false);
 
     Services.prefs.addObserver("social.sidebar.open", this, false);
     Services.prefs.addObserver("social.toast-notifications.enabled", this, false);
 
     gBrowser.addEventListener("ActivateSocialFeature", this._activationEventHandler, true, true);
 
     // Called when we enter DOM full-screen mode.
     window.addEventListener("mozfullscreenchange", function () SocialSidebar.updateSidebar());
@@ -24,16 +25,17 @@ let SocialUI = {
     Social.init(this._providerReady.bind(this));
   },
 
   // Called on window unload
   uninit: function SocialUI_uninit() {
     Services.obs.removeObserver(this, "social:pref-changed");
     Services.obs.removeObserver(this, "social:ambient-notification-changed");
     Services.obs.removeObserver(this, "social:profile-changed");
+    Services.obs.removeObserver(this, "social:frameworker-error");
 
     Services.prefs.removeObserver("social.sidebar.open", this);
     Services.prefs.removeObserver("social.toast-notifications.enabled", this);
   },
 
   showProfile: function SocialUI_showProfile() {
     if (this.haveLoggedInUser())
       openUILinkIn(Social.provider.profile.profileURL, "tab");
@@ -64,16 +66,22 @@ let SocialUI = {
         SocialToolbar.updateButton();
         SocialMenu.populate();
         break;
       case "social:profile-changed":
         SocialToolbar.updateProfile();
         SocialShareButton.updateProfileInfo();
         SocialChatBar.update();
         break;
+      case "social:frameworker-error":
+        if (Social.provider) {
+          Social.errorState = "frameworker-error";
+          SocialSidebar.setSidebarErrorMessage("frameworker-error");
+        }
+        break;
       case "nsPref:changed":
         SocialSidebar.updateSidebar();
         SocialToolbar.updateButton();
         SocialMenu.populate();
         break;
     }
   },
 
@@ -996,16 +1004,21 @@ var SocialSidebar = {
         this.unloadSidebar();
       } else {
         this._unloadTimeoutId = setTimeout(
           this.unloadSidebar,
           Services.prefs.getIntPref("social.sidebar.unload_timeout_ms")
         );
       }
     } else {
+      if (Social.errorState == "frameworker-error") {
+        SocialSidebar.setSidebarErrorMessage("frameworker-error");
+        return;
+      }
+
       // Make sure the right sidebar URL is loaded
       if (sbrowser.getAttribute("origin") != Social.provider.origin) {
         sbrowser.setAttribute("origin", Social.provider.origin);
         sbrowser.setAttribute("src", Social.provider.sidebarURL);
         sbrowser.addEventListener("load", function sidebarOnShow() {
           sbrowser.removeEventListener("load", sidebarOnShow, true);
           // let load finish, then fire our event
           setTimeout(function () {
@@ -1044,20 +1057,28 @@ var SocialSidebar = {
 
     container.appendChild(sbrowser);
 
     SocialFlyout.unload();
   },
 
   _unloadTimeoutId: 0,
 
-  setSidebarErrorMessage: function() {
+  setSidebarErrorMessage: function(aType) {
     let sbrowser = document.getElementById("social-sidebar-browser");
-    let url = encodeURIComponent(Social.provider.sidebarURL);
-    sbrowser.loadURI("about:socialerror?mode=tryAgain&url=" + url, null, null);
+    switch (aType) {
+      case "sidebar-error":
+        let url = encodeURIComponent(Social.provider.sidebarURL);
+        sbrowser.loadURI("about:socialerror?mode=tryAgain&url=" + url, null, null);
+        break;
+
+      case "frameworker-error":
+        sbrowser.setAttribute("src", "about:socialerror?mode=workerFailure");
+        break;
+    }
   }
 }
 
 // Error handling class used to listen for network errors in the social frames
 // and replace them with a social-specific error page
 function SocialErrorListener(aType) {
   this.type = aType;
 }
@@ -1085,17 +1106,17 @@ SocialErrorListener.prototype = {
     if (failure && aStatus != Components.results.NS_BINDING_ABORTED) {
       aRequest.cancel(Components.results.NS_BINDING_ABORTED);
       this.setErrorMessage(aWebProgress);
     }
   },
 
   onLocationChange: function SPL_onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {
     let failure = aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE;
-    if (failure) {
+    if (failure && Social.errorState != "frameworker-error") {
       aRequest.cancel(Components.results.NS_BINDING_ABORTED);
       window.setTimeout(function(self) {
         self.setErrorMessage(aWebProgress);
       }, 0, this);
     }
   },
 
   onProgressChange: function SPL_onProgressChange() {},
@@ -1104,17 +1125,17 @@ SocialErrorListener.prototype = {
 
   setErrorMessage: function(aWebProgress) {
     switch (this.type) {
       case "flyout":
         SocialFlyout.setFlyoutErrorMessage();
         break;
 
       case "sidebar":
-        SocialSidebar.setSidebarErrorMessage();
+        SocialSidebar.setSidebarErrorMessage("sidebar-error");
         break;
 
       case "notification-panel":
         let frame = aWebProgress.QueryInterface(Ci.nsIDocShell)
                                 .chromeEventHandler;
         SocialToolbar.setPanelErrorMessage(frame);
         break;
     }
--- a/browser/components/privatebrowsing/test/browser/global/Makefile.in
+++ b/browser/components/privatebrowsing/test/browser/global/Makefile.in
@@ -28,17 +28,16 @@ MOCHITEST_BROWSER_FILES =  \
 		browser_privatebrowsing_localStorage_page2.html \
 		browser_privatebrowsing_opendir.js \
 		browser_privatebrowsing_openlocation.js \
 		browser_privatebrowsing_openLocationLastURL.js \
 		browser_privatebrowsing_placestitle.js \
 		browser_privatebrowsing_popupblocker.js \
 		browser_privatebrowsing_protocolhandler.js \
 		browser_privatebrowsing_protocolhandler_page.html \
-		browser_privatebrowsing_sslsite_transition.js \
 		browser_privatebrowsing_theming.js \
 		browser_privatebrowsing_ui.js \
 		browser_privatebrowsing_urlbarfocus.js \
 		browser_privatebrowsing_windowtitle.js \
 		browser_privatebrowsing_windowtitle_page.html \
 		browser_privatebrowsing_zoom.js \
 		browser_privatebrowsing_zoomrestore.js \
 		ctxmenu.html \
--- a/browser/components/privatebrowsing/test/browser/obsolete/Makefile.in
+++ b/browser/components/privatebrowsing/test/browser/obsolete/Makefile.in
@@ -17,16 +17,17 @@ MOCHITEST_BROWSER_FILES =  \
 		browser_privatebrowsing_fastswitch.js \
 		browser_privatebrowsing_findbar.js \
 		browser_privatebrowsing_forgetthissite.js \
 		browser_privatebrowsing_import.js \
 		browser_privatebrowsing_newwindow_stopcmd.js \
 		browser_privatebrowsing_pageinfo.js \
 		browser_privatebrowsing_popupmode.js \
 		browser_privatebrowsing_searchbar.js \
+		browser_privatebrowsing_sslsite_transition.js \
 		browser_privatebrowsing_transition.js \
 		browser_privatebrowsing_urlbarundo.js \
 		browser_privatebrowsing_viewsource.js \
 		staller.sjs \
 		$(NULL)
 
 # Disabled until bug 564934 is fixed:
 #		browser_privatebrowsing_downloadmonitor.js \
rename from browser/components/privatebrowsing/test/browser/global/browser_privatebrowsing_sslsite_transition.js
rename to browser/components/privatebrowsing/test/browser/obsolete/browser_privatebrowsing_sslsite_transition.js
--- a/browser/modules/Social.jsm
+++ b/browser/modules/Social.jsm
@@ -37,16 +37,19 @@ let Social = {
     }.bind(this));
   },
 
   get uiVisible() {
     return this.provider && this.provider.enabled;
   },
 
   set enabled(val) {
+    if (!val) {
+      delete this.errorState;
+    }
     SocialService.enabled = val;
   },
   get enabled() {
     return SocialService.enabled;
   },
 
   get active() {
     return Services.prefs.getBoolPref("social.active");
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -1418,17 +1418,16 @@ richlistitem[type~="action"][actiontype=
 }
 
 #unsharePopupBottomButtons {
   margin-top: 1em;
 }
 
 /* Star button */
 #star-button {
-  padding: 1px;
   list-style-image: url("chrome://browser/skin/places/starPage.png");
 }
 
 #star-button[starred="true"] {
   list-style-image: url("chrome://browser/skin/places/pageStarred.png");
 }
 
 /* Bookmarking panel */
--- a/caps/idl/nsIScriptSecurityManager.idl
+++ b/caps/idl/nsIScriptSecurityManager.idl
@@ -5,17 +5,17 @@
 
 #include "nsISupports.idl"
 #include "nsIPrincipal.idl"
 #include "nsIXPCSecurityManager.idl"
 interface nsIURI;
 interface nsIChannel;
 interface nsIDocShell;
 
-[scriptable, uuid(b17f9a0b-c36b-4961-8f19-11e03f43436d)]
+[scriptable, uuid(ae486501-ec57-4ec8-a565-6880ca4ae6c4)]
 interface nsIScriptSecurityManager : nsIXPCSecurityManager
 {
     ///////////////// Security Checks //////////////////
     /**
      * Checks whether the running script is allowed to access aProperty.
      */
     [noscript] void checkPropertyAccess(in JSContextPtr aJSContext,
                                         in JSObjectPtr aJSObject,
@@ -162,16 +162,23 @@ interface nsIScriptSecurityManager : nsI
 
     /**
      * Returns a principal with that has the same origin as uri and is not part
      * of an appliction.
      * The returned principal will have appId = NO_APP_ID.
      */
     nsIPrincipal getNoAppCodebasePrincipal(in nsIURI uri);
 
+    /**
+     * Legacy name for getNoAppCodebasePrincipal.
+     *
+     * @deprecated use getNoAppCodebasePrincipal instead.
+     */
+    [deprecated] nsIPrincipal getCodebasePrincipal(in nsIURI uri);
+
     ///////////////////////
     /**
      * Return the principal of the specified object in the specified context.
      */
     [noscript] nsIPrincipal getObjectPrincipal(in JSContextPtr cx,
                                                in JSObjectPtr obj);
 
     /**
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -1870,16 +1870,23 @@ NS_IMETHODIMP
 nsScriptSecurityManager::GetNoAppCodebasePrincipal(nsIURI* aURI,
                                                    nsIPrincipal** aPrincipal)
 {
   return GetCodebasePrincipalInternal(aURI,  nsIScriptSecurityManager::NO_APP_ID,
                                       false, aPrincipal);
 }
 
 NS_IMETHODIMP
+nsScriptSecurityManager::GetCodebasePrincipal(nsIURI* aURI,
+                                              nsIPrincipal** aPrincipal)
+{
+  return GetNoAppCodebasePrincipal(aURI, aPrincipal);
+}
+
+NS_IMETHODIMP
 nsScriptSecurityManager::GetAppCodebasePrincipal(nsIURI* aURI,
                                                  uint32_t aAppId,
                                                  bool aInMozBrowser,
                                                  nsIPrincipal** aPrincipal)
 {
   NS_ENSURE_TRUE(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
                  NS_ERROR_INVALID_ARG);
 
--- a/config/makefiles/xpcshell.mk
+++ b/config/makefiles/xpcshell.mk
@@ -53,16 +53,17 @@ xpcshell-tests:
 	  $(LIBXUL_DIST)/bin/xpcshell \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 
 xpcshell-tests-remote: DM_TRANS?=adb
 xpcshell-tests-remote:
 	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/build \
 	  -I$(topsrcdir)/build/mobile \
+	  -I$(topsrcdir)/testing/mozbase/mozdevice/mozdevice \
 	  $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  $(EXTRA_TEST_ARGS) \
 	  --dm_trans=$(DM_TRANS) \
 	  --deviceIP=${TEST_DEVICE} \
 	  --objdir=$(DEPTH) \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -1020,17 +1020,17 @@ nsScriptLoader::ConvertToUTF16(nsIChanne
 
   if (!unicodeDecoder &&
       aChannel &&
       NS_SUCCEEDED(aChannel->GetContentCharset(charset))) {
     charsetConv->GetUnicodeDecoder(charset.get(),
                                    getter_AddRefs(unicodeDecoder));
   }
 
-  if (!unicodeDecoder) {
+  if (!unicodeDecoder && !aHintCharset.IsEmpty()) {
     CopyUTF16toUTF8(aHintCharset, charset);
     charsetConv->GetUnicodeDecoder(charset.get(),
                                    getter_AddRefs(unicodeDecoder));
   }
 
   if (!unicodeDecoder && aDocument) {
     charset = aDocument->GetDocumentCharacterSet();
     charsetConv->GetUnicodeDecoderRaw(charset.get(),
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -2885,27 +2885,30 @@ nsEventStateManager::DoScrollText(nsIScr
     case nsIDOMWheelEvent::DOM_DELTA_PIXEL:
       origin = nsGkAtoms::pixels;
       break;
     default:
       MOZ_NOT_REACHED("Invalid deltaMode value comes");
       return;
   }
 
-  // We shouldn't scroll more one page at once.
+  // We shouldn't scroll more one page at once except when over one page scroll
+  // is allowed for the event.
   nsSize pageSize = aScrollableFrame->GetPageScrollAmount();
   nsIntSize devPixelPageSize(pc->AppUnitsToDevPixels(pageSize.width),
                              pc->AppUnitsToDevPixels(pageSize.height));
-  if (NS_ABS(actualDevPixelScrollAmount.x) > devPixelPageSize.width) {
+  if (!WheelPrefs::GetInstance()->IsOverOnePageScrollAllowedX(aEvent) &&
+      NS_ABS(actualDevPixelScrollAmount.x) > devPixelPageSize.width) {
     actualDevPixelScrollAmount.x =
       (actualDevPixelScrollAmount.x >= 0) ? devPixelPageSize.width :
                                             -devPixelPageSize.width;
   }
 
-  if (NS_ABS(actualDevPixelScrollAmount.y) > devPixelPageSize.height) {
+  if (!WheelPrefs::GetInstance()->IsOverOnePageScrollAllowedY(aEvent) &&
+      NS_ABS(actualDevPixelScrollAmount.y) > devPixelPageSize.height) {
     actualDevPixelScrollAmount.y =
       (actualDevPixelScrollAmount.y >= 0) ? devPixelPageSize.height :
                                             -devPixelPageSize.height;
   }
 
   bool isDeltaModePixel =
     (aEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL);
 
@@ -5542,8 +5545,28 @@ nsEventStateManager::WheelPrefs::NeedToC
                                    widget::WheelEvent* aEvent)
 {
   Index index = GetIndexFor(aEvent);
   Init(index);
 
   return (mMultiplierX[index] != 1.0 && mMultiplierX[index] != -1.0) ||
          (mMultiplierY[index] != 1.0 && mMultiplierY[index] != -1.0);
 }
+
+bool
+nsEventStateManager::WheelPrefs::IsOverOnePageScrollAllowedX(
+                                   widget::WheelEvent* aEvent)
+{
+  Index index = GetIndexFor(aEvent);
+  Init(index);
+  return NS_ABS(mMultiplierX[index]) >=
+           MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL;
+}
+
+bool
+nsEventStateManager::WheelPrefs::IsOverOnePageScrollAllowedY(
+                                   widget::WheelEvent* aEvent)
+{
+  Index index = GetIndexFor(aEvent);
+  Init(index);
+  return NS_ABS(mMultiplierY[index]) >=
+           MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL;
+}
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -363,16 +363,23 @@ protected:
     Action ComputeActionFor(mozilla::widget::WheelEvent* aEvent);
 
     /**
      * NeedToComputeLineOrPageDelta() returns if the aEvent needs to be
      * computed the lineOrPageDelta values.
      */
     bool NeedToComputeLineOrPageDelta(mozilla::widget::WheelEvent* aEvent);
 
+    /**
+     * IsOverOnePageScrollAllowed*() checks whether wheel scroll amount should
+     * be rounded down to the page width/height (false) or not (true).
+     */
+    bool IsOverOnePageScrollAllowedX(mozilla::widget::WheelEvent* aEvent);
+    bool IsOverOnePageScrollAllowedY(mozilla::widget::WheelEvent* aEvent);
+
   private:
     WheelPrefs();
     ~WheelPrefs();
 
     static int OnPrefChanged(const char* aPrefName, void* aClosure);
 
     enum Index
     {
@@ -404,16 +411,25 @@ protected:
      *                      "mousewheel.default.".
      */
     void GetBasePrefName(Index aIndex, nsACString& aBasePrefName);
 
     void Init(Index aIndex);
 
     void Reset();
 
+    /**
+     * If the abosolute values of mMultiplierX and/or mMultiplierY are equals or
+     * larger than this value, the computed scroll amount isn't rounded down to
+     * the page width or height.
+     */
+    enum {
+      MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL = 1000
+    };
+
     bool mInit[COUNT_OF_MULTIPLIERS];
     double mMultiplierX[COUNT_OF_MULTIPLIERS];
     double mMultiplierY[COUNT_OF_MULTIPLIERS];
     double mMultiplierZ[COUNT_OF_MULTIPLIERS];
     Action mActions[COUNT_OF_MULTIPLIERS];
 
     static WheelPrefs* sInstance;
   };
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -55,18 +55,17 @@ public:
   NS_DECL_NSISELECTIONLISTENER
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   nsresult Init(nsIWidget* aWidget,
                 nsPresContext* aPresContext,
-                nsINode* aNode,
-                bool aWantUpdates);
+                nsINode* aNode);
   void     Destroy(void);
   bool     IsManaging(nsPresContext* aPresContext, nsIContent* aContent);
 
   nsCOMPtr<nsIWidget>            mWidget;
   nsCOMPtr<nsISelection>         mSel;
   nsCOMPtr<nsIContent>           mRootContent;
   nsCOMPtr<nsINode>              mEditableNode;
   bool                           mDestroying;
@@ -111,16 +110,19 @@ nsIMEStateManager::OnDestroyPresContext(
                    TextCompositionArray::NoIndex);
     }
   }
 
   if (aPresContext != sPresContext)
     return NS_OK;
   nsCOMPtr<nsIWidget> widget = sPresContext->GetNearestWidget();
   if (widget) {
+    if (IsEditableIMEState(widget)) {
+      widget->OnIMEFocusChange(false);
+    }
     IMEState newState = GetNewIMEState(sPresContext, nullptr);
     InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
                               InputContextAction::LOST_FOCUS);
     SetIMEState(newState, nullptr, widget, action);
   }
   NS_IF_RELEASE(sContent);
   sPresContext = nullptr;
   DestroyTextStateManager();
@@ -170,16 +172,19 @@ nsIMEStateManager::OnRemoveContent(nsPre
   if (!sPresContext || !sContent ||
       !nsContentUtils::ContentIsDescendantOf(sContent, aContent)) {
     return NS_OK;
   }
 
   // Current IME transaction should commit
   nsCOMPtr<nsIWidget> widget = sPresContext->GetNearestWidget();
   if (widget) {
+    if (IsEditableIMEState(widget)) {
+      widget->OnIMEFocusChange(false);
+    }
     IMEState newState = GetNewIMEState(sPresContext, nullptr);
     InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
                               InputContextAction::LOST_FOCUS);
     SetIMEState(newState, nullptr, widget, action);
   }
 
   NS_IF_RELEASE(sContent);
   sPresContext = nullptr;
@@ -197,26 +202,45 @@ nsIMEStateManager::OnChangeFocus(nsPresC
   return OnChangeFocusInternal(aPresContext, aContent, action);
 }
 
 nsresult
 nsIMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
                                          nsIContent* aContent,
                                          InputContextAction aAction)
 {
+  bool focusActuallyChanging =
+    (sContent != aContent || sPresContext != aPresContext);
+
+  nsCOMPtr<nsIWidget> oldWidget =
+    sPresContext ? sPresContext->GetNearestWidget() : nullptr;
+  if (oldWidget && focusActuallyChanging) {
+    // If we're deactivating, we shouldn't commit composition forcibly because
+    // the user may want to continue the composition.
+    if (aPresContext) {
+      NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
+    }
+    // Notify IME of losing focus even if we're deactivating.
+    if (IsEditableIMEState(oldWidget)) {
+      oldWidget->OnIMEFocusChange(false);
+    }
+  }
+
   if (sTextStateObserver &&
       !sTextStateObserver->IsManaging(aPresContext, aContent)) {
     DestroyTextStateManager();
   }
 
   if (!aPresContext) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIWidget> widget = aPresContext->GetNearestWidget();
+  nsCOMPtr<nsIWidget> widget =
+    (sPresContext == aPresContext) ? oldWidget.get() :
+                                     aPresContext->GetNearestWidget();
   if (!widget) {
     return NS_OK;
   }
 
   // Handle secure input mode for password field input.
   bool contentIsPassword = false;
   if (aContent && aContent->GetNameSpaceID() == kNameSpaceID_XHTML) {
     if (aContent->Tag() == nsGkAtoms::input) {
@@ -235,45 +259,39 @@ nsIMEStateManager::OnChangeFocusInternal
     if (contentIsPassword) {
       if (NS_SUCCEEDED(widget->BeginSecureKeyboardInput())) {
         sInSecureInputMode = true;
       }
     }
   }
 
   IMEState newState = GetNewIMEState(aPresContext, aContent);
-  if (aPresContext == sPresContext && aContent == sContent) {
+  if (!focusActuallyChanging) {
     // actual focus isn't changing, but if IME enabled state is changing,
     // we should do it.
     InputContext context = widget->GetInputContext();
     if (context.mIMEState.mEnabled == newState.mEnabled) {
       // the enabled state isn't changing.
       return NS_OK;
     }
     aAction.mFocusChange = InputContextAction::FOCUS_NOT_CHANGED;
+
+    // Even if focus isn't changing actually, we should commit current
+    // composition here since the IME state is changing.
+    if (sPresContext && oldWidget && !focusActuallyChanging) {
+      NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
+    }
   } else if (aAction.mFocusChange == InputContextAction::FOCUS_NOT_CHANGED) {
     // If aContent isn't null or aContent is null but editable, somebody gets
     // focus.
     bool gotFocus = aContent || (newState.mEnabled == IMEState::ENABLED);
     aAction.mFocusChange =
       gotFocus ? InputContextAction::GOT_FOCUS : InputContextAction::LOST_FOCUS;
   }
 
-  // Current IME transaction should commit
-  if (sPresContext) {
-    nsCOMPtr<nsIWidget> oldWidget;
-    if (sPresContext == aPresContext)
-      oldWidget = widget;
-    else
-      oldWidget = sPresContext->GetNearestWidget();
-    if (oldWidget) {
-      NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
-    }
-  }
-
   // Update IME state for new focus widget
   SetIMEState(newState, aContent, widget, aAction);
 
   sPresContext = aPresContext;
   if (sContent != aContent) {
     NS_IF_RELEASE(sContent);
     NS_IF_ADDREF(sContent = aContent);
   }
@@ -651,25 +669,20 @@ nsIMEStateManager::NotifyIME(Notificatio
 nsTextStateManager::nsTextStateManager()
 {
   mDestroying = false;
 }
 
 nsresult
 nsTextStateManager::Init(nsIWidget* aWidget,
                          nsPresContext* aPresContext,
-                         nsINode* aNode,
-                         bool aWantUpdates)
+                         nsINode* aNode)
 {
   mWidget = aWidget;
   MOZ_ASSERT(mWidget);
-  if (!aWantUpdates) {
-    mEditableNode = aNode;
-    return NS_OK;
-  }
 
   nsIPresShell* presShell = aPresContext->PresShell();
 
   // get selection and root content
   nsCOMPtr<nsISelectionController> selCon;
   if (aNode->IsNodeOfType(nsINode::eCONTENT)) {
     nsIFrame* frame = static_cast<nsIContent*>(aNode)->GetPrimaryFrame();
     NS_ENSURE_TRUE(frame, NS_ERROR_UNEXPECTED);
@@ -931,25 +944,40 @@ nsIMEStateManager::GetRootEditableNode(n
   if (aPresContext) {
     nsIDocument* document = aPresContext->Document();
     if (document && document->IsEditable())
       return document;
   }
   return nullptr;
 }
 
+bool
+nsIMEStateManager::IsEditableIMEState(nsIWidget* aWidget)
+{
+  switch (aWidget->GetInputContext().mIMEState.mEnabled) {
+    case widget::IMEState::ENABLED:
+    case widget::IMEState::PASSWORD:
+      return true;
+    case widget::IMEState::PLUGIN:
+    case widget::IMEState::DISABLED:
+      return false;
+    default:
+      MOZ_NOT_REACHED("Unknown IME enable state");
+      return false;
+  }
+}
+
 void
 nsIMEStateManager::DestroyTextStateManager()
 {
   if (!sTextStateObserver || sTextStateObserver->mDestroying) {
     return;
   }
 
   sTextStateObserver->mDestroying = true;
-  sTextStateObserver->mWidget->OnIMEFocusChange(false);
   sTextStateObserver->Destroy();
   NS_RELEASE(sTextStateObserver);
 }
 
 void
 nsIMEStateManager::CreateTextStateManager()
 {
   if (sTextStateObserver) {
@@ -959,45 +987,38 @@ nsIMEStateManager::CreateTextStateManage
   }
 
   nsCOMPtr<nsIWidget> widget = sPresContext->GetNearestWidget();
   if (!widget) {
     return; // Sometimes, there are no widgets.
   }
 
   // If it's not text ediable, we don't need to create nsTextStateManager.
-  switch (widget->GetInputContext().mIMEState.mEnabled) {
-    case widget::IMEState::ENABLED:
-    case widget::IMEState::PASSWORD:
-      break;
-    default:
-      return;
+  if (!IsEditableIMEState(widget)) {
+    return;
   }
 
   nsINode *editableNode = GetRootEditableNode(sPresContext, sContent);
   if (!editableNode) {
     return;
   }
 
   nsresult rv = widget->OnIMEFocusChange(true);
   if (rv == NS_ERROR_NOT_IMPLEMENTED)
     return;
   NS_ENSURE_SUCCESS_VOID(rv);
 
-  bool wantUpdates = rv != NS_SUCCESS_IME_NO_UPDATES;
-
   // OnIMEFocusChange may cause focus and sTextStateObserver to change
   // In that case return and keep the current sTextStateObserver
   NS_ENSURE_TRUE_VOID(!sTextStateObserver);
 
   sTextStateObserver = new nsTextStateManager();
   NS_ENSURE_TRUE_VOID(sTextStateObserver);
   NS_ADDREF(sTextStateObserver);
-  rv = sTextStateObserver->Init(widget, sPresContext,
-                                editableNode, wantUpdates);
+  rv = sTextStateObserver->Init(widget, sPresContext, editableNode);
   if (NS_SUCCEEDED(rv)) {
     return;
   }
 
   sTextStateObserver->mDestroying = true;
   sTextStateObserver->Destroy();
   NS_RELEASE(sTextStateObserver);
   widget->OnIMEFocusChange(false);
--- a/content/events/src/nsIMEStateManager.h
+++ b/content/events/src/nsIMEStateManager.h
@@ -118,16 +118,18 @@ protected:
   static void EnsureTextCompositionArray();
   static void CreateTextStateManager();
   static void DestroyTextStateManager();
 
   static bool IsEditable(nsINode* node);
   static nsINode* GetRootEditableNode(nsPresContext* aPresContext,
                                       nsIContent* aContent);
 
+  static bool IsEditableIMEState(nsIWidget* aWidget);
+
   static nsIContent*    sContent;
   static nsPresContext* sPresContext;
   static bool           sInstalledMenuKeyboardListener;
   static bool           sInSecureInputMode;
 
   static nsTextStateManager* sTextStateObserver;
 
   // All active compositions in the process are stored by this array.
--- a/content/events/test/window_wheel_default_action.html
+++ b/content/events/test/window_wheel_default_action.html
@@ -1130,17 +1130,17 @@ function doTestZoom(aSettings, aCallback
 
       synthesizeKey("0", { accelKey: true });
       hitEventLoop(doNextTest, 20);
     }, 20);
   }
   doNextTest();
 }
 
-function doTestZoomedScroll()
+function doTestZoomedScroll(aCallback)
 {
   function testZoomedPixelScroll()
   {
     // Reset zoom and store the scroll amount into the data.
     synthesizeKey("0", { accelKey: true });
     gScrollableElement.scrollTop = 1000;
     gScrollableElement.scrollLeft = 1000;
     // Ensure not to be in reflow.
@@ -1257,28 +1257,285 @@ function doTestZoomedScroll()
                  gScrollableElement.scrollLeft + ", scrolledX=" + scrolledX);
             ok(Math.abs(gScrollableElement.scrollTop - scrolledY) <= 1,
                "doTestZoomedScroll: zoomed vertical scroll amount by line wheel event is different from normal, scrollTop=" +
                  gScrollableElement.scrollTop + ", scrolledY=" + scrolledY);
 
             window.removeEventListener("MozMousePixelScroll", handler, true);
 
             synthesizeKey("0", { accelKey: true });
+
+            SimpleTest.executeSoon(aCallback);
           }, 20);
         }, 20);
       }, 20);
     }, 20);
   }
 
   // XXX It's too difficult to test page scroll because the page scroll amount
   //     is computed by complex logic.
 
   testZoomedPixelScroll();
 }
 
+function doTestWholeScroll(aCallback)
+{
+  SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_x", 99999999);
+  SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_y", 99999999);
+
+  const kTests = [
+    { description: "try whole-scroll to top (line)",
+      prepare: function () {
+        gScrollableElement.scrollTop = 1000;
+        gScrollableElement.scrollLeft = 1000;
+      },
+      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
+               deltaX: 0.0, deltaY: -1.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1 },
+      expectedScrollTop: 0,
+      expectedScrollLeft: 1000
+    },
+    { description: "try whole-scroll to top when scrollTop is already top-most (line)",
+      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
+               deltaX: 0.0, deltaY: -1.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1 },
+      expectedScrollTop: 0,
+      expectedScrollLeft: 1000
+    },
+    { description: "try whole-scroll to bottom (line)",
+      prepare: function () {
+        gScrollableElement.scrollTop = 1000;
+        gScrollableElement.scrollLeft = 1000;
+      },
+      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
+               deltaX: 0.0, deltaY: 1.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1 },
+      expectedScrollTop: gScrollableElement.scrollTopMax,
+      expectedScrollLeft: 1000
+    },
+    { description: "try whole-scroll to bottom when scrollTop is already bottom-most (line)",
+      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
+               deltaX: 0, deltaY: 1.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1 },
+      expectedScrollTop: gScrollableElement.scrollTopMax,
+      expectedScrollLeft: 1000
+    },
+    { description: "try whole-scroll to left (line)",
+      prepare: function () {
+        gScrollableElement.scrollTop = 1000;
+        gScrollableElement.scrollLeft = 1000;
+      },
+      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
+               deltaX: -1.0, deltaY: 0.0,
+               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0 },
+      expectedScrollTop: 1000,
+      expectedScrollLeft: 0
+    },
+    { description: "try whole-scroll to left when scrollLeft is already left-most (line)",
+      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
+               deltaX: -1.0, deltaY: 0,
+               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0 },
+      expectedScrollTop: 1000,
+      expectedScrollLeft: 0
+    },
+    { description: "try whole-scroll to right (line)",
+      prepare: function () {
+        gScrollableElement.scrollTop = 1000;
+        gScrollableElement.scrollLeft = 1000;
+      },
+      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
+               deltaX: 1.0, deltaY: 0.0,
+               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0 },
+      expectedScrollTop: 1000,
+      expectedScrollLeft: gScrollableElement.scrollLeftMax
+    },
+    { description: "try whole-scroll to right when scrollLeft is already right-most (line)",
+      event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
+               deltaX: 1.0, deltaY: 0.0,
+               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0 },
+      expectedScrollTop: 1000,
+      expectedScrollLeft: gScrollableElement.scrollLeftMax
+    },
+
+
+    { description: "try whole-scroll to top (pixel)",
+      prepare: function () {
+        gScrollableElement.scrollTop = 1000;
+        gScrollableElement.scrollLeft = 1000;
+      },
+      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+               deltaX: 0.0, deltaY: -1.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
+      expectedScrollTop: 0,
+      expectedScrollLeft: 1000
+    },
+    { description: "try whole-scroll to top when scrollTop is already top-most (pixel)",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+               deltaX: 0.0, deltaY: -1.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
+      expectedScrollTop: 0,
+      expectedScrollLeft: 1000
+    },
+    { description: "try whole-scroll to bottom (pixel)",
+      prepare: function () {
+        gScrollableElement.scrollTop = 1000;
+        gScrollableElement.scrollLeft = 1000;
+      },
+      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+               deltaX: 0.0, deltaY: 1.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
+      expectedScrollTop: gScrollableElement.scrollTopMax,
+      expectedScrollLeft: 1000
+    },
+    { description: "try whole-scroll to bottom when scrollTop is already bottom-most (pixel)",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+               deltaX: 0, deltaY: 1.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
+      expectedScrollTop: gScrollableElement.scrollTopMax,
+      expectedScrollLeft: 1000
+    },
+    { description: "try whole-scroll to left (pixel)",
+      prepare: function () {
+        gScrollableElement.scrollTop = 1000;
+        gScrollableElement.scrollLeft = 1000;
+      },
+      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+               deltaX: -1.0, deltaY: 0.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
+      expectedScrollTop: 1000,
+      expectedScrollLeft: 0
+    },
+    { description: "try whole-scroll to left when scrollLeft is already left-most (pixel)",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+               deltaX: -1.0, deltaY: 0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
+      expectedScrollTop: 1000,
+      expectedScrollLeft: 0
+    },
+    { description: "try whole-scroll to right (pixel)",
+      prepare: function () {
+        gScrollableElement.scrollTop = 1000;
+        gScrollableElement.scrollLeft = 1000;
+      },
+      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+               deltaX: 1.0, deltaY: 0.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
+      expectedScrollTop: 1000,
+      expectedScrollLeft: gScrollableElement.scrollLeftMax
+    },
+    { description: "try whole-scroll to right when scrollLeft is already right-most (pixel)",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
+               deltaX: 1.0, deltaY: 0.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 },
+      expectedScrollTop: 1000,
+      expectedScrollLeft: gScrollableElement.scrollLeftMax
+    },
+
+
+    { description: "try whole-scroll to top (page)",
+      prepare: function () {
+        gScrollableElement.scrollTop = 1000;
+        gScrollableElement.scrollLeft = 1000;
+      },
+      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
+               deltaX: 0.0, deltaY: -1.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1 },
+      expectedScrollTop: 0,
+      expectedScrollLeft: 1000
+    },
+    { description: "try whole-scroll to top when scrollTop is already top-most (page)",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
+               deltaX: 0.0, deltaY: -1.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: -1 },
+      expectedScrollTop: 0,
+      expectedScrollLeft: 1000
+    },
+    { description: "try whole-scroll to bottom (page)",
+      prepare: function () {
+        gScrollableElement.scrollTop = 1000;
+        gScrollableElement.scrollLeft = 1000;
+      },
+      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
+               deltaX: 0.0, deltaY: 1.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1 },
+      expectedScrollTop: gScrollableElement.scrollTopMax,
+      expectedScrollLeft: 1000
+    },
+    { description: "try whole-scroll to bottom when scrollTop is already bottom-most (page)",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
+               deltaX: 0, deltaY: 1.0,
+               lineOrPageDeltaX: 0, lineOrPageDeltaY: 1 },
+      expectedScrollTop: gScrollableElement.scrollTopMax,
+      expectedScrollLeft: 1000
+    },
+    { description: "try whole-scroll to left (page)",
+      prepare: function () {
+        gScrollableElement.scrollTop = 1000;
+        gScrollableElement.scrollLeft = 1000;
+      },
+      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
+               deltaX: -1.0, deltaY: 0.0,
+               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0 },
+      expectedScrollTop: 1000,
+      expectedScrollLeft: 0
+    },
+    { description: "try whole-scroll to left when scrollLeft is already left-most (page)",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
+               deltaX: -1.0, deltaY: 0,
+               lineOrPageDeltaX: -1, lineOrPageDeltaY: 0 },
+      expectedScrollTop: 1000,
+      expectedScrollLeft: 0
+    },
+    { description: "try whole-scroll to right (page)",
+      prepare: function () {
+        gScrollableElement.scrollTop = 1000;
+        gScrollableElement.scrollLeft = 1000;
+      },
+      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
+               deltaX: 1.0, deltaY: 0.0,
+               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0 },
+      expectedScrollTop: 1000,
+      expectedScrollLeft: gScrollableElement.scrollLeftMax
+    },
+    { description: "try whole-scroll to right when scrollLeft is already right-most (page)",
+      event: { deltaMode: WheelEvent.DOM_DELTA_PAGE,
+               deltaX: 1.0, deltaY: 0.0,
+               lineOrPageDeltaX: 1, lineOrPageDeltaY: 0 },
+      expectedScrollTop: 1000,
+      expectedScrollLeft: gScrollableElement.scrollLeftMax
+    },
+  ];
+
+  var index = 0;
+
+  function doIt()
+  {
+    const kTest = kTests[index];
+    if (kTest.prepare) {
+      kTest.prepare();
+    }
+    synthesizeWheel(gScrollableElement, 10, 10, kTest.event);
+    hitEventLoop(function () {
+      is(gScrollableElement.scrollTop, kTest.expectedScrollTop,
+         "doTestWholeScroll, " + kTest.description + ": unexpected scrollTop");
+      is(gScrollableElement.scrollLeft, kTest.expectedScrollLeft,
+         "doTestWholeScroll, " + kTest.description + ": unexpected scrollLeft");
+      if (++index == kTests.length) {
+        SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_x");
+        SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_y");
+        SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_z");
+        SimpleTest.executeSoon(aCallback);
+      } else {
+        doIt();
+      }
+    }, 20);
+  }
+  doIt();
+}
+
 function runTests()
 {
   SpecialPowers.setBoolPref("general.smoothScroll", false);
 
   SpecialPowers.setIntPref("mousewheel.default.action", 1);      // scroll
   SpecialPowers.setIntPref("mousewheel.with_shift.action", 2);   // history
   SpecialPowers.setIntPref("mousewheel.with_control.action", 3); // zoom
 
@@ -1308,18 +1565,21 @@ function runTests()
   var index = 0;
 
   function doTest() {
     setDeltaMultiplierSettings(kSettings[index]);
     doTestScroll(kSettings[index], function () {
         doTestZoom(kSettings[index], function() {
           if (++index == kSettings.length) {
             setDeltaMultiplierSettings(kSettings[0]);
-            doTestZoomedScroll();
-            finishTests();
+            doTestZoomedScroll(function() {
+              doTestWholeScroll(function() {
+                finishTests();
+              });
+            });
           } else {
             doTest();
           }
         });
       });
   }
   doTest();
 }
--- a/content/media/webaudio/AudioBuffer.h
+++ b/content/media/webaudio/AudioBuffer.h
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#pragma once
+#ifndef AudioBuffer_h_
+#define AudioBuffer_h_
 
 #include "nsWrapperCache.h"
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/Attributes.h"
 #include "EnableWebAudioCheck.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
 #include "AudioContext.h"
@@ -76,8 +77,10 @@ private:
   FallibleTArray<JSObject*> mChannels;
   uint32_t mLength;
   float mSampleRate;
 };
 
 }
 }
 
+#endif
+
--- a/content/media/webaudio/AudioBufferSourceNode.h
+++ b/content/media/webaudio/AudioBufferSourceNode.h
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#pragma once
+#ifndef AudioBufferSourceNode_h_
+#define AudioBufferSourceNode_h_
 
 #include "AudioSourceNode.h"
 #include "AudioBuffer.h"
 
 namespace mozilla {
 namespace dom {
 
 class AudioBufferSourceNode : public AudioSourceNode
@@ -34,8 +35,10 @@ public:
 
 private:
   nsRefPtr<AudioBuffer> mBuffer;
 };
 
 }
 }
 
+#endif
+
--- a/content/media/webaudio/AudioContext.h
+++ b/content/media/webaudio/AudioContext.h
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#pragma once
+#ifndef AudioContext_h_
+#define AudioContext_h_
 
 #include "nsWrapperCache.h"
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/Attributes.h"
 #include "nsCOMPtr.h"
 #include "EnableWebAudioCheck.h"
 #include "nsAutoPtr.h"
 
@@ -63,8 +64,10 @@ public:
 private:
   nsCOMPtr<nsIDOMWindow> mWindow;
   nsRefPtr<AudioDestinationNode> mDestination;
 };
 
 }
 }
 
+#endif
+
--- a/content/media/webaudio/AudioDestinationNode.h
+++ b/content/media/webaudio/AudioDestinationNode.h
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#pragma once
+#ifndef AudioDestinationNode_h_
+#define AudioDestinationNode_h_
 
 #include "AudioNode.h"
 
 namespace mozilla {
 namespace dom {
 
 class AudioContext;
 
@@ -32,8 +33,10 @@ public:
     return 0;
   }
 
 };
 
 }
 }
 
+#endif
+
--- a/content/media/webaudio/AudioEventTimeline.h
+++ b/content/media/webaudio/AudioEventTimeline.h
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#pragma once
+#ifndef AudioEventTimeline_h_
+#define AudioEventTimeline_h_
 
 #include "mozilla/Attributes.h"
 #include "mozilla/FloatingPoint.h"
 #include "nsTArray.h"
 #include "math.h"
 
 namespace mozilla {
 
@@ -367,8 +368,10 @@ private:
   const float mDefaultValue;
   const float mMinValue;
   const float mMaxValue;
 };
 
 }
 }
 
+#endif
+
--- a/content/media/webaudio/AudioNode.h
+++ b/content/media/webaudio/AudioNode.h
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#pragma once
+#ifndef AudioNode_h_
+#define AudioNode_h_
 
 #include "nsWrapperCache.h"
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/Attributes.h"
 #include "EnableWebAudioCheck.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
 #include "AudioContext.h"
@@ -123,8 +124,10 @@ private:
   nsRefPtr<AudioContext> mContext;
   nsTArray<Input> mInputs;
   nsTArray<Output> mOutputs;
 };
 
 }
 }
 
+#endif
+
--- a/content/media/webaudio/AudioParam.h
+++ b/content/media/webaudio/AudioParam.h
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#pragma once
+#ifndef AudioParam_h_
+#define AudioParam_h_
 
 #include "AudioEventTimeline.h"
 #include "nsWrapperCache.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCOMPtr.h"
 #include "EnableWebAudioCheck.h"
 #include "nsAutoPtr.h"
 #include "AudioContext.h"
@@ -109,8 +110,10 @@ public:
 
 private:
   nsRefPtr<AudioContext> mContext;
 };
 
 }
 }
 
+#endif
+
--- a/content/media/webaudio/AudioSourceNode.h
+++ b/content/media/webaudio/AudioSourceNode.h
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#pragma once
+#ifndef AudioSourceNode_h_
+#define AudioSourceNode_h_
 
 #include "AudioNode.h"
 
 namespace mozilla {
 namespace dom {
 
 class AudioSourceNode : public AudioNode
 {
@@ -27,8 +28,10 @@ public:
     return 1;
   }
 
 };
 
 }
 }
 
+#endif
+
--- a/content/media/webaudio/EnableWebAudioCheck.h
+++ b/content/media/webaudio/EnableWebAudioCheck.h
@@ -1,21 +1,24 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#pragma once
+#ifndef EnableWebAudioCheck_h_
+#define EnableWebAudioCheck_h_
 
 namespace mozilla {
 namespace dom {
 
 // This is a helper class which enables Web Audio to be enabled or disabled
 // as whole.  Individual Web Audio object classes should inherit from this.
 class EnableWebAudioCheck {
 public:
   static bool PrefEnabled();
 };
 
 }
 }
 
+#endif
+
--- a/content/xul/document/crashtests/428951-1.xul
+++ b/content/xul/document/crashtests/428951-1.xul
@@ -1,11 +1,11 @@
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:mathml="http://www.w3.org/1998/Math/MathML">
 <box>
-  <box style="background: -moz-initial;" id="f">
+  <box style="background: initial;" id="f">
     <box style="margin-top: -9999999px;"/>
   </box>
   <mathml:divergence>
     <box/>
   </mathml:divergence>
   <mathml:moment command="f"/>
 </box>
 
--- a/dom/activities/src/ActivitiesService.jsm
+++ b/dom/activities/src/ActivitiesService.jsm
@@ -279,23 +279,23 @@ let Activities = {
     let msg = aMessage.json;
 
     let caller;
     let obsData;
 
     if (aMessage.name == "Activity:PostResult" ||
         aMessage.name == "Activity:PostError") {
       caller = this.callers[msg.id];
-      if (caller) {
-        obsData = JSON.stringify({ manifestURL: caller.manifestURL,
-                                   pageURL: caller.pageURL,
-                                   success: aMessage.name == "Activity:PostResult" });
-      } else {
+      if (!caller) {
         debug("!! caller is null for msg.id=" + msg.id);
+        return;
       }
+      obsData = JSON.stringify({ manifestURL: caller.manifestURL,
+                                 pageURL: caller.pageURL,
+                                 success: aMessage.name == "Activity:PostResult" });
     }
 
     switch(aMessage.name) {
       case "Activity:Start":
         this.callers[msg.id] = { mm: aMessage.target,
                                  manifestURL: msg.manifestURL,
                                  pageURL: msg.pageURL };
         this.startActivity(msg);
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -241,19 +241,53 @@ let DOMApplicationRegistry = {
         }
         aNext();
       }).bind(this));
     } else {
       aNext();
     }
   },
 
+#ifdef MOZ_WIDGET_GONK
+  fixIndexedDb: function fixIndexedDb() {
+    debug("Fixing indexedDb folder names");
+    let idbDir = FileUtils.getDir("indexedDBPDir", ["indexedDB"]);
+
+    if (!idbDir.isDirectory()) {
+      return;
+    }
+
+    let re = /^(\d+)\+(.*)\+(f|t)$/;
+
+    let entries = idbDir.directoryEntries;
+    while (entries.hasMoreElements()) {
+      let entry = entries.getNext().QueryInterface(Ci.nsIFile);
+      if (!entry.isDirectory()) {
+        continue;
+      }
+
+      let newName = entry.leafName.replace(re, "$1+$3+$2");
+      if (newName != entry.leafName) {
+        try {
+          entry.moveTo(idbDir, newName);
+        } catch(e) { }
+      }
+    }
+  },
+#endif
+
   loadAndUpdateApps: function loadAndUpdateApps() {
     let runUpdate = AppsUtils.isFirstRun(Services.prefs);
 
+#ifdef MOZ_WIDGET_GONK
+    if (runUpdate) {
+      this.fixIndexedDb();
+    }
+#endif
+
     let onAppsLoaded = (function onAppsLoaded() {
       if (runUpdate) {
         // At first run, set up the permissions
         for (let id in this.webapps) {
           this.updatePermissionsForApp(id);
           this.updateOfflineCacheForApp(id);
         }
       }
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -137,32 +137,30 @@
 // Event related includes
 #include "nsEventListenerManager.h"
 #include "nsIDOMEventTarget.h"
 
 // CSS related includes
 #include "nsCSSRules.h"
 #include "nsIDOMStyleSheet.h"
 #include "nsIDOMStyleSheetList.h"
-#include "nsIDOMCSSStyleDeclaration.h"
 #include "nsIDOMCSSRule.h"
 #include "nsICSSRuleList.h"
 #include "nsIDOMRect.h"
 #include "nsIDOMRGBColor.h"
 #include "nsIDOMNSRGBAColor.h"
 #include "nsDOMCSSAttrDeclaration.h"
 
 // XBL related includes.
 #include "nsXBLService.h"
 #include "nsXBLBinding.h"
 #include "nsBindingManager.h"
 #include "nsIFrame.h"
 #include "nsIPresShell.h"
 #include "nsIDOMElement.h"
-#include "nsIDOMCSSStyleDeclaration.h"
 #include "nsStyleContext.h"
 #include "nsAutoPtr.h"
 #include "nsMemory.h"
 
 // Tranformiix
 #include "nsIDOMXPathEvaluator.h"
 #include "nsIXSLTProcessor.h"
 #include "nsIXSLTProcessorPrivate.h"
@@ -276,17 +274,16 @@
 #include "nsIDOMTimeRanges.h"
 #include "nsIDOMHTMLSourceElement.h"
 #include "nsIDOMHTMLVideoElement.h"
 #include "nsIDOMHTMLAudioElement.h"
 #if defined (MOZ_MEDIA)
 #include "nsIDOMMediaStream.h"
 #endif
 #include "nsIDOMProgressEvent.h"
-#include "nsIDOMCSS2Properties.h"
 #include "nsIDOMCSSCharsetRule.h"
 #include "nsIDOMCSSImportRule.h"
 #include "nsIDOMCSSMediaRule.h"
 #include "nsIDOMCSSFontFaceRule.h"
 #include "nsIDOMCSSMozDocumentRule.h"
 #include "nsIDOMCSSSupportsRule.h"
 #include "nsIDOMMozCSSKeyframeRule.h"
 #include "nsIDOMMozCSSKeyframesRule.h"
@@ -1027,18 +1024,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(CSSGroupRuleRuleList, nsCSSRuleListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MediaList, nsMediaListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(StyleSheetList, nsStyleSheetListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CSSStyleSheet, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(CSSStyleDeclaration, nsCSSStyleDeclSH,
-                           ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(ROCSSPrimitiveValue, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   // Range classes
   NS_DEFINE_CLASSINFO_DATA(Range, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(Selection, nsDOMGenericSH,
                            DEFAULT_SCRIPTABLE_FLAGS)
@@ -1522,18 +1517,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(USSDReceivedEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(DataErrorEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(CSSFontFaceRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(CSSFontFaceStyleDecl, nsCSSStyleDeclSH,
-                           ARRAY_SCRIPTABLE_FLAGS)
 
 #if defined(MOZ_MEDIA)
   NS_DEFINE_CLASSINFO_DATA(HTMLVideoElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(HTMLSourceElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MediaError, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -3034,21 +3027,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(StyleSheetList, nsIDOMStyleSheetList)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStyleSheetList)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(CSSStyleSheet, nsIDOMCSSStyleSheet)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSStyleSheet)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(CSSStyleDeclaration, nsIDOMCSSStyleDeclaration)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSStyleDeclaration)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSS2Properties)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ROCSSPrimitiveValue,
                                       nsIDOMCSSPrimitiveValue)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSPrimitiveValue)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(CSSValueList, nsIDOMCSSValueList)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSValueList)
   DOM_CLASSINFO_MAP_END
@@ -4119,21 +4107,16 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDataErrorEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEvent)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(CSSFontFaceRule, nsIDOMCSSFontFaceRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSFontFaceRule)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(CSSFontFaceStyleDecl,
-                                      nsIDOMCSSStyleDeclaration)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSStyleDeclaration)
-  DOM_CLASSINFO_MAP_END
-
 #if defined (MOZ_MEDIA)
   DOM_CLASSINFO_MAP_BEGIN(HTMLVideoElement, nsIDOMHTMLVideoElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLVideoElement)
     DOM_CLASSINFO_GENERIC_HTML_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(HTMLSourceElement, nsIDOMHTMLSourceElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLSourceElement)
@@ -10309,64 +10292,16 @@ nsISupports*
 nsCSSValueListSH::GetItemAt(nsISupports *aNative, uint32_t aIndex,
                             nsWrapperCache **aCache, nsresult *aResult)
 {
   nsDOMCSSValueList* list = nsDOMCSSValueList::FromSupports(aNative);
 
   return list->GetItemAt(aIndex);
 }
 
-
-// CSSStyleDeclaration helper
-
-NS_IMETHODIMP
-nsCSSStyleDeclSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
-                            JSObject *globalObj, JSObject **parentObj)
-{
-#ifdef DEBUG
-  nsWrapperCache* cache = nullptr;
-  CallQueryInterface(nativeObj, &cache);
-  MOZ_ASSERT(cache, "All CSS declarations must be wrappercached");
-#endif
-
-  nsICSSDeclaration *declaration = static_cast<nsICSSDeclaration*>(nativeObj);
-  nsINode *native_parent = declaration->GetParentObject();
-  if (!native_parent) {
-    return nsDOMClassInfo::PreCreate(nativeObj, cx, globalObj, parentObj);
-  }
-
-  nsresult rv =
-    WrapNativeParent(cx, globalObj, native_parent, parentObj);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_SUCCESS_ALLOW_SLIM_WRAPPERS;
-}
-
-nsresult
-nsCSSStyleDeclSH::GetStringAt(nsISupports *aNative, int32_t aIndex,
-                              nsAString& aResult)
-{
-  if (aIndex < 0) {
-    return NS_ERROR_DOM_INDEX_SIZE_ERR;
-  }
-
-  nsCOMPtr<nsIDOMCSSStyleDeclaration> style_decl(do_QueryInterface(aNative));
-
-  nsresult rv = style_decl->Item(uint32_t(aIndex), aResult);
-#ifdef DEBUG
-  if (DOMStringIsNull(aResult)) {
-    uint32_t length = 0;
-    style_decl->GetLength(&length);
-    NS_ASSERTION(uint32_t(aIndex) >= length, "Item should only return null for out-of-bounds access");
-  }
-#endif
-  return rv;
-}
-
-
 // CSSRuleList scriptable helper
 
 nsISupports*
 nsCSSRuleListSH::GetItemAt(nsISupports *aNative, uint32_t aIndex,
                            nsWrapperCache **aCache, nsresult *aResult)
 {
   nsICSSRuleList* list = static_cast<nsICSSRuleList*>(aNative);
 #ifdef DEBUG
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -1157,44 +1157,16 @@ protected:
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsCSSValueListSH(aData);
   }
 };
 
-
-// CSSStyleDeclaration helper
-
-class nsCSSStyleDeclSH : public nsStringArraySH
-{
-protected:
-  nsCSSStyleDeclSH(nsDOMClassInfoData* aData) : nsStringArraySH(aData)
-  {
-  }
-
-  virtual ~nsCSSStyleDeclSH()
-  {
-  }
-
-  virtual nsresult GetStringAt(nsISupports *aNative, int32_t aIndex,
-                               nsAString& aResult);
-
-public:
-  NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
-                       JSObject *globalObj, JSObject **parentObj);
-
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsCSSStyleDeclSH(aData);
-  }
-};
-
-
 // CSSRuleList helper
 
 class nsCSSRuleListSH : public nsArraySH
 {
 protected:
   nsCSSRuleListSH(nsDOMClassInfoData* aData) : nsArraySH(aData)
   {
   }
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -125,17 +125,16 @@ DOMCI_CLASS(CSSCharsetRule)
 DOMCI_CLASS(CSSImportRule)
 DOMCI_CLASS(CSSMediaRule)
 DOMCI_CLASS(CSSNameSpaceRule)
 DOMCI_CLASS(CSSRuleList)
 DOMCI_CLASS(CSSGroupRuleRuleList)
 DOMCI_CLASS(MediaList)
 DOMCI_CLASS(StyleSheetList)
 DOMCI_CLASS(CSSStyleSheet)
-DOMCI_CLASS(CSSStyleDeclaration)
 DOMCI_CLASS(ROCSSPrimitiveValue)
 
 // Range classes
 DOMCI_CLASS(Range)
 DOMCI_CLASS(Selection)
 
 // XUL classes
 #ifdef MOZ_XUL
@@ -409,17 +408,16 @@ DOMCI_CLASS(MozMobileConnection)
 #endif
 
 DOMCI_CLASS(USSDReceivedEvent)
 
 DOMCI_CLASS(DataErrorEvent)
 
 // @font-face in CSS
 DOMCI_CLASS(CSSFontFaceRule)
-DOMCI_CLASS(CSSFontFaceStyleDecl)
 
 #if defined(MOZ_MEDIA)
 // WhatWG Video Element
 DOMCI_CLASS(HTMLVideoElement)
 DOMCI_CLASS(HTMLSourceElement)
 DOMCI_CLASS(MediaError)
 DOMCI_CLASS(HTMLAudioElement)
 DOMCI_CLASS(TimeRanges)
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -300,20 +300,16 @@ nsWindowMemoryReporter::CollectReports(n
   WindowArray windows;
   windowsById->Enumerate(GetWindows, &windows);
 
   // Get the IDs of all the "ghost" windows.
   nsTHashtable<nsUint64HashKey> ghostWindows;
   ghostWindows.Init();
   CheckForGhostWindows(&ghostWindows);
 
-  nsCOMPtr<nsIEffectiveTLDService> tldService = do_GetService(
-    NS_EFFECTIVETLDSERVICE_CONTRACTID);
-  NS_ENSURE_STATE(tldService);
-
   WindowPaths windowPaths;
   windowPaths.Init();
 
   // Collect window memory usage.
   nsWindowSizes windowTotalSizes(NULL);
   for (uint32_t i = 0; i < windows.Length(); i++) {
     nsresult rv = CollectWindowReports(windows[i], &windowTotalSizes,
                                        &ghostWindows, &windowPaths,
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -224,22 +224,23 @@ CloseScoSocket()
     NS_WARNING("BluetoothScoManager is not available!");
     return;
   }
   sco->Disconnect();
 }
 
 BluetoothHfpManager::BluetoothHfpManager()
   : mCurrentCallIndex(0)
-  , mCurrentCallState(nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED)
   , mReceiveVgsFlag(false)
 {
   sCINDItems[CINDType::CALL].value = CallState::NO_CALL;
   sCINDItems[CINDType::CALLSETUP].value = CallSetupState::NO_CALLSETUP;
   sCINDItems[CINDType::CALLHELD].value = CallHeldState::NO_CALLHELD;
+
+  mCurrentCallStateArray.AppendElement((int)nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED);
 }
 
 bool
 BluetoothHfpManager::Init()
 {
   mSocketStatus = GetConnectionStatus();
 
   sHfpObserver = new BluetoothHfpManagerObserver();
@@ -326,17 +327,16 @@ BluetoothHfpManager::NotifySettings()
   if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED) {
     v = true;
   } else {
     v = false;
   }
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("address");
-  GetSocketAddr(mDevicePath);
   v = mDevicePath;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   if (!BroadcastSystemMessage(type, parameters)) {
     NS_WARNING("Failed to broadcast system message to dialer");
     return;
   }
 }
@@ -444,16 +444,17 @@ BluetoothHfpManager::HandleShutdown()
 
 // Virtual function of class SocketConsumer
 void
 BluetoothHfpManager::ReceiveSocketData(UnixSocketRawData* aMessage)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   const char* msg = (const char*)aMessage->mData;
+  int currentCallState = mCurrentCallStateArray[mCurrentCallIndex];
 
   // For more information, please refer to 4.34.1 "Bluetooth Defined AT
   // Capabilities" in Bluetooth hands-free profile 1.6
   if (!strncmp(msg, "AT+BRSF=", 8)) {
     SendCommand("+BRSF: ", 23);
     SendLine("OK");
   } else if (!strncmp(msg, "AT+CIND=?", 9)) {
     // Asking for CIND range
@@ -462,19 +463,43 @@ BluetoothHfpManager::ReceiveSocketData(U
   } else if (!strncmp(msg, "AT+CIND?", 8)) {
     // Asking for CIND value
     SendCommand("+CIND: ", 1);
     SendLine("OK");
   } else if (!strncmp(msg, "AT+CMER=", 8)) {
     // SLC establishment
     SendLine("OK");
   } else if (!strncmp(msg, "AT+CHLD=?", 9)) {
-    SendLine("+CHLD: (0,1,2,3)");
+    SendLine("+CHLD: (1,2)");
     SendLine("OK");
   } else if (!strncmp(msg, "AT+CHLD=", 8)) {
+    int length = strlen(msg) - 9;
+    nsAutoCString chldString(nsDependentCSubstring(msg+8, length));
+
+    nsresult rv;
+    int chld = chldString.ToInteger(&rv);
+    if (NS_FAILED(rv)) {
+      NS_WARNING("Failed to extract volume value from bluetooth headset!");
+    }
+
+    switch(chld) {
+      case 1:
+        // Releases active calls and accepts the other (held or waiting) call
+        NotifyDialer(NS_LITERAL_STRING("CHUP+ATA"));
+        break;
+      case 2:
+        // Places active calls on hold and accepts the other (held or waiting) call
+        NotifyDialer(NS_LITERAL_STRING("CHLD+ATA"));
+        break;
+      default:
+#ifdef DEBUG
+        NS_WARNING("Not handling chld value");
+#endif
+        break;
+    }
     SendLine("OK");
   } else if (!strncmp(msg, "AT+VGS=", 7)) {
     mReceiveVgsFlag = true;
 
     int length = strlen(msg) - 8;
     nsAutoCString vgsString(nsDependentCSubstring(msg+7, length));
 
     nsresult rv;
@@ -508,17 +533,17 @@ BluetoothHfpManager::ReceiveSocketData(U
   } else if (!strncmp(msg, "ATA", 3)) {
     NotifyDialer(NS_LITERAL_STRING("ATA"));
     SendLine("OK");
   } else if (!strncmp(msg, "AT+CHUP", 7)) {
     NotifyDialer(NS_LITERAL_STRING("CHUP"));
     SendLine("OK");
   } else if (!strncmp(msg, "AT+CKPD", 7)) {
     // For Headset
-    switch (mCurrentCallState) {
+    switch (currentCallState) {
       case nsIRadioInterfaceLayer::CALL_STATE_INCOMING:
         NotifyDialer(NS_LITERAL_STRING("ATA"));
         break;
       case nsIRadioInterfaceLayer::CALL_STATE_CONNECTED:
       case nsIRadioInterfaceLayer::CALL_STATE_DIALING:
       case nsIRadioInterfaceLayer::CALL_STATE_ALERTING:
         NotifyDialer(NS_LITERAL_STRING("CHUP"));
         break;
@@ -570,30 +595,23 @@ BluetoothHfpManager::Connect(const nsASt
 
   nsString serviceUuidStr;
   if (aIsHandsfree) {
     serviceUuidStr = NS_ConvertUTF8toUTF16(HANDSFREE_UUID);
   } else {
     serviceUuidStr = NS_ConvertUTF8toUTF16(HEADSET_UUID);
   }
 
-  nsCOMPtr<nsIRILContentHelper> ril =
-    do_GetService("@mozilla.org/ril/content-helper;1");
-  if (!ril) {
-    MOZ_ASSERT("Failed to get RIL Content Helper");
-  }
-  ril->EnumerateCalls(mListener->GetCallback());
-
   nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
 
   nsresult rv = bs->GetSocketViaService(aDevicePath,
                                         serviceUuidStr,
                                         BluetoothSocketType::RFCOMM,
                                         true,
-                                        false,
+                                        true,
                                         this,
                                         runnable);
 
   runnable.forget();
   return NS_FAILED(rv) ? false : true;
 }
 
 bool
@@ -612,17 +630,17 @@ BluetoothHfpManager::Listen()
   if (!bs) {
     NS_WARNING("BluetoothService not available!");
     return false;
   }
 
   nsresult rv = bs->ListenSocketViaService(BluetoothReservedChannels::HANDSFREE_AG,
                                            BluetoothSocketType::RFCOMM,
                                            true,
-                                           false,
+                                           true,
                                            this);
 
   mSocketStatus = GetConnectionStatus();
 
   return NS_FAILED(rv) ? false : true;
 }
 
 void
@@ -706,27 +724,35 @@ BluetoothHfpManager::SendCommand(const c
 }
 
 void
 BluetoothHfpManager::SetupCIND(int aCallIndex, int aCallState, bool aInitial)
 {
   nsRefPtr<nsRunnable> sendRingTask;
   nsString address;
 
+  while (aCallIndex >= mCurrentCallStateArray.Length()) {
+    mCurrentCallStateArray.AppendElement((int)nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED);
+  }
+
+  int currentCallState = mCurrentCallStateArray[aCallIndex];
+
   switch (aCallState) {
     case nsIRadioInterfaceLayer::CALL_STATE_INCOMING:
       sCINDItems[CINDType::CALLSETUP].value = CallSetupState::INCOMING;
       if (!aInitial) {
         SendCommand("+CIEV: ", CINDType::CALLSETUP);
       }
 
-      // Start sending RING indicator to HF
-      sStopSendingRingFlag = false;
-      MessageLoop::current()->PostTask(FROM_HERE,
-                                       new SendRingIndicatorTask());
+      if (!mCurrentCallIndex) {
+        // Start sending RING indicator to HF
+        sStopSendingRingFlag = false;
+        MessageLoop::current()->PostTask(FROM_HERE,
+                                         new SendRingIndicatorTask());
+      }
       break;
     case nsIRadioInterfaceLayer::CALL_STATE_DIALING:
       sCINDItems[CINDType::CALLSETUP].value = CallSetupState::OUTGOING;
       if (!aInitial) {
         SendCommand("+CIEV: ", CINDType::CALLSETUP);
 
         GetSocketAddr(address);
         OpenScoSocket(address);
@@ -734,27 +760,29 @@ BluetoothHfpManager::SetupCIND(int aCall
       break;
     case nsIRadioInterfaceLayer::CALL_STATE_ALERTING:
       sCINDItems[CINDType::CALLSETUP].value = CallSetupState::OUTGOING_ALERTING;
       if (!aInitial) {
         SendCommand("+CIEV: ", CINDType::CALLSETUP);
       }
       break;
     case nsIRadioInterfaceLayer::CALL_STATE_CONNECTED:
+      mCurrentCallIndex = aCallIndex;
       if (aInitial) {
         sCINDItems[CINDType::CALL].value = CallState::IN_PROGRESS;
         sCINDItems[CINDType::CALLSETUP].value = CallSetupState::NO_CALLSETUP;
       } else {
-        switch (mCurrentCallState) {
+        switch (currentCallState) {
           case nsIRadioInterfaceLayer::CALL_STATE_INCOMING:
             // Incoming call, no break
             sStopSendingRingFlag = true;
 
             GetSocketAddr(address);
             OpenScoSocket(address);
+          case nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED:
           case nsIRadioInterfaceLayer::CALL_STATE_ALERTING:
             // Outgoing call
             sCINDItems[CINDType::CALL].value = CallState::IN_PROGRESS;
             SendCommand("+CIEV: ", CINDType::CALL);
             sCINDItems[CINDType::CALLSETUP].value = CallSetupState::NO_CALLSETUP;
             SendCommand("+CIEV: ", CINDType::CALLSETUP);
             break;
           default:
@@ -762,69 +790,102 @@ BluetoothHfpManager::SetupCIND(int aCall
             NS_WARNING("Not handling state changed");
 #endif
             break;
         }
       }
       break;
     case nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED:
       if (!aInitial) {
-        switch (mCurrentCallState) {
+        switch (currentCallState) {
           case nsIRadioInterfaceLayer::CALL_STATE_INCOMING:
             // Incoming call, no break
             sStopSendingRingFlag = true;
           case nsIRadioInterfaceLayer::CALL_STATE_DIALING:
           case nsIRadioInterfaceLayer::CALL_STATE_ALERTING:
             // Outgoing call
             sCINDItems[CINDType::CALLSETUP].value = CallSetupState::NO_CALLSETUP;
             SendCommand("+CIEV: ", CINDType::CALLSETUP);
             break;
           case nsIRadioInterfaceLayer::CALL_STATE_CONNECTED:
             sCINDItems[CINDType::CALL].value = CallState::NO_CALL;
             SendCommand("+CIEV: ", CINDType::CALL);
             break;
+          case nsIRadioInterfaceLayer::CALL_STATE_HELD:
+            sCINDItems[CINDType::CALLHELD].value = NO_CALLHELD;
+            SendCommand("+CIEV: ", CINDType::CALLHELD);
           default:
 #ifdef DEBUG
             NS_WARNING("Not handling state changed");
 #endif
             break;
         }
-        CloseScoSocket();
+
+        if (aCallIndex == mCurrentCallIndex) {
+#ifdef DEBUG
+          NS_ASSERTION(mCurrentCallStateArray.Length() > aCallIndex,
+            "Call index out of bounds!");
+#endif
+          mCurrentCallStateArray[aCallIndex] = aCallState;
+
+          // Find the first non-disconnected call (like connected, held),
+          // and update mCurrentCallIndex
+          int c;
+          for (c = 1; c < mCurrentCallStateArray.Length(); c++) {
+            if (mCurrentCallStateArray[c] != nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED) {
+              mCurrentCallIndex = c;
+              break;
+            }
+          }
+
+          // There is no call 
+          if (c == mCurrentCallStateArray.Length()) {
+            mCurrentCallIndex = 0;
+            CloseScoSocket();
+          } 
+        }
       }
       break;
+    case nsIRadioInterfaceLayer::CALL_STATE_HELD:
+      sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
+
+      if (!aInitial) {
+        SendCommand("+CIEV: ", CINDType::CALLHELD);
+      }
+      
+      break;
     default:
 #ifdef DEBUG
       NS_WARNING("Not handling state changed");
       sCINDItems[CINDType::CALL].value = CallState::NO_CALL;
       sCINDItems[CINDType::CALLSETUP].value = CallSetupState::NO_CALLSETUP;
+      sCINDItems[CINDType::CALLHELD].value = CallHeldState::NO_CALLHELD;
 #endif
       break;
   }
 
-  mCurrentCallIndex = aCallIndex;
-  mCurrentCallState = aCallState;
+  mCurrentCallStateArray[aCallIndex] = aCallState;
 }
 
 /*
  * EnumerateCallState will be called for each call
  */
 void
 BluetoothHfpManager::EnumerateCallState(int aCallIndex, int aCallState,
                                         const char* aNumber, bool aIsActive)
 {
-  if (aIsActive &&
-      (sCINDItems[CINDType::CALLHELD].value == CallHeldState::ONHOLD_NOACTIVE)) {
-    sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
-  }
+  SetupCIND(aCallIndex, aCallState, true);
 
-  if (sCINDItems[CINDType::CALL].value || sCINDItems[CINDType::CALLSETUP].value) {
-    return;
+  if (sCINDItems[CINDType::CALL].value == CallState::IN_PROGRESS ||
+      sCINDItems[CINDType::CALLSETUP].value == CallSetupState::OUTGOING ||
+      sCINDItems[CINDType::CALLSETUP].value == CallSetupState::OUTGOING_ALERTING) {
+    nsString address;
+    GetSocketAddr(address);
+    OpenScoSocket(address);
   }
-
-  SetupCIND(aCallIndex, aCallState, true);
 }
 
 /*
  * CallStateChanged will be called whenever call status is changed, and it
  * also means we need to notify HS about the change. For more information, 
  * please refer to 4.13 ~ 4.15 in Bluetooth hands-free profile 1.6.
  */
 void
@@ -839,24 +900,24 @@ BluetoothHfpManager::CallStateChanged(in
 }
 
 void
 BluetoothHfpManager::OnConnectSuccess()
 {
   // Cache device path for NotifySettings() since we can't get socket address
   // when a headset disconnect with us
   GetSocketAddr(mDevicePath);
+  mSocketStatus = GetConnectionStatus();
 
-  if (mCurrentCallState == nsIRadioInterfaceLayer::CALL_STATE_CONNECTED ||
-      mCurrentCallState == nsIRadioInterfaceLayer::CALL_STATE_DIALING ||
-      mCurrentCallState == nsIRadioInterfaceLayer::CALL_STATE_ALERTING) {
-    OpenScoSocket(mDevicePath);
+  nsCOMPtr<nsIRILContentHelper> ril =
+    do_GetService("@mozilla.org/ril/content-helper;1");
+  if (!ril) {
+    MOZ_ASSERT("Failed to get RIL Content Helper");
   }
-
-  mSocketStatus = GetConnectionStatus();
+  ril->EnumerateCalls(mListener->GetCallback());
 
   NotifySettings();
 }
 
 void
 BluetoothHfpManager::OnConnectError()
 {
   CloseSocket();
--- a/dom/bluetooth/BluetoothHfpManager.h
+++ b/dom/bluetooth/BluetoothHfpManager.h
@@ -47,18 +47,18 @@ private:
   void NotifyDialer(const nsAString& aCommand);
   void NotifySettings();
   virtual void OnConnectSuccess() MOZ_OVERRIDE;
   virtual void OnConnectError() MOZ_OVERRIDE;
   virtual void OnDisconnect() MOZ_OVERRIDE;
 
   int mCurrentVgs;
   int mCurrentCallIndex;
-  int mCurrentCallState;
   bool mReceiveVgsFlag;
   nsString mDevicePath;
   enum mozilla::ipc::SocketConnectionStatus mSocketStatus;
+  nsTArray<int> mCurrentCallStateArray;
   nsAutoPtr<BluetoothRilListener> mListener;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/bluetooth/BluetoothOppManager.cpp
+++ b/dom/bluetooth/BluetoothOppManager.cpp
@@ -14,17 +14,23 @@
 #include "ObexBase.h"
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
+#include "nsIDOMFile.h"
+#include "nsIFile.h"
 #include "nsIInputStream.h"
+#include "nsIOutputStream.h"
+#include "nsNetUtil.h"
+
+#define TARGET_FOLDER "/sdcard/download/bluetooth/"
 
 USING_BLUETOOTH_NAMESPACE
 using namespace mozilla;
 using namespace mozilla::ipc;
 
 class BluetoothOppManagerObserver : public nsIObserver
 {
 public:
@@ -63,22 +69,30 @@ public:
   }
 };
 
 namespace {
 // Sending system message "bluetooth-opp-update-progress" every 50kb
 static const uint32_t kUpdateProgressBase = 50 * 1024;
 StaticRefPtr<BluetoothOppManager> sInstance;
 StaticRefPtr<BluetoothOppManagerObserver> sOppObserver;
-static nsCOMPtr<nsIInputStream> stream = nullptr;
+
+/*
+ * FIXME / Bug 806749
+ *
+ * Currently Bluetooth*Manager inherits mozilla::ipc::UnixSocketConsumer,
+ * which means that each Bluetooth*Manager can handle only one socket
+ * connection at a time. We need to support concurrent multiple socket
+ * connections, and then we will be able to have multiple file transferring
+ * sessions at a time.
+ */
 static uint32_t sSentFileLength = 0;
 static nsString sFileName;
 static uint32_t sFileLength = 0;
 static nsString sContentType;
-static int sUpdateProgressCounter = 0;
 static bool sInShutdown = false;
 }
 
 NS_IMETHODIMP
 BluetoothOppManagerObserver::Observe(nsISupports* aSubject,
                                      const char* aTopic,
                                      const PRUnichar* aData)
 {
@@ -90,48 +104,34 @@ BluetoothOppManagerObserver::Observe(nsI
 
   MOZ_ASSERT(false, "BluetoothOppManager got unexpected topic!");
   return NS_ERROR_UNEXPECTED;
 }
 
 class ReadFileTask : public nsRunnable
 {
 public:
-  ReadFileTask(nsIDOMBlob* aBlob) : mBlob(aBlob)
+  ReadFileTask(nsIInputStream* aInputStream) : mInputStream(aInputStream)
   {
     MOZ_ASSERT(NS_IsMainThread());
   }
 
   NS_IMETHOD Run()
   {
-    if (NS_IsMainThread()) {
-      NS_WARNING("Can't read file from main thread");
-      return NS_ERROR_FAILURE;
-    }
-
-    nsresult rv;
-
-    if (stream == nullptr) {
-      rv = mBlob->GetInternalStream(getter_AddRefs(stream));
-      if (NS_FAILED(rv)) {
-        NS_WARNING("Can't get internal stream of blob");
-        return NS_ERROR_FAILURE;
-      }
-    }
+    MOZ_ASSERT(!NS_IsMainThread());
 
     /*
      * 255 is the Minimum OBEX Packet Length (See section 3.3.1.4,
      * IrOBEX ver 1.2)
      */
     char buf[255];
     uint32_t numRead;
-    int offset = 0;
 
     // function inputstream->Read() only works on non-main thread
-    rv = stream->Read(buf, sizeof(buf), &numRead);
+    nsresult rv = mInputStream->Read(buf, sizeof(buf), &numRead);
     if (NS_FAILED(rv)) {
       // Needs error handling here
       return NS_ERROR_FAILURE;
     }
 
     if (numRead > 0) {
       if (sSentFileLength + numRead >= sFileLength) {
         sInstance->SendPutRequest((uint8_t*)buf, numRead, true);
@@ -141,38 +141,32 @@ public:
 
       sSentFileLength += numRead;
     }
 
     return NS_OK;
   };
 
 private:
-  nsCOMPtr<nsIDOMBlob> mBlob;
+  nsCOMPtr<nsIInputStream> mInputStream;
 };
 
 BluetoothOppManager::BluetoothOppManager() : mConnected(false)
                                            , mConnectionId(1)
                                            , mLastCommand(0)
-                                           , mBlob(nullptr)
                                            , mRemoteObexVersion(0)
                                            , mRemoteConnectionFlags(0)
                                            , mRemoteMaxPacketLength(0)
                                            , mAbortFlag(false)
-                                           , mReadFileThread(nullptr)
                                            , mPacketLeftLength(0)
                                            , mReceiving(false)
                                            , mPutFinal(false)
                                            , mWaitingForConfirmationFlag(false)
 {
-  // FIXME / Bug 800249:
-  //   mConnectedDeviceAddress is Bluetooth address of connected device,
-  //   we will be able to get this value after bug 800249 lands. For now,
-  //   just assign a fake value to it.
-  mConnectedDeviceAddress.AssignASCII("00:00:00:00:00:00");
+  mConnectedDeviceAddress.AssignLiteral("00:00:00:00:00:00");
 }
 
 BluetoothOppManager::~BluetoothOppManager()
 {
 }
 
 //static
 BluetoothOppManager*
@@ -203,17 +197,17 @@ BluetoothOppManager::Connect(const nsASt
     NS_ConvertUTF8toUTF16(mozilla::dom::bluetooth::BluetoothServiceUuidStr::ObjectPush);
 
   nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
 
   nsresult rv = bs->GetSocketViaService(aDeviceObjectPath,
                                         serviceUuidStr,
                                         BluetoothSocketType::RFCOMM,
                                         true,
-                                        false,
+                                        true,
                                         this,
                                         runnable);
 
   runnable.forget();
   return NS_FAILED(rv) ? false : true;
 }
 
 void
@@ -243,17 +237,17 @@ BluetoothOppManager::Listen()
   if (!bs) {
     NS_WARNING("BluetoothService not available!");
     return false;
   }
 
   nsresult rv = bs->ListenSocketViaService(BluetoothReservedChannels::OPUSH,
                                            BluetoothSocketType::RFCOMM,
                                            true,
-                                           false,
+                                           true,
                                            this);
   return NS_FAILED(rv) ? false : true;
 }
 
 bool
 BluetoothOppManager::SendFile(BlobParent* aActor,
                               BluetoothReplyRunnable* aRunnable)
 {
@@ -297,23 +291,67 @@ BluetoothOppManager::ConfirmReceivingFil
   }
 
   NS_ASSERTION(mPacketLeftLength == 0,
                "Should not be in the middle of receiving a PUT packet.");
 
   mWaitingForConfirmationFlag = false;
   ReplyToPut(mPutFinal, aConfirm);
 
+  if (aConfirm) {
+    StartFileTransfer(mConnectedDeviceAddress, true,
+                      sFileName, sFileLength, sContentType);
+  }
+
   if (mPutFinal || !aConfirm) {
     mReceiving = false;
     FileTransferComplete(mConnectedDeviceAddress, aConfirm, true, sFileName,
                          sSentFileLength, sContentType);
   }
 }
 
+void
+BluetoothOppManager::AfterOppConnected()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  mConnected = true;
+  mUpdateProgressCounter = 1;
+  sSentFileLength = 0;
+  mAbortFlag = false;
+}
+
+void
+BluetoothOppManager::AfterOppDisconnected()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  mConnected = false;
+  mReceiving = false;
+  mLastCommand = 0;
+  mBlob = nullptr;
+
+  if (mInputStream) {
+    mInputStream->Close();
+    mInputStream = nullptr;
+  }
+
+  if (mOutputStream) {
+    mOutputStream->Close();
+    mOutputStream = nullptr;
+  }
+
+  if (mReadFileThread) {
+    mReadFileThread->Shutdown();
+    mReadFileThread = nullptr;
+  }
+
+  mConnectedDeviceAddress.AssignLiteral("00:00:00:00:00:00");
+}
+
 // Virtual function of class SocketConsumer
 void
 BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
 {
   uint8_t opCode;
   int packetLength;
   int receivedLength = aMessage->mSize;
 
@@ -322,17 +360,17 @@ BluetoothOppManager::ReceiveSocketData(U
     packetLength = mPacketLeftLength;
   } else {
     opCode = aMessage->mData[0];
     packetLength = (((int)aMessage->mData[1]) << 8) | aMessage->mData[2];
   }
 
   if (mLastCommand == ObexRequestCode::Connect) {
     if (opCode == ObexResponseCode::Success) {
-      mConnected = true;
+      AfterOppConnected();
 
       // Keep remote information
       mRemoteObexVersion = aMessage->mData[3];
       mRemoteConnectionFlags = aMessage->mData[4];
       mRemoteMaxPacketLength =
         (((int)(aMessage->mData[5]) << 8) | aMessage->mData[6]);
 
       if (mBlob) {
@@ -377,113 +415,187 @@ BluetoothOppManager::ReceiveSocketData(U
         sFileLength = fileLength;
 
         if (NS_FAILED(NS_NewThread(getter_AddRefs(mReadFileThread)))) {
           NS_WARNING("Can't create thread");
           SendDisconnectRequest();
           return;
         }
 
-        sUpdateProgressCounter = 1;
-        sSentFileLength = 0;
-        mAbortFlag = false;
         sInstance->SendPutHeaderRequest(sFileName, sFileLength);
         StartFileTransfer(mConnectedDeviceAddress, false,
                           sFileName, sFileLength, sContentType);
       }
     }
   } else if (mLastCommand == ObexRequestCode::Disconnect) {
     if (opCode != ObexResponseCode::Success) {
       // FIXME: Needs error handling here
       NS_WARNING("[OPP] Disconnect failed");
-    } else {
-      mConnected = false;
-      mReceiving = false;
-      mLastCommand = 0;
-      mBlob = nullptr;
-      mReadFileThread = nullptr;
     }
+
+    AfterOppDisconnected();
   } else if (mLastCommand == ObexRequestCode::Put) {
     if (opCode != ObexResponseCode::Continue) {
       // FIXME: Needs error handling here
       NS_WARNING("[OPP] Put failed");
-    } else {
-      if (mAbortFlag || mReadFileThread == nullptr) {
-        SendAbortRequest();
-      } else {
-        if (kUpdateProgressBase * sUpdateProgressCounter < sSentFileLength) {
-          UpdateProgress(mConnectedDeviceAddress, false,
-                         sSentFileLength, sFileLength);
-          ++sUpdateProgressCounter;
-        }
+      return;
+    }
+
+    if (mAbortFlag || mReadFileThread) {
+      SendAbortRequest();
+      return;
+    }
 
-        nsRefPtr<ReadFileTask> task = new ReadFileTask(mBlob);
+    if (kUpdateProgressBase * mUpdateProgressCounter < sSentFileLength) {
+      UpdateProgress(mConnectedDeviceAddress, false,
+                     sSentFileLength, sFileLength);
+      mUpdateProgressCounter = sSentFileLength / kUpdateProgressBase + 1;
+    }
 
-        if (NS_FAILED(mReadFileThread->Dispatch(task, NS_DISPATCH_NORMAL))) {
-          NS_WARNING("Cannot dispatch ring task!");
-        }
+    if (mInputStream) {
+      nsresult rv = mBlob->GetInternalStream(getter_AddRefs(mInputStream));
+      if (NS_FAILED(rv)) {
+        NS_WARNING("Can't get internal stream of blob");
+        return;
       }
     }
+
+    nsRefPtr<ReadFileTask> task = new ReadFileTask(mInputStream);
+    if (NS_FAILED(mReadFileThread->Dispatch(task, NS_DISPATCH_NORMAL))) {
+      NS_WARNING("Cannot dispatch ring task!");
+    }
   } else if (mLastCommand == ObexRequestCode::PutFinal) {
     if (opCode != ObexResponseCode::Success) {
       // FIXME: Needs error handling here
       NS_WARNING("[OPP] PutFinal failed");
-    } else {
-      FileTransferComplete(mConnectedDeviceAddress, true, false, sFileName,
-                           sSentFileLength, sContentType);
-      SendDisconnectRequest();
+      return;
     }
+
+    FileTransferComplete(mConnectedDeviceAddress, true, false, sFileName,
+                         sSentFileLength, sContentType);
+    SendDisconnectRequest();
   } else if (mLastCommand == ObexRequestCode::Abort) {
     if (opCode != ObexResponseCode::Success) {
       NS_WARNING("[OPP] Abort failed");
     }
 
     FileTransferComplete(mConnectedDeviceAddress, false, false, sFileName,
                          sSentFileLength, sContentType);
     SendDisconnectRequest();
   } else {
     // Remote request or unknown mLastCommand
     ObexHeaderSet pktHeaders(opCode);
 
     if (opCode == ObexRequestCode::Connect) {
-      ParseHeaders(&aMessage->mData[7], receivedLength - 7, &pktHeaders);
+      // Section 3.3.1 "Connect", IrOBEX 1.2
+      // [opcode:1][length:2][version:1][flags:1][MaxPktSizeWeCanReceive:2]
+      // [Headers:var]
+      ParseHeadersAndFindBody(&aMessage->mData[7],
+                              receivedLength - 7,
+                              &pktHeaders);
       ReplyToConnect();
+      AfterOppConnected();
     } else if (opCode == ObexRequestCode::Disconnect) {
-      ParseHeaders(&aMessage->mData[3], receivedLength - 3, &pktHeaders);
+      // Section 3.3.2 "Disconnect", IrOBEX 1.2
+      // [opcode:1][length:2][Headers:var]
+      ParseHeadersAndFindBody(&aMessage->mData[3],
+                              receivedLength - 3,
+                              &pktHeaders);
       ReplyToDisconnect();
+      AfterOppDisconnected();
     } else if (opCode == ObexRequestCode::Put ||
                opCode == ObexRequestCode::PutFinal) {
+      // Section 3.3.3 "Put", IrOBEX 1.2
+      // [opcode:1][length:2][Headers:var]
+      int headerStartIndex = 3;
+
       if (!mReceiving) {
+        nsString path;
+        path.AssignLiteral(TARGET_FOLDER);
+
         MOZ_ASSERT(mPacketLeftLength == 0);
-        ParseHeaders(&aMessage->mData[3], receivedLength - 3, &pktHeaders);
+        ParseHeadersAndFindBody(&aMessage->mData[headerStartIndex],
+                                receivedLength - headerStartIndex,
+                                &pktHeaders);
 
         pktHeaders.GetName(sFileName);
         pktHeaders.GetContentType(sContentType);
         pktHeaders.GetLength(&sFileLength);
 
+        path += sFileName;
+
+        nsCOMPtr<nsIFile> f;
+        nsresult rv = NS_NewLocalFile(path, false, getter_AddRefs(f));
+        if (NS_FAILED(rv)) {
+          NS_WARNING("Couldn't new a local file");
+        }
+
+        rv = f->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 00644);
+        if (NS_FAILED(rv)) {
+          NS_WARNING("Couldn't create the file");
+        }
+
+        NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), f);
+        if (!mOutputStream) {
+          NS_WARNING("Couldn't new an output stream");
+        }
+
         mReceiving = true;
         mWaitingForConfirmationFlag = true;
       }
 
       /*
        * A PUT request from remote devices may be divided into multiple parts.
        * In other words, one request may need to be received multiple times,
        * so here we keep a variable mPacketLeftLength to indicate if current
        * PUT request is done.
        */
       mPutFinal = (opCode == ObexRequestCode::PutFinal);
 
+      uint32_t wrote = 0;
       if (mPacketLeftLength == 0) {
-        NS_ASSERTION(mPacketLeftLength >= receivedLength,
+        NS_ASSERTION(packetLength >= receivedLength,
                      "Invalid packet length");
         mPacketLeftLength = packetLength - receivedLength;
+
+        int headerBodyOffset =
+          ParseHeadersAndFindBody(&aMessage->mData[headerStartIndex],
+                                  receivedLength - headerStartIndex,
+                                  &pktHeaders);
+
+        if (headerBodyOffset != -1) {
+          /*
+           * Adding by 3 is because the format of a header is like:
+           *     [HeaderId:1 (BODY)][HeaderLength:2][Data:n]
+           * and headerStartIndex + headerBodyOffset points to HeaderId,
+           * so adding 3 is to point to the beginning of data.
+           *
+           */
+          int fileBodyIndex = headerStartIndex + headerBodyOffset + 3;
+
+          mOutputStream->Write((char*)&aMessage->mData[fileBodyIndex],
+                               receivedLength - fileBodyIndex, &wrote);
+          NS_ASSERTION(receivedLength - fileBodyIndex == wrote,
+                       "Writing to the file failed");
+        }
       } else {
         NS_ASSERTION(mPacketLeftLength >= receivedLength,
                      "Invalid packet length");
         mPacketLeftLength -= receivedLength;
+
+        mOutputStream->Write((char*)&aMessage->mData[0], receivedLength, &wrote);
+        NS_ASSERTION(receivedLength == wrote, "Writing to the file failed");
+      }
+
+      sSentFileLength += wrote;
+      if (sSentFileLength > kUpdateProgressBase * mUpdateProgressCounter &&
+          !mWaitingForConfirmationFlag) {
+        UpdateProgress(mConnectedDeviceAddress, true,
+                       sSentFileLength, sFileLength);
+        mUpdateProgressCounter = sSentFileLength / kUpdateProgressBase + 1;
       }
 
       if (mPacketLeftLength == 0) {
         if (mWaitingForConfirmationFlag) {
           ReceivingFileConfirmation(mConnectedDeviceAddress, sFileName,
                                     sFileLength, sContentType);
         } else {
           ReplyToPut(mPutFinal, true);
@@ -557,17 +669,16 @@ BluetoothOppManager::SendPutHeaderReques
   delete [] req;
 }
 
 void
 BluetoothOppManager::SendPutRequest(uint8_t* aFileBody,
                                     int aFileBodyLength,
                                     bool aFinal)
 {
-  int sentFileBodyLength = 0;
   int index = 3;
   int packetLeftSpace = mRemoteMaxPacketLength - index - 3;
 
   if (!mConnected) return;
   if (aFileBodyLength > packetLeftSpace) {
     NS_WARNING("Not allowed such a small MaxPacketLength value");
     return;
   }
@@ -841,19 +952,26 @@ BluetoothOppManager::ReceivingFileConfir
     NS_WARNING("Failed to broadcast [bluetooth-opp-receiving-file-confirmation]");
     return;
   }
 }
 
 void
 BluetoothOppManager::OnConnectSuccess()
 {
+  // Cache device address since we can't get socket address when a remote
+  // device disconnect with us.
+  GetSocketAddr(mConnectedDeviceAddress);
 }
 
 void
 BluetoothOppManager::OnConnectError()
 {
 }
 
 void
 BluetoothOppManager::OnDisconnect()
 {
+  // It is valid for a bluetooth device which is transfering file via OPP
+  // closing socket without sending OBEX disconnect request first. So we
+  // call AfterOppDisconnected here to ensure all variables will be cleaned.
+  AfterOppDisconnected();
 }
--- a/dom/bluetooth/BluetoothOppManager.h
+++ b/dom/bluetooth/BluetoothOppManager.h
@@ -7,16 +7,19 @@
 #ifndef mozilla_dom_bluetooth_bluetoothoppmanager_h__
 #define mozilla_dom_bluetooth_bluetoothoppmanager_h__
 
 #include "BluetoothCommon.h"
 #include "mozilla/dom/ipc/Blob.h"
 #include "mozilla/ipc/UnixSocket.h"
 #include "nsIDOMFile.h"
 
+class nsIOutputStream;
+class nsIInputStream;
+
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothReplyRunnable;
 
 class BluetoothOppManager : public mozilla::ipc::UnixSocketConsumer
 {
 public:
   /*
@@ -80,32 +83,37 @@ private:
                       uint32_t aFileLength);
   void ReceivingFileConfirmation(const nsString& aAddress,
                                  const nsString& aFileName,
                                  uint32_t aFileLength,
                                  const nsString& aContentType);
   void ReplyToConnect();
   void ReplyToDisconnect();
   void ReplyToPut(bool aFinal, bool aContinue);
+  void AfterOppConnected();
+  void AfterOppDisconnected();
   virtual void OnConnectSuccess() MOZ_OVERRIDE;
   virtual void OnConnectError() MOZ_OVERRIDE;
   virtual void OnDisconnect() MOZ_OVERRIDE;
 
   bool mConnected;
   int mConnectionId;
   int mLastCommand;
   uint8_t mRemoteObexVersion;
   uint8_t mRemoteConnectionFlags;
   int mRemoteMaxPacketLength;
   bool mAbortFlag;
   int mPacketLeftLength;
   nsString mConnectedDeviceAddress;
   bool mReceiving;
   bool mPutFinal;
   bool mWaitingForConfirmationFlag;
+  int mUpdateProgressCounter;
 
   nsCOMPtr<nsIDOMBlob> mBlob;
   nsCOMPtr<nsIThread> mReadFileThread;
+  nsCOMPtr<nsIOutputStream> mOutputStream;
+  nsCOMPtr<nsIInputStream> mInputStream;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/bluetooth/BluetoothScoManager.cpp
+++ b/dom/bluetooth/BluetoothScoManager.cpp
@@ -239,17 +239,17 @@ BluetoothScoManager::Listen()
   if (!bs) {
     NS_WARNING("BluetoothService not available!");
     return false;
   }
 
   nsresult rv = bs->ListenSocketViaService(-1,
                                            BluetoothSocketType::SCO,
                                            true,
-                                           false,
+                                           true,
                                            this);
 
   mSocketStatus = GetConnectionStatus();
 
   return NS_FAILED(rv) ? false : true;
 }
 
 void
--- a/dom/bluetooth/BluetoothUnixSocketConnector.cpp
+++ b/dom/bluetooth/BluetoothUnixSocketConnector.cpp
@@ -83,22 +83,20 @@ BluetoothUnixSocketConnector::SetUp(int 
 {
   int lm = 0;
   int sndbuf;
   /* kernel does not yet support LM for SCO */
   switch (mType) {
   case BluetoothSocketType::RFCOMM:
     lm |= mAuth ? RFCOMM_LM_AUTH : 0;
     lm |= mEncrypt ? RFCOMM_LM_ENCRYPT : 0;
-    lm |= (mAuth && mEncrypt) ? RFCOMM_LM_SECURE : 0;
     break;
   case BluetoothSocketType::L2CAP:
     lm |= mAuth ? L2CAP_LM_AUTH : 0;
     lm |= mEncrypt ? L2CAP_LM_ENCRYPT : 0;
-    lm |= (mAuth && mEncrypt) ? L2CAP_LM_SECURE : 0;
     break;
   }
 
   if (lm) {
     if (setsockopt(aFd, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm))) {
       NS_WARNING("setsockopt(RFCOMM_LM) failed, throwing");
       return false;
     }
--- a/dom/bluetooth/ObexBase.cpp
+++ b/dom/bluetooth/ObexBase.cpp
@@ -63,31 +63,42 @@ AppendHeaderConnectionId(uint8_t* retBuf
 void
 SetObexPacketInfo(uint8_t* retBuf, uint8_t opcode, int packetLength)
 {
   retBuf[0] = opcode;
   retBuf[1] = (packetLength & 0xFF00) >> 8;
   retBuf[2] = packetLength & 0x00FF;
 }
 
-void
-ParseHeaders(uint8_t* buf, int totalLength, ObexHeaderSet* retHandlerSet)
+int
+ParseHeadersAndFindBody(uint8_t* aHeaderStart,
+                        int aTotalLength,
+                        ObexHeaderSet* aRetHandlerSet)
 {
-  uint8_t* ptr = buf;
+  uint8_t* ptr = aHeaderStart;
+
+  while (ptr - aHeaderStart < aTotalLength) {
+    ObexHeaderId headerId = (ObexHeaderId)*ptr;
 
-  while (ptr - buf < totalLength) {
-    ObexHeaderId headerId = (ObexHeaderId)*ptr++;
+    if (headerId == ObexHeaderId::Body ||
+        headerId == ObexHeaderId::EndOfBody) {
+      return ptr - aHeaderStart;
+    }
+
+    ++ptr;
+
     int contentLength = 0;
     uint8_t highByte, lowByte;
 
     // Defined in 2.1 OBEX Headers, IrOBEX 1.2
     switch (headerId >> 6)
     {
       case 0x00:
-        // NULL terminated Unicode text, length prefixed with 2 byte unsigned integer.
+        // NULL terminated Unicode text, length prefixed with 2-byte
+        // unsigned integer.
       case 0x01:
         // byte sequence, length prefixed with 2 byte unsigned integer.
         highByte = *ptr++;
         lowByte = *ptr++;
         contentLength = (((int)highByte << 8) | lowByte) - 3;
         break;
 
       case 0x02:
@@ -96,23 +107,19 @@ ParseHeaders(uint8_t* buf, int totalLeng
         break;
 
       case 0x03:
         // 4 byte quantity
         contentLength = 4;
         break;
     }
 
-    // FIXME: This case should be happened when we are receiving header 'Body'
-    // (file body). I will handle this in another bug.
-    if (contentLength + (ptr - buf) > totalLength) {
-      break;
-    }
-
     uint8_t* content = new uint8_t[contentLength];
     memcpy(content, ptr, contentLength);
-    retHandlerSet->AddHeader(new ObexHeader(headerId, contentLength, content));
+    aRetHandlerSet->AddHeader(new ObexHeader(headerId, contentLength, content));
 
     ptr += contentLength;
   }
+
+  return -1;
 }
 
 END_BLUETOOTH_NAMESPACE
--- a/dom/bluetooth/ObexBase.h
+++ b/dom/bluetooth/ObexBase.h
@@ -137,16 +137,18 @@ public:
 
   void AddHeader(ObexHeader* aHeader)
   {
     mHeaders.AppendElement(aHeader);
   }
 
   void GetName(nsString& aRetName)
   {
+    aRetName.Truncate();
+
     int length = mHeaders.Length();
 
     for (int i = 0; i < length; ++i) {
       if (mHeaders[i]->mId == ObexHeaderId::Name) {
         uint8_t* ptr = mHeaders[i]->mData.get();
         int nameLength = mHeaders[i]->mDataLength / 2;
 
         for (int j = 0; j < nameLength; ++j) {
@@ -156,16 +158,18 @@ public:
 
         break;
       }
     }
   }
 
   void GetContentType(nsString& aRetContentType)
   {
+    aRetContentType.Truncate();
+
     int length = mHeaders.Length();
 
     for (int i = 0; i < length; ++i) {
       if (mHeaders[i]->mId == ObexHeaderId::Type) {
         uint8_t* ptr = mHeaders[i]->mData.get();
         aRetContentType.AssignASCII((const char*)ptr);
         break;
       }
@@ -191,13 +195,15 @@ public:
   }
 };
 
 int AppendHeaderName(uint8_t* retBuf, const char* name, int length);
 int AppendHeaderBody(uint8_t* retBuf, uint8_t* data, int length);
 int AppendHeaderLength(uint8_t* retBuf, int objectLength);
 int AppendHeaderConnectionId(uint8_t* retBuf, int connectionId);
 void SetObexPacketInfo(uint8_t* retBuf, uint8_t opcode, int packetLength);
-void ParseHeaders(uint8_t* buf, int totalLength, ObexHeaderSet* retHanderSet);
+int ParseHeadersAndFindBody(uint8_t* aHeaderStart,
+                            int aTotalLength,
+                            ObexHeaderSet* aRetHanderSet);
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/interfaces/css/Makefile.in
+++ b/dom/interfaces/css/Makefile.in
@@ -21,17 +21,16 @@ SDK_XPIDLSRCS = 				\
 	nsIDOMCSSStyleDeclaration.idl		\
 	nsIDOMCSSStyleSheet.idl			\
 	nsIDOMCSSValue.idl			\
 	nsIDOMCSSValueList.idl			\
 	nsIDOMElementCSSInlineStyle.idl		\
 	$(NULL)
 
 XPIDLSRCS =					\
-	nsIDOMCSS2Properties.idl		\
 	nsIDOMCSSCharsetRule.idl		\
 	nsIDOMCSSFontFaceRule.idl		\
 	nsIDOMCSSImportRule.idl			\
 	nsIDOMCSSMediaRule.idl			\
 	nsIDOMCSSMozDocumentRule.idl		\
 	nsIDOMCSSSupportsRule.idl		\
 	nsIDOMMozCSSKeyframeRule.idl		\
 	nsIDOMMozCSSKeyframesRule.idl		\
deleted file mode 100644
--- a/dom/interfaces/css/nsIDOMCSS2Properties.idl
+++ /dev/null
@@ -1,832 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "domstubs.idl"
-
-/**
- * The nsIDOMCSS2Properties interface is a datatype for additional
- * reflection of data already provided in nsIDOMCSSStyleDeclaration in
- * the Document Object Model.
- *
- * For more information on this interface please see
- * http://www.w3.org/TR/DOM-Level-2-Style
- */
-
-[builtinclass, scriptable, uuid(df3491fd-2243-427f-bd93-b0dd3c3e7834)]
-interface nsIDOMCSS2Properties : nsISupports
-{
-           attribute DOMString        background;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        backgroundAttachment;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        backgroundColor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        backgroundImage;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        backgroundPosition;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        backgroundRepeat;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        border;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderCollapse;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderColor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderSpacing;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderStyle;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderTop;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderRight;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderBottom;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderLeft;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderTopColor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderRightColor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderBottomColor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderLeftColor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderTopStyle;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderRightStyle;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderBottomStyle;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderLeftStyle;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderTopWidth;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderRightWidth;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderBottomWidth;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderLeftWidth;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderWidth;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderRadius;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderTopLeftRadius;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderTopRightRadius;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderBottomLeftRadius;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderBottomRightRadius;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        bottom;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        boxShadow;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        captionSide;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        clear;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        clip;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        color;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        content;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        counterIncrement;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        counterReset;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        cursor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        direction;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        display;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        emptyCells;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        cssFloat;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        font;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        fontFamily;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        fontSize;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        fontSizeAdjust;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        fontStretch;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        fontStyle;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        fontVariant;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        fontWeight;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        height;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        left;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        letterSpacing;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        lineHeight;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        listStyle;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        listStyleImage;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        listStylePosition;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        listStyleType;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        margin;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        marginTop;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        marginRight;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        marginBottom;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        marginLeft;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        markerOffset;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        marks;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        maxHeight;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        maxWidth;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        minHeight;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        minWidth;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        orphans;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        outline;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        outlineColor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        outlineStyle;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        outlineWidth;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        overflow;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        padding;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        paddingTop;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        paddingRight;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        paddingBottom;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        paddingLeft;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        page;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        pageBreakAfter;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        pageBreakBefore;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        pageBreakInside;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        position;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        quotes;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        right;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        size;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        tableLayout;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        textAlign;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        textDecoration;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        textIndent;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        textOverflow;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        textShadow;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        textTransform;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        top;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        unicodeBidi;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        verticalAlign;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        visibility;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        whiteSpace;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        widows;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        width;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        wordSpacing;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        zIndex;
-                                        // raises(DOMException) on setting
-
-           /* SVG CSS properties */
-           attribute DOMString        clipPath;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        clipRule;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        colorInterpolation;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        colorInterpolationFilters;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        dominantBaseline;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        fill;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        fillOpacity;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        fillRule;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        filter;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        floodColor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        floodOpacity;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        imageRendering;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        lightingColor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        marker;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        markerEnd;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        markerMid;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        markerStart;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        mask;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        shapeRendering;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        stopColor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        stopOpacity;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        stroke;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        strokeDasharray;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        strokeDashoffset;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        strokeLinecap;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        strokeLinejoin;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        strokeMiterlimit;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        strokeOpacity;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        strokeWidth;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        textAnchor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        textRendering;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        vectorEffect;
-                                        // raises(DOMException) on setting
-
-           /* Non-DOM 2 extensions */
-
-           /* Mozilla extension CSS properties */
-           attribute DOMString        MozAppearance;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        backgroundClip;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBackgroundInlinePolicy;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        backgroundOrigin;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBinding;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBorderBottomColors;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBorderLeftColors;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBorderRightColors;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBorderTopColors;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBoxAlign;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBoxDirection;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBoxFlex;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBoxOrient;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBoxOrdinalGroup;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBoxPack;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBoxSizing;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozColumnCount;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozColumnWidth;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozColumnFill;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozColumnGap;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozFloatEdge;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozFontFeatureSettings;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozFontLanguageOverride;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozForceBrokenImageIcon;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozImageRegion;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozMarginEnd;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozMarginStart;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozOrient;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozOutlineRadius;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozOutlineRadiusTopleft;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozOutlineRadiusTopright;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozOutlineRadiusBottomleft;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozOutlineRadiusBottomright;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozPaddingEnd;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozPaddingStart;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozUserFocus;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozUserInput;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozUserModify;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozUserSelect;
-                                        // raises(DOMException) on setting
-
-           /* CSS3 properties */
-           attribute DOMString        opacity;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        outlineOffset;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTextAlignLast;
-                                        // raises(DOMException) on setting
-
-           /* Mozilla extensions */
-           attribute DOMString        overflowX;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        overflowY;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        imeMode;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBorderEnd;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBorderEndColor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBorderEndStyle;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBorderEndWidth;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBorderStart;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBorderStartColor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBorderStartStyle;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBorderStartWidth;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozStackSizing;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderImage;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozColumns;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozColumnRule;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozColumnRuleWidth;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozColumnRuleStyle;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozColumnRuleColor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        wordBreak;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        wordWrap;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozHyphens;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        transform;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        transformOrigin;
-                                        // raises(DOMException) on setting 
-
-           attribute DOMString        perspective;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        perspectiveOrigin;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        backfaceVisibility;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        transformStyle;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTransform;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTransformOrigin;
-                                        // raises(DOMException) on setting 
-
-           attribute DOMString        MozPerspective;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozPerspectiveOrigin;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBackfaceVisibility;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTransformStyle;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozWindowShadow;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        backgroundSize;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTextBlink;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTextDecorationColor;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTextDecorationLine;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTextDecorationStyle;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        transitionProperty;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        transitionDuration;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        transitionDelay;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        transitionTimingFunction;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        transition;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTransitionProperty;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTransitionDuration;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTransitionDelay;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTransitionTimingFunction;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTransition;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        pointerEvents;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTabSize;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        resize;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        animationName;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        animationDuration;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        animationDelay;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        animationTimingFunction;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        animationDirection;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        animationFillMode;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        animationIterationCount;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        animationPlayState;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        animation;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozAnimationName;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozAnimationDuration;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozAnimationDelay;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozAnimationTimingFunction;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozAnimationDirection;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozAnimationFillMode;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozAnimationIterationCount;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozAnimationPlayState;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozAnimation;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozTextSizeAdjust;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderImageSource;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderImageSlice;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderImageWidth;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderImageOutset;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        borderImageRepeat;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        MozBorderImage;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        alignItems;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        alignSelf;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        flex;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        flexBasis;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        flexDirection;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        flexGrow;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        flexShrink;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        order;
-                                        // raises(DOMException) on setting
-
-           attribute DOMString        justifyContent;
-                                        // raises(DOMException) on setting
-};
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -520,17 +520,17 @@ TabParent::RecvNotifyIMEFocus(const bool
 
   *aSeqno = mIMESeqno;
   mIMETabParent = aFocus ? this : nullptr;
   mIMESelectionAnchor = 0;
   mIMESelectionFocus = 0;
   nsresult rv = widget->OnIMEFocusChange(aFocus);
 
   if (aFocus) {
-    if (NS_SUCCEEDED(rv) && rv != NS_SUCCESS_IME_NO_UPDATES) {
+    if (NS_SUCCEEDED(rv)) {
       *aPreference = widget->GetIMEUpdatePreference();
     } else {
       aPreference->mWantUpdates = false;
       aPreference->mWantHints = false;
     }
   } else {
     mIMECacheText.Truncate(0);
   }
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -200,24 +200,24 @@ nsPluginInstanceOwner::GetImageContainer
   float xResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetXResolution();
   float yResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetYResolution();
   r.Scale(xResolution, yResolution);
   mInstance->NotifySize(nsIntSize(r.width, r.height));
 
   return container.forget();
 #endif
 
-  // Every call to nsIPluginInstance::GetImage() creates
-  // a new image.  See nsIPluginInstance.idl.
   mInstance->GetImageContainer(getter_AddRefs(container));
   if (container) {
 #ifdef XP_MACOSX
     AutoLockImage autoLock(container);
     Image* image = autoLock.GetImage();
     if (image && image->GetFormat() == MAC_IO_SURFACE && mObjectFrame) {
+      // With this drawing model, every call to
+      // nsIPluginInstance::GetImage() creates a new image.
       MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image);
       NS_ADDREF_THIS();
       oglImage->SetUpdateCallback(&DrawPlugin, this);
       oglImage->SetDestroyCallback(&OnDestroyImage);
     }
 #endif
     return container.forget();
   }
@@ -632,21 +632,24 @@ NS_IMETHODIMP nsPluginInstanceOwner::Inv
     nsCOMPtr<nsIRunnable> event = new AsyncPaintWaitEvent(mContent, true);
     NS_DispatchToMainThread(event);
     mWaitingForPaint = false;
   }
 
   if (!mObjectFrame || !invalidRect || !mWidgetVisible)
     return NS_ERROR_FAILURE;
 
+#if defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID)
   // Each time an asynchronously-drawing plugin sends a new surface to display,
-  // InvalidateRect is called. We notify reftests that painting is up to
-  // date and update our ImageContainer with the new surface.
+  // the image in the ImageContainer is updated and InvalidateRect is called.
+  // MacIOSurfaceImages callbacks are attached here.
+  // There are different side effects for (sync) Android plugins.
   nsRefPtr<ImageContainer> container;
   mInstance->GetImageContainer(getter_AddRefs(container));
+#endif
 
 #ifndef XP_MACOSX
   // Windowed plugins should not be calling NPN_InvalidateRect, but
   // Silverlight does and expects it to "work"
   if (mWidget) {
     mWidget->Invalidate(nsIntRect(invalidRect->left, invalidRect->top,
                                   invalidRect->right - invalidRect->left,
                                   invalidRect->bottom - invalidRect->top));
@@ -3429,40 +3432,16 @@ void nsPluginInstanceOwner::SetFrame(nsO
 {
   // Don't do anything if the frame situation hasn't changed.
   if (mObjectFrame == aFrame) {
     return;
   }
 
   // If we already have a frame that is changing or going away...
   if (mObjectFrame) {
-    // We have an old frame.
-    // Drop image reference because the child may destroy the surface after we return.
-    nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
-    if (container) {
-#ifdef XP_MACOSX
-      AutoLockImage autoLock(container);
-      Image *image = autoLock.GetImage();
-      if (image && (image->GetFormat() == MAC_IO_SURFACE) && mObjectFrame) {
-        // Undo what we did to the current image in SetCurrentImageInTransaction().
-        MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image);
-        oglImage->SetUpdateCallback(nullptr, nullptr);
-        oglImage->SetDestroyCallback(nullptr);
-        // If we have a current image here, its destructor hasn't yet been
-        // called, so OnDestroyImage() can't yet have been called.  So we need
-        // to do ourselves what OnDestroyImage() would have done.
-        NS_RELEASE_THIS();
-      }
-      // Important! Unlock here otherwise SetCurrentImageInTransaction will deadlock with
-      // our lock if we have a RemoteImage.
-      autoLock.Unlock();
-#endif
-      container->SetCurrentImageInTransaction(nullptr);
-    }
-
     // Make sure the old frame isn't holding a reference to us.
     mObjectFrame->SetInstanceOwner(nullptr);
   }
 
   // Swap in the new frame (or no frame)
   mObjectFrame = aFrame;
 
   // Set up a new frame
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -90,24 +90,21 @@ PluginInstanceParent::~PluginInstancePar
 #if defined(MOZ_WIDGET_COCOA)
     if (mShWidth != 0 && mShHeight != 0) {
         DeallocShmem(mShSurface);
     }
     if (mShColorSpace)
         ::CGColorSpaceRelease(mShColorSpace);
 #endif
     if (mRemoteImageDataShmem.IsWritable()) {
-        ImageContainer *container =
-            GetImageContainer();
-
-        if (container) {
-            container->SetRemoteImageData(nullptr, nullptr);
-            container->SetCompositionNotifySink(nullptr);
-            DeallocShmem(mRemoteImageDataShmem);
+        if (mImageContainer) {
+            mImageContainer->SetRemoteImageData(nullptr, nullptr);
+            mImageContainer->SetCompositionNotifySink(nullptr);
         }
+        DeallocShmem(mRemoteImageDataShmem);
     }
 }
 
 bool
 PluginInstanceParent::Init()
 {
     mScriptableObjects.Init();
     return true;
@@ -120,24 +117,23 @@ PluginInstanceParent::ActorDestroy(Actor
     if (why == AbnormalShutdown) {
         // If the plugin process crashes, this is the only
         // chance we get to destroy resources.
         SharedSurfaceRelease();
         UnsubclassPluginWindow();
     }
 #endif
     // After this method, the data backing the remote surface may no
-    // longer be calid. The X surface may be destroyed, or the shared
-    // memory backing this surface may no longer be valid. The right
-    // way to inform the nsObjectFrame that the surface is no longer
-    // valid is with an invalidate call.
+    // longer be valid. The X surface may be destroyed, or the shared
+    // memory backing this surface may no longer be valid.
     if (mFrontSurface) {
         mFrontSurface = NULL;
-        const NPRect rect = {0, 0, 0, 0};
-        RecvNPN_InvalidateRect(rect);
+        if (mImageContainer) {
+            mImageContainer->SetCurrentImage(nullptr);
+        }
 #ifdef MOZ_X11
         FinishX(DefaultXDisplay());
 #endif
     }
 }
 
 NPError
 PluginInstanceParent::Destroy()
@@ -414,29 +410,25 @@ PluginInstanceParent::AnswerNPN_SetValue
 #elif defined(MOZ_X11)
                drawingModel == NPDrawingModelSyncX
 #else
                false
 #endif
                ) {
         *shmem = null_t();
 
-        ImageContainer *container = GetImageContainer();
-        if (!container) {
-            *result = NPERR_GENERIC_ERROR;
-            return true;
-        }
-
         mDrawingModel = drawingModel;
         *result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel,
                                       (void*)(intptr_t)drawingModel);
 
         if (mRemoteImageDataShmem.IsWritable()) {
-            container->SetRemoteImageData(nullptr, nullptr);
-            container->SetCompositionNotifySink(nullptr);
+            if (mImageContainer) {
+                mImageContainer->SetRemoteImageData(nullptr, nullptr);
+                mImageContainer->SetCompositionNotifySink(nullptr);
+            }
             DeallocShmem(mRemoteImageDataShmem);
             mRemoteImageDataMutex = NULL;
         }
     } else {
         *result = NPERR_GENERIC_ERROR;
     }
     return true;
 }
@@ -602,49 +594,62 @@ PluginInstanceParent::RecvShow(const NPR
 #ifdef XP_WIN
     else if (newSurface.type() == SurfaceDescriptor::TPPluginSurfaceParent) {
         PluginSurfaceParent* s =
             static_cast<PluginSurfaceParent*>(newSurface.get_PPluginSurfaceParent());
         surface = s->Surface();
     }
 #endif
 
-#ifdef MOZ_X11
-    if (mFrontSurface &&
-        mFrontSurface->GetType() == gfxASurface::SurfaceTypeXlib)
+    if (mFrontSurface) {
         // This is the "old front buffer" we're about to hand back to
         // the plugin.  We might still have drawing operations
-        // referencing it, so we XSync here to let them finish before
-        // the plugin starts scribbling on it again, or worse,
-        // destroys it.
-        FinishX(DefaultXDisplay());
+        // referencing it.
+        mFrontSurface->Finish();
+
+#ifdef MOZ_X11
+        if (mFrontSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
+            // XSync here to ensure the server has finished operations on the
+            // surface before the plugin starts scribbling on it again, or
+            // worse, destroys it.
+            FinishX(DefaultXDisplay());
+        }
 #endif
+    }
 
     if (mFrontSurface && gfxSharedImageSurface::IsSharedImage(mFrontSurface))
         *prevSurface = static_cast<gfxSharedImageSurface*>(mFrontSurface.get())->GetShmem();
     else
         *prevSurface = null_t();
 
     if (surface) {
         // Notify the cairo backend that this surface has changed behind
         // its back.
         gfxRect ur(updatedRect.left, updatedRect.top,
                    updatedRect.right - updatedRect.left,
                    updatedRect.bottom - updatedRect.top);
         surface->MarkDirty(ur);
-        surface->Flush();
+
+        ImageContainer *container = GetImageContainer();
+        ImageFormat format = CAIRO_SURFACE;
+        nsRefPtr<Image> image = container->CreateImage(&format, 1);
+        NS_ASSERTION(image->GetFormat() == CAIRO_SURFACE, "Wrong format?");
+        CairoImage* cairoImage = static_cast<CairoImage*>(image.get());
+        CairoImage::Data cairoData;
+        cairoData.mSurface = surface;
+        cairoData.mSize = surface->GetSize();
+        cairoImage->SetData(cairoData);
+
+        container->SetCurrentImage(cairoImage);
+    }
+    else if (mImageContainer) {
+        mImageContainer->SetCurrentImage(nullptr);
     }
 
     mFrontSurface = surface;
-    if (!surface) {
-      ImageContainer* container = GetImageContainer();
-      if (container) {
-        container->SetCurrentImage(nullptr);
-      }
-    }
     RecvNPN_InvalidateRect(updatedRect);
 
     PLUGIN_LOG_DEBUG(("   (RecvShow invalidated for surface %p)",
                       mFrontSurface.get()));
 
     return true;
 }
 
@@ -710,65 +715,49 @@ PluginInstanceParent::GetImageContainer(
     }
 
     if (!mFrontSurface && !ioSurface)
 #else
     if (!mFrontSurface)
 #endif
         return NS_ERROR_NOT_AVAILABLE;
 
-    ImageFormat format = CAIRO_SURFACE;
-#ifdef XP_MACOSX
-    if (ioSurface) {
-        format = MAC_IO_SURFACE;
-    }
-#endif
-
     ImageContainer *container = GetImageContainer();
 
     if (!container) {
         return NS_ERROR_FAILURE;
     }
 
     if (IsAsyncDrawing()) {
       NS_IF_ADDREF(container);
       *aContainer = container;
       return NS_OK;
     }
 
-    nsRefPtr<Image> image;
-    image = container->CreateImage(&format, 1);
-    if (!image) {
-        return NS_ERROR_FAILURE;
-    }
-
 #ifdef XP_MACOSX
     if (ioSurface) {
+        ImageFormat format = MAC_IO_SURFACE;
+        nsRefPtr<Image> image = container->CreateImage(&format, 1);
+        if (!image) {
+            return NS_ERROR_FAILURE;
+        }
+
         NS_ASSERTION(image->GetFormat() == MAC_IO_SURFACE, "Wrong format?");
         MacIOSurfaceImage* ioImage = static_cast<MacIOSurfaceImage*>(image.get());
         MacIOSurfaceImage::Data ioData;
         ioData.mIOSurface = ioSurface;
         ioImage->SetData(ioData);
         container->SetCurrentImageInTransaction(ioImage);
 
         NS_IF_ADDREF(container);
         *aContainer = container;
         return NS_OK;
     }
 #endif
 
-    NS_ASSERTION(image->GetFormat() == CAIRO_SURFACE, "Wrong format?");
-    CairoImage* pluginImage = static_cast<CairoImage*>(image.get());
-    CairoImage::Data cairoData;
-    cairoData.mSurface = mFrontSurface;
-    cairoData.mSize = mFrontSurface->GetSize();
-    pluginImage->SetData(cairoData);
-
-    container->SetCurrentImageInTransaction(pluginImage);
-
     NS_IF_ADDREF(container);
     *aContainer = container;
     return NS_OK;
 }
 
 nsresult
 PluginInstanceParent::GetImageSize(nsIntSize* aSize)
 {
--- a/dom/sms/interfaces/nsIDOMSmsMessage.idl
+++ b/dom/sms/interfaces/nsIDOMSmsMessage.idl
@@ -1,26 +1,32 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-[scriptable, builtinclass, uuid(5e3224dd-1ca3-43e6-861e-b7734656fd2f)]
+[scriptable, builtinclass, uuid(a82f9998-02a2-4db2-a0d1-f8353933d7b0)]
 interface nsIDOMMozSmsMessage : nsISupports
 {
   // TODO: we should add SENT and RECEIVED DOMString constants, see bug 443316.
 
   readonly attribute long      id;
   readonly attribute DOMString delivery;  // Should be "sent" or "received".
   /**
    * For received messages, it is "success"; for sent messages, it can be
    * "pending", "success", "error", or "not-applicable" if the message was sent
    * without status report requisition.
    */
   readonly attribute DOMString deliveryStatus;
   readonly attribute DOMString sender;
   readonly attribute DOMString receiver;
   readonly attribute DOMString body;
+
+  /**
+   * Should be "normal", "class-0", "class-1", "class-2" or "class-3".
+   */
+  readonly attribute DOMString messageClass;
+
   [implicit_jscontext]
   readonly attribute jsval     timestamp; // jsval is for Date.
   readonly attribute boolean   read;
 };
--- a/dom/sms/interfaces/nsISmsDatabaseService.idl
+++ b/dom/sms/interfaces/nsISmsDatabaseService.idl
@@ -8,21 +8,21 @@
 #define SMS_DATABASE_SERVICE_CID \
 { 0x2454c2a1, 0xefdd, 0x4d96,    \
 { 0x83, 0xbd, 0x51, 0xa2, 0x9a, 0x21, 0xf5, 0xab } }
 #define SMS_DATABASE_SERVICE_CONTRACTID "@mozilla.org/sms/smsdatabaseservice;1"
 %}
 
 interface nsIDOMMozSmsFilter;
 
-[scriptable, uuid(d6318c22-1ebd-4262-b991-432f61a96237)]
+[scriptable, uuid(6fdb6007-51d0-456c-8b2e-dc0aea456298)]
 interface nsISmsDatabaseService : nsISupports
 {
   // Takes some information required to save the message and returns its id.
-  long saveReceivedMessage(in DOMString aSender, in DOMString aBody, in unsigned long long aDate);
+  long saveReceivedMessage(in DOMString aSender, in DOMString aBody, in DOMString aMessageClass, in unsigned long long aDate);
   // Takes some information required to save the message and returns its id.
   long saveSentMessage(in DOMString aReceiver, in DOMString aBody, in unsigned long long aDate);
   void setMessageDeliveryStatus(in long aMessageId, in DOMString aDeliveryStatus);
 
   [binaryname(GetMessageMoz)] void getMessage(in long messageId, in long requestId, [optional] in unsigned long long processId);
   void deleteMessage(in long messageId, in long requestId, [optional] in unsigned long long processId);
 
   void createMessageList(in nsIDOMMozSmsFilter filter, in boolean reverse, in long requestId, [optional] in unsigned long long processId);
--- a/dom/sms/interfaces/nsISmsService.idl
+++ b/dom/sms/interfaces/nsISmsService.idl
@@ -6,26 +6,27 @@
 
 interface nsIDOMMozSmsMessage;
 
 %{C++
 #define SMS_SERVICE_CID { 0xbada3cb8, 0xa568, 0x4dff, { 0xb5, 0x43, 0x52, 0xbb, 0xb3, 0x14, 0x31, 0x21 } }
 #define SMS_SERVICE_CONTRACTID "@mozilla.org/sms/smsservice;1"
 %}
 
-[scriptable, builtinclass, uuid(a1367149-c09f-4e8c-a890-5812406bed61)]
+[scriptable, builtinclass, uuid(9808dc00-33c6-45cc-a761-d1151cb192d6)]
 interface nsISmsService : nsISupports
 {
   boolean        hasSupport();
   unsigned short getNumberOfMessagesForText(in DOMString text);
             void send(in DOMString number, in DOMString message,
                       in long requestId, [optional] in unsigned long long processId);
 
   [implicit_jscontext]
   nsIDOMMozSmsMessage createSmsMessage(in long      id,
                                        in DOMString delivery,
                                        in DOMString deliveryStatus,
                                        in DOMString sender,
                                        in DOMString receiver,
                                        in DOMString body,
+                                       in DOMString messageClass,
                                        in jsval     timestamp,
                                        in bool      read);
 };
--- a/dom/sms/src/Constants.h
+++ b/dom/sms/src/Constants.h
@@ -18,13 +18,19 @@ extern const char* kSmsDeliveryErrorObse
 #define DELIVERY_RECEIVED NS_LITERAL_STRING("received")
 #define DELIVERY_SENT     NS_LITERAL_STRING("sent")
 
 #define DELIVERY_STATUS_NOT_APPLICABLE NS_LITERAL_STRING("not-applicable")
 #define DELIVERY_STATUS_SUCCESS        NS_LITERAL_STRING("success")
 #define DELIVERY_STATUS_PENDING        NS_LITERAL_STRING("pending")
 #define DELIVERY_STATUS_ERROR          NS_LITERAL_STRING("error")
 
+#define MESSAGE_CLASS_NORMAL  NS_LITERAL_STRING("normal")
+#define MESSAGE_CLASS_CLASS_0 NS_LITERAL_STRING("class-0")
+#define MESSAGE_CLASS_CLASS_1 NS_LITERAL_STRING("class-1")
+#define MESSAGE_CLASS_CLASS_2 NS_LITERAL_STRING("class-2")
+#define MESSAGE_CLASS_CLASS_3 NS_LITERAL_STRING("class-3")
+
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_sms_Constants_h
--- a/dom/sms/src/SmsMessage.cpp
+++ b/dom/sms/src/SmsMessage.cpp
@@ -25,35 +25,37 @@ NS_IMPL_ADDREF(SmsMessage)
 NS_IMPL_RELEASE(SmsMessage)
 
 SmsMessage::SmsMessage(int32_t aId,
                        DeliveryState aDelivery,
                        DeliveryStatus aDeliveryStatus,
                        const nsString& aSender,
                        const nsString& aReceiver,
                        const nsString& aBody,
+                       MessageClass aMessageClass,
                        uint64_t aTimestamp,
                        bool aRead)
   : mData(aId, aDelivery, aDeliveryStatus, aSender, aReceiver, aBody,
-          aTimestamp, aRead)
+          aMessageClass, aTimestamp, aRead)
 {
 }
 
 SmsMessage::SmsMessage(const SmsMessageData& aData)
   : mData(aData)
 {
 }
 
 /* static */ nsresult
 SmsMessage::Create(int32_t aId,
                    const nsAString& aDelivery,
                    const nsAString& aDeliveryStatus,
                    const nsAString& aSender,
                    const nsAString& aReceiver,
                    const nsAString& aBody,
+                   const nsAString& aMessageClass,
                    const jsval& aTimestamp,
                    const bool aRead,
                    JSContext* aCx,
                    nsIDOMMozSmsMessage** aMessage)
 {
   *aMessage = nullptr;
 
   // SmsMessageData exposes these as references, so we can simply assign
@@ -80,16 +82,30 @@ SmsMessage::Create(int32_t aId,
   } else if (aDeliveryStatus.Equals(DELIVERY_STATUS_PENDING)) {
     data.deliveryStatus() = eDeliveryStatus_Pending;
   } else if (aDeliveryStatus.Equals(DELIVERY_STATUS_ERROR)) {
     data.deliveryStatus() = eDeliveryStatus_Error;
   } else {
     return NS_ERROR_INVALID_ARG;
   }
 
+  if (aMessageClass.Equals(MESSAGE_CLASS_NORMAL)) {
+    data.messageClass() = eMessageClass_Normal;
+  } else if (aMessageClass.Equals(MESSAGE_CLASS_CLASS_0)) {
+    data.messageClass() = eMessageClass_Class0;
+  } else if (aMessageClass.Equals(MESSAGE_CLASS_CLASS_1)) {
+    data.messageClass() = eMessageClass_Class1;
+  } else if (aMessageClass.Equals(MESSAGE_CLASS_CLASS_2)) {
+    data.messageClass() = eMessageClass_Class2;
+  } else if (aMessageClass.Equals(MESSAGE_CLASS_CLASS_3)) {
+    data.messageClass() = eMessageClass_Class3;
+  } else {
+    return NS_ERROR_INVALID_ARG;
+  }
+
   // We support both a Date object and a millisecond timestamp as a number.
   if (aTimestamp.isObject()) {
     JSObject& obj = aTimestamp.toObject();
     if (!JS_ObjectIsDate(aCx, &obj)) {
       return NS_ERROR_INVALID_ARG;
     }
     data.timestamp() = js_DateGetMsecSinceEpoch(&obj);
   } else {
@@ -183,16 +199,43 @@ SmsMessage::GetReceiver(nsAString& aRece
 NS_IMETHODIMP
 SmsMessage::GetBody(nsAString& aBody)
 {
   aBody = mData.body();
   return NS_OK;
 }
 
 NS_IMETHODIMP
+SmsMessage::GetMessageClass(nsAString& aMessageClass)
+{
+  switch (mData.messageClass()) {
+    case eMessageClass_Normal:
+      aMessageClass = MESSAGE_CLASS_NORMAL;
+      break;
+    case eMessageClass_Class0:
+      aMessageClass = MESSAGE_CLASS_CLASS_0;
+      break;
+    case eMessageClass_Class1:
+      aMessageClass = MESSAGE_CLASS_CLASS_1;
+      break;
+    case eMessageClass_Class2:
+      aMessageClass = MESSAGE_CLASS_CLASS_2;
+      break;
+    case eMessageClass_Class3:
+      aMessageClass = MESSAGE_CLASS_CLASS_3;
+      break;
+    default:
+      MOZ_NOT_REACHED("We shouldn't get any other message class!");
+      return NS_ERROR_UNEXPECTED;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 SmsMessage::GetTimestamp(JSContext* cx, jsval* aDate)
 {
   *aDate = OBJECT_TO_JSVAL(JS_NewDateObjectMsec(cx, mData.timestamp()));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsMessage::GetRead(bool* aRead)
--- a/dom/sms/src/SmsMessage.h
+++ b/dom/sms/src/SmsMessage.h
@@ -24,26 +24,28 @@ public:
   NS_DECL_NSIDOMMOZSMSMESSAGE
 
   SmsMessage(int32_t aId,
              DeliveryState aDelivery,
              DeliveryStatus aDeliveryStatus,
              const nsString& aSender,
              const nsString& aReceiver,
              const nsString& aBody,
+             MessageClass aMessageClass,
              uint64_t aTimestamp,
              bool aRead);
   SmsMessage(const SmsMessageData& aData);
 
   static nsresult Create(int32_t aId,
                          const nsAString& aDelivery,
                          const nsAString& aDeliveryStatus,
                          const nsAString& aSender,
                          const nsAString& aReceiver,
                          const nsAString& aBody,
+                         const nsAString& aMessageClass,
                          const JS::Value& aTimestamp,
                          const bool aRead,
                          JSContext* aCx,
                          nsIDOMMozSmsMessage** aMessage);
   const SmsMessageData& GetData() const;
 
 private:
   // Don't try to use the default constructor.
--- a/dom/sms/src/Types.h
+++ b/dom/sms/src/Types.h
@@ -37,16 +37,27 @@ enum DeliveryStatus {
 enum ReadState {
   eReadState_Unknown = -1,
   eReadState_Unread,
   eReadState_Read,
   // This state should stay at the end.
   eReadState_EndGuard
 };
 
+// For SmsFilterData.messageClass
+enum MessageClass {
+  eMessageClass_Normal = 0,
+  eMessageClass_Class0,
+  eMessageClass_Class1,
+  eMessageClass_Class2,
+  eMessageClass_Class3,
+  // This state should stay at the end.
+  eMessageClass_EndGuard
+};
+
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
 
 namespace IPC {
 
 /**
  * Delivery state serializer.
@@ -73,11 +84,21 @@ struct ParamTraits<mozilla::dom::sms::De
  */
 template <>
 struct ParamTraits<mozilla::dom::sms::ReadState>
   : public EnumSerializer<mozilla::dom::sms::ReadState,
                           mozilla::dom::sms::eReadState_Unknown,
                           mozilla::dom::sms::eReadState_EndGuard>
 {};
 
+/**
+ * Message class serializer.
+ */
+template <>
+struct ParamTraits<mozilla::dom::sms::MessageClass>
+  : public EnumSerializer<mozilla::dom::sms::MessageClass,
+                          mozilla::dom::sms::eMessageClass_Normal,
+                          mozilla::dom::sms::eMessageClass_EndGuard>
+{};
+
 } // namespace IPC
 
 #endif // mozilla_dom_sms_Types_h
--- a/dom/sms/src/android/SmsDatabaseService.cpp
+++ b/dom/sms/src/android/SmsDatabaseService.cpp
@@ -11,16 +11,17 @@ namespace mozilla {
 namespace dom {
 namespace sms {
 
 NS_IMPL_ISUPPORTS1(SmsDatabaseService, nsISmsDatabaseService)
 
 NS_IMETHODIMP
 SmsDatabaseService::SaveReceivedMessage(const nsAString& aSender,
                                         const nsAString& aBody,
+                                        const nsAString& aMessageClass,
                                         uint64_t aDate, int32_t* aId)
 {
   // The Android stock SMS app does this already.
   *aId = -1;
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/dom/sms/src/android/SmsService.cpp
+++ b/dom/sms/src/android/SmsService.cpp
@@ -48,22 +48,23 @@ SmsService::Send(const nsAString& aNumbe
 
 NS_IMETHODIMP
 SmsService::CreateSmsMessage(int32_t aId,
                              const nsAString& aDelivery,
                              const nsAString& aDeliveryStatus,
                              const nsAString& aSender,
                              const nsAString& aReceiver,
                              const nsAString& aBody,
+                             const nsAString& aMessageClass,
                              const jsval& aTimestamp,
                              const bool aRead,
                              JSContext* aCx,
                              nsIDOMMozSmsMessage** aMessage)
 {
   return SmsMessage::Create(aId, aDelivery, aDeliveryStatus,
                             aSender, aReceiver,
-                            aBody, aTimestamp, aRead,
+                            aBody, aMessageClass, aTimestamp, aRead,
                             aCx, aMessage);
 }
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/fallback/SmsDatabaseService.cpp
+++ b/dom/sms/src/fallback/SmsDatabaseService.cpp
@@ -9,17 +9,19 @@ namespace mozilla {
 namespace dom {
 namespace sms {
 
 NS_IMPL_ISUPPORTS1(SmsDatabaseService, nsISmsDatabaseService)
 
 NS_IMETHODIMP
 SmsDatabaseService::SaveReceivedMessage(const nsAString& aSender,
                                         const nsAString& aBody,
-                                        uint64_t aDate, int32_t* aId)
+                                        const nsAString& aMessageClass,
+                                        uint64_t aDate,
+                                        int32_t* aId)
 {
   *aId = -1;
   NS_ERROR("We should not be here!");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsDatabaseService::SaveSentMessage(const nsAString& aReceiver,
--- a/dom/sms/src/fallback/SmsService.cpp
+++ b/dom/sms/src/fallback/SmsService.cpp
@@ -38,22 +38,23 @@ SmsService::Send(const nsAString& aNumbe
 
 NS_IMETHODIMP
 SmsService::CreateSmsMessage(int32_t aId,
                              const nsAString& aDelivery,
                              const nsAString& aDeliveryStatus,
                              const nsAString& aSender,
                              const nsAString& aReceiver,
                              const nsAString& aBody,
+                             const nsAString& aMessageClass,
                              const jsval& aTimestamp,
                              const bool aRead,
                              JSContext* aCx,
                              nsIDOMMozSmsMessage** aMessage)
 {
   return SmsMessage::Create(aId, aDelivery, aDeliveryStatus,
                             aSender, aReceiver,
-                            aBody, aTimestamp, aRead,
+                            aBody, aMessageClass, aTimestamp, aRead,
                             aCx, aMessage);
 }
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/ipc/PSms.ipdl
+++ b/dom/sms/src/ipc/PSms.ipdl
@@ -4,29 +4,31 @@
  * 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 protocol PContent;
 include "mozilla/dom/sms/Types.h";
 
 using DeliveryState;
 using DeliveryStatus;
+using MessageClass;
 using ReadState;
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
 struct SmsMessageData {
   int32_t        id;
   DeliveryState  delivery;
   DeliveryStatus deliveryStatus;
   nsString       sender;
   nsString       receiver;
   nsString       body;
+  MessageClass   messageClass;
   uint64_t       timestamp; // ms since epoch.
   bool           read;
 };
 
 struct SmsFilterData {
   uint64_t      startDate;
   uint64_t      endDate;
   nsString[]    numbers;
@@ -82,17 +84,17 @@ parent:
         returns (bool aHasSupport);
 
     sync GetNumberOfMessagesForText(nsString aText)
         returns (uint16_t aNumber);
 
     SendMessage(nsString aNumber, nsString aMessage, int32_t aRequestId,
                 uint64_t aProcessId);
 
-    sync SaveReceivedMessage(nsString aSender, nsString aBody, uint64_t aDate)
+    sync SaveReceivedMessage(nsString aSender, nsString aBody, nsString aMessageClass, uint64_t aDate)
         returns (int32_t aId);
 
     sync SaveSentMessage(nsString aReceiver, nsString aBody, uint64_t aDate)
         returns (int32_t aId);
 
     SetMessageDeliveryStatus(int32_t aMessageId, nsString aDeliveryStatus);
 
     GetMessage(int32_t aMessageId, int32_t aRequestId, uint64_t aProcessId);
--- a/dom/sms/src/ipc/SmsIPCService.cpp
+++ b/dom/sms/src/ipc/SmsIPCService.cpp
@@ -60,37 +60,40 @@ SmsIPCService::Send(const nsAString& aNu
 
 NS_IMETHODIMP
 SmsIPCService::CreateSmsMessage(int32_t aId,
                                 const nsAString& aDelivery,
                                 const nsAString& aDeliveryStatus,
                                 const nsAString& aSender,
                                 const nsAString& aReceiver,
                                 const nsAString& aBody,
+                                const nsAString& aMessageClass,
                                 const jsval& aTimestamp,
                                 const bool aRead,
                                 JSContext* aCx,
                                 nsIDOMMozSmsMessage** aMessage)
 {
   return SmsMessage::Create(aId, aDelivery, aDeliveryStatus,
                             aSender, aReceiver,
-                            aBody, aTimestamp, aRead,
+                            aBody, aMessageClass, aTimestamp, aRead,
                             aCx, aMessage);
 }
 
 /*
  * Implementation of nsISmsDatabaseService.
  */
 NS_IMETHODIMP
 SmsIPCService::SaveReceivedMessage(const nsAString& aSender,
                                    const nsAString& aBody,
-                                   uint64_t aDate, int32_t* aId)
+                                   const nsAString& aMessageClass,
+                                   uint64_t aDate,
+                                   int32_t* aId)
 {
   GetSmsChild()->SendSaveReceivedMessage(nsString(aSender), nsString(aBody),
-                                         aDate, aId);
+                                         nsString(aMessageClass), aDate, aId);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsIPCService::SaveSentMessage(const nsAString& aReceiver,
                                const nsAString& aBody,
                                uint64_t aDate, int32_t* aId)
--- a/dom/sms/src/ipc/SmsParent.cpp
+++ b/dom/sms/src/ipc/SmsParent.cpp
@@ -157,25 +157,27 @@ SmsParent::RecvSendMessage(const nsStrin
 
   smsService->Send(aNumber, aMessage, aRequestId, aProcessId);
   return true;
 }
 
 bool
 SmsParent::RecvSaveReceivedMessage(const nsString& aSender,
                                    const nsString& aBody,
-                                   const uint64_t& aDate, int32_t* aId)
+                                   const nsString& aMessageClass,
+                                   const uint64_t& aDate,
+                                   int32_t* aId)
 {
   *aId = -1;
 
   nsCOMPtr<nsISmsDatabaseService> smsDBService =
     do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsDBService, true);
 
-  smsDBService->SaveReceivedMessage(aSender, aBody, aDate, aId);
+  smsDBService->SaveReceivedMessage(aSender, aBody, aMessageClass, aDate, aId);
   return true;
 }
 
 bool
 SmsParent::RecvSaveSentMessage(const nsString& aRecipient,
                                const nsString& aBody,
                                const uint64_t& aDate, int32_t* aId)
 {
--- a/dom/sms/src/ipc/SmsParent.h
+++ b/dom/sms/src/ipc/SmsParent.h
@@ -22,17 +22,17 @@ public:
 
   static void GetAll(nsTArray<SmsParent*>& aArray);
 
   SmsParent();
 
   virtual bool RecvHasSupport(bool* aHasSupport) MOZ_OVERRIDE;
   virtual bool RecvGetNumberOfMessagesForText(const nsString& aText, uint16_t* aResult) MOZ_OVERRIDE;
   virtual bool RecvSendMessage(const nsString& aNumber, const nsString& aMessage, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
-  virtual bool RecvSaveReceivedMessage(const nsString& aSender, const nsString& aBody, const uint64_t& aDate, int32_t* aId) MOZ_OVERRIDE;
+  virtual bool RecvSaveReceivedMessage(const nsString& aSender, const nsString& aBody, const nsString& aMessageClass, const uint64_t& aDate, int32_t* aId) MOZ_OVERRIDE;
   virtual bool RecvSaveSentMessage(const nsString& aRecipient, const nsString& aBody, const uint64_t& aDate, int32_t* aId) MOZ_OVERRIDE;
   virtual bool RecvSetMessageDeliveryStatus(const int32_t& aMessageId, const nsString& aDeliveryStatus) MOZ_OVERRIDE;
   virtual bool RecvGetMessage(const int32_t& aMessageId, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvDeleteMessage(const int32_t& aMessageId, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvCreateMessageList(const SmsFilterData& aFilter, const bool& aReverse, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvGetNextMessageInList(const int32_t& aListId, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvClearMessageList(const int32_t& aListId) MOZ_OVERRIDE;
   virtual bool RecvMarkMessageRead(const int32_t& aMessageId, const bool& aValue, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
--- a/dom/sms/src/ril/SmsDatabaseService.js
+++ b/dom/sms/src/ril/SmsDatabaseService.js
@@ -20,16 +20,18 @@ const STORE_NAME = "sms";
 const DELIVERY_SENT = "sent";
 const DELIVERY_RECEIVED = "received";
 
 const DELIVERY_STATUS_NOT_APPLICABLE = "not-applicable";
 const DELIVERY_STATUS_SUCCESS = "success";
 const DELIVERY_STATUS_PENDING = "pending";
 const DELIVERY_STATUS_ERROR = "error";
 
+const MESSAGE_CLASS_NORMAL = "normal";
+
 const FILTER_TIMESTAMP = "timestamp";
 const FILTER_NUMBERS = "numbers";
 const FILTER_DELIVERY = "delivery";
 const FILTER_READ = "read";
 
 // We can´t create an IDBKeyCursor with a boolean, so we need to use numbers
 // instead.
 const FILTER_READ_UNREAD = 0;
@@ -321,16 +323,17 @@ SmsDatabaseService.prototype = {
         self.lastMessageListId += 1;
         self.messageLists[self.lastMessageListId] = messageList;
         let sms = gSmsService.createSmsMessage(message.id,
                                                message.delivery,
                                                message.deliveryStatus,
                                                message.sender,
                                                message.receiver,
                                                message.body,
+                                               message.messageClass,
                                                message.timestamp,
                                                message.read);
         gSmsRequestManager.notifyCreateMessageList(requestId,
                                                    self.lastMessageListId,
                                                    sms);
       };
     });
   },
@@ -349,37 +352,39 @@ SmsDatabaseService.prototype = {
     return message.id;
   },
 
 
   /**
    * nsISmsDatabaseService API
    */
 
-  saveReceivedMessage: function saveReceivedMessage(sender, body, date) {
+  saveReceivedMessage: function saveReceivedMessage(sender, body, messageClass, date) {
     let receiver = this.mRIL.rilContext.icc ? this.mRIL.rilContext.icc.msisdn : null;
 
     let message = {delivery:       DELIVERY_RECEIVED,
                    deliveryStatus: DELIVERY_STATUS_SUCCESS,
                    sender:         sender,
                    receiver:       receiver,
                    body:           body,
+                   messageClass:   messageClass,
                    timestamp:      date,
                    read:           FILTER_READ_UNREAD};
     return this.saveMessage(message);
   },
 
   saveSentMessage: function saveSentMessage(receiver, body, date) {
     let sender = this.mRIL.rilContext.icc ? this.mRIL.rilContext.icc.msisdn : null;
 
     let message = {delivery:       DELIVERY_SENT,
                    deliveryStatus: DELIVERY_STATUS_PENDING,
                    sender:         sender,
                    receiver:       receiver,
                    body:           body,
+                   messageClass:   MESSAGE_CLASS_NORMAL,
                    timestamp:      date,
                    read:           FILTER_READ_READ};
     return this.saveMessage(message);
   },
 
   setMessageDeliveryStatus: function setMessageDeliveryStatus(messageId, deliveryStatus) {
     if ((deliveryStatus != DELIVERY_STATUS_SUCCESS)
         && (deliveryStatus != DELIVERY_STATUS_ERROR)) {
@@ -464,16 +469,17 @@ SmsDatabaseService.prototype = {
           return;
         }
         let message = gSmsService.createSmsMessage(data.id,
                                                    data.delivery,
                                                    data.deliveryStatus,
                                                    data.sender,
                                                    data.receiver,
                                                    data.body,
+                                                   data.messageClass,
                                                    data.timestamp,
                                                    data.read);
         gSmsRequestManager.notifyGotSms(requestId, message);
       };
 
       txn.onerror = function onerror(event) {
         if (DEBUG) debug("Caught error on transaction", event.target.errorCode);
         //TODO look at event.target.errorCode, pick appropriate error constant
@@ -689,16 +695,17 @@ SmsDatabaseService.prototype = {
             requestId, Ci.nsISmsRequestManager.NOT_FOUND_ERROR);
         }
         let sms = gSmsService.createSmsMessage(message.id,
                                                message.delivery,
                                                message.deliveryStatus,
                                                message.sender,
                                                message.receiver,
                                                message.body,
+                                               message.messageClass,
                                                message.timestamp,
                                                message.read);
         gSmsRequestManager.notifyGotNextMessage(requestId, sms);
       };
 
       txn.onerror = function onerror(event) {
         //TODO check event.target.errorCode
         if (DEBUG) {
--- a/dom/sms/src/ril/SmsService.cpp
+++ b/dom/sms/src/ril/SmsService.cpp
@@ -63,22 +63,23 @@ SmsService::Send(const nsAString& aNumbe
 
 NS_IMETHODIMP
 SmsService::CreateSmsMessage(int32_t aId,
                              const nsAString& aDelivery,
                              const nsAString& aDeliveryStatus,
                              const nsAString& aSender,
                              const nsAString& aReceiver,
                              const nsAString& aBody,
+                             const nsAString& aMessageClass,
                              const jsval& aTimestamp,
                              const bool aRead,
                              JSContext* aCx,
                              nsIDOMMozSmsMessage** aMessage)
 {
   return SmsMessage::Create(aId, aDelivery, aDeliveryStatus,
                             aSender, aReceiver,
-                            aBody, aTimestamp, aRead,
+                            aBody, aMessageClass, aTimestamp, aRead,
                             aCx, aMessage);
 }
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/tests/marionette/test_getmessage.js
+++ b/dom/sms/tests/marionette/test_getmessage.js
@@ -35,16 +35,17 @@ function simulateIncomingSms() {
     inSmsId = incomingSms.id;
     log("Received SMS (id: " + inSmsId + ").");
     is(incomingSms.body, inText, "msg body");
     is(incomingSms.delivery, "received", "delivery");
     is(incomingSms.deliveryStatus, "success", "deliveryStatus");
     is(incomingSms.read, false, "read");
     is(incomingSms.receiver, null, "receiver");
     is(incomingSms.sender, remoteNumber, "sender");
+    is(incomingSms.messageClass, "normal", "messageClass");
     ok(incomingSms.timestamp instanceof Date, "timestamp is instanceof date");
     inSmsTimeStamp = incomingSms.timestamp;
     sendSms();
   };
   // Simulate incoming sms sent from remoteNumber to our emulator
   runEmulatorCmd("sms send " + remoteNumber + " " + inText, function(result) {
     is(result[0], "OK", "emulator output");
   });
@@ -61,16 +62,17 @@ function sendSms() {
     outSmsId = sentSms.id;
     log("Sent SMS (id: " + outSmsId + ").");
     is(sentSms.body, outText, "msg body");
     is(sentSms.delivery, "sent", "delivery");
     is(sentSms.deliveryStatus, "pending", "deliveryStatus");
     is(sentSms.read, true, "read");
     is(sentSms.receiver, remoteNumber, "receiver");
     is(sentSms.sender, null, "sender");
+    is(sentSms.messageClass, "normal", "messageClass");
     ok(sentSms.timestamp instanceof Date, "timestamp is instanceof date");  
     outSmsTimeStamp = sentSms.timestamp;
 
     if (gotSmsOnsent && gotReqOnsuccess) { getReceivedSms(); }
   };
 
   let requestRet = sms.send(remoteNumber, outText);
   ok(requestRet, "smsrequest obj returned");
@@ -109,16 +111,17 @@ function getReceivedSms() {
     is(foundSms.id, inSmsId, "SMS id matches");
     log("Got SMS (id: " + foundSms.id + ").");
     is(foundSms.body, inText, "SMS msg text matches");
     is(foundSms.delivery, "received", "delivery");
     is(foundSms.deliveryStatus, "success", "deliveryStatus");
     is(foundSms.read, false, "read");
     is(foundSms.receiver, myNumber, "receiver");
     is(foundSms.sender, remoteNumber, "sender");
+    is(foundSms.messageClass, "normal", "messageClass");
     ok(foundSms.timestamp instanceof Date, "timestamp is instanceof date");
     is(foundSms.timestamp.getTime(), inSmsTimeStamp.getTime(), "timestamp matches");
     getSentSms();
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
@@ -141,16 +144,17 @@ function getSentSms() {
     is(foundSms.id, outSmsId, "SMS id matches");
     log("Got SMS (id: " + foundSms.id + ").");
     is(foundSms.body, outText, "SMS msg text matches");
     is(foundSms.delivery, "sent", "delivery");
     is(foundSms.deliveryStatus, "pending", "deliveryStatus");
     is(foundSms.read, true, "read");
     is(foundSms.receiver, remoteNumber, "receiver");
     is(foundSms.sender, myNumber, "sender");
+    is(foundSms.messageClass, "normal", "messageClass");
     ok(foundSms.timestamp instanceof Date, "timestamp is instanceof date");
     is(foundSms.timestamp.getTime(), outSmsTimeStamp.getTime(), "timestamp matches");
     deleteMsgs();
   };
 
   requestRet.onerror = function(event) {
     log("Received 'onerror' smsrequest event.");
     ok(event.target.error, "domerror obj");
--- a/dom/sms/tests/marionette/test_incoming.js
+++ b/dom/sms/tests/marionette/test_incoming.js
@@ -24,16 +24,17 @@ sms.onreceived = function onreceived(eve
   let message = event.message;
   ok(message instanceof MozSmsMessage);
 
   is(message.delivery, "received");
   is(message.deliveryStatus, "success");
   is(message.sender, sender);
   is(message.receiver, null);
   is(message.body, body);
+  is(message.messageClass, "normal");
   ok(message.timestamp instanceof Date);
   // SMSC timestamp is in seconds.
   ok(Math.floor(message.timestamp.getTime() / 1000) >= Math.floor(now / 1000));
 
   cleanUp();
 };
 
 function cleanUp() {
--- a/dom/sms/tests/marionette/test_incoming_delete.js
+++ b/dom/sms/tests/marionette/test_incoming_delete.js
@@ -26,16 +26,17 @@ function simulateIncomingSms() {
     ok(incomingSms.id, "sms id");
     log("Received SMS (id: " + incomingSms.id + ").");
     is(incomingSms.body, msgText, "msg body");
     is(incomingSms.delivery, "received", "delivery");
     is(incomingSms.deliveryStatus, "success", "deliveryStatus");
     is(incomingSms.read, false, "read");
     is(incomingSms.receiver, null, "receiver");
     is(incomingSms.sender, fromNumber, "sender");
+    is(incomingSms.messageClass, "normal", "messageClass");
     ok(incomingSms.timestamp instanceof Date, "timestamp is istanceof date");
 
     verifySmsExists(incomingSms);
   };
   runEmulatorCmd("sms send " + fromNumber + " " + msgText, function(result) {
     is(result[0], "OK", "emulator output");
   });
 }
--- a/dom/sms/tests/marionette/test_message_classes.js
+++ b/dom/sms/tests/marionette/test_message_classes.js
@@ -26,28 +26,29 @@ function sendSmsPduToEmulator(pdu) {
   runEmulatorCmd(cmd, function (result) {
     --pendingEmulatorCmdCount;
 
     is(result[0], "OK", "Emulator response");
   });
 }
 
 const TIMESTAMP = Date.UTC(2000, 0, 1);
-function checkMessage(message, id) {
+function checkMessage(message, id, messageClass) {
   ok(message instanceof MozSmsMessage,
      "message is instanceof " + message.constructor);
   if (id == null) {
     ok(message.id > 0, "message.id");
   } else {
     is(message.id, -1, "message.id");
   }
   is(message.delivery, "received", "message.delivery");
   is(message.deliveryStatus, "success", "message.deliveryStatus");
   is(message.sender, "+1", "message.sender");
   is(message.body, "A", "message.body");
+  is(message.messageClass, messageClass, "message.messageClass");
   ok(message.timestamp instanceof Date,
      "message.timestamp is instanceof " + message.timestamp.constructor);
   is(message.timestamp.getTime(), TIMESTAMP, "message.timestamp");
   is(message.read, false, "message.read");
 }
 
 function test_message_class_0() {
   let allDCSs = [
@@ -56,17 +57,17 @@ function test_message_class_0() {
     "F0"  // (no name) Group: 1111
   ];
 
   function do_test(dcsIndex) {
     sms.addEventListener("received", function onReceived(event) {
       sms.removeEventListener("received", onReceived);
 
       let message = event.message;
-      checkMessage(message, -1);
+      checkMessage(message, -1, "class-0");
 
       // Make sure the message is not stored.
       let request = sms.getMessages(null, false);
       request.onsuccess = function onsuccess() {
         let cursor = request.result;
         if (cursor.message) {
           // Here we check whether there is any message of the same sender.
           isnot(cursor.message.sender, message.sender, "cursor.message.sender");
@@ -95,23 +96,23 @@ function test_message_class_0() {
 
     sendSmsPduToEmulator(pdu);
   }
 
   log("Checking Message Class 0");
   do_test(0);
 }
 
-function doTestMessageClassGeneric(allDCSs, next) {
+function doTestMessageClassGeneric(allDCSs, messageClass, next) {
   function do_test(dcsIndex) {
     sms.addEventListener("received", function onReceived(event) {
       sms.removeEventListener("received", onReceived);
 
       // Make sure we can correctly receive the message
-      checkMessage(event.message);
+      checkMessage(event.message, null, messageClass);
 
       ++dcsIndex;
       if (dcsIndex >= allDCSs.length) {
         window.setTimeout(next, 0);
       } else {
         window.setTimeout(do_test.bind(null, dcsIndex), 0);
       }
     });
@@ -130,17 +131,17 @@ function doTestMessageClassGeneric(allDC
 function test_message_class_1() {
   let allDCSs = [
     "11", // General Group: 00xx
     "51", // Automatica Deletion Group: 01xx
     "F1"  // (no name) Group: 1111
   ];
 
   log("Checking Message Class 1");
-  doTestMessageClassGeneric(allDCSs, test_message_class_2);
+  doTestMessageClassGeneric(allDCSs, "class-1", test_message_class_2);
 }
 
 function test_message_class_2() {
   let allDCSs = [
     "12", // General Group: 00xx
     "52", // Automatica Deletion Group: 01xx
     "F2"  // (no name) Group: 1111
   ];
@@ -151,17 +152,17 @@ function test_message_class_2() {
     PDU_PID_USIM_DATA_DOWNLOAD
   ];
 
   function do_test_dcs(dcsIndex) {
     function do_test_pid(pidIndex) {
       function onReceived(event) {
         if (pidIndex == 0) {
           // Make sure we can correctly receive the message
-          checkMessage(event.message);
+          checkMessage(event.message, null, "class-2");
 
           next();
           return;
         }
 
         // TODO: Bug 792798 - B2G SMS: develop test cases for 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
@@ -215,17 +216,17 @@ function test_message_class_2() {
 function test_message_class_3() {
   let allDCSs = [
     "13", // General Group: 00xx
     "53", // Automatica Deletion Group: 01xx
     "F3"  // (no name) Group: 1111
   ];
 
   log("Checking Message Class 3");
-  doTestMessageClassGeneric(allDCSs, cleanUp);
+  doTestMessageClassGeneric(allDCSs, "class-3", cleanUp);
 }
 
 function cleanUp() {
   if (pendingEmulatorCmdCount) {
     window.setTimeout(cleanUp, 100);
     return;
   }
 
--- a/dom/sms/tests/marionette/test_outgoing.js
+++ b/dom/sms/tests/marionette/test_outgoing.js
@@ -32,16 +32,17 @@ function checkSentMessage(message, body,
      "message is instanceof " + message.constructor);
 
   ok(message.id, "message.id is valid");
   is(message.delivery, "sent", "message.delivery");
   is(message.deliveryStatus, "pending", "message.deliveryStatus");
   is(message.sender, null, "message.sender");
   is(message.receiver, receiver, "message.receiver");
   is(message.body, body, "message.body");
+  is(message.messageClass, "normal", "messageClass");
   ok(message.timestamp instanceof Date,
      "message.timestamp is instanceof " + message.timestamp.constructor);
   // SMSC timestamp is in seconds.
   ok(Math.floor(message.timestamp.getTime() / 1000) >= Math.floor(sentDate / 1000),
      "sent timestamp is valid");
   is(message.read, true, "message.read");
 }
 
--- a/dom/sms/tests/marionette/test_outgoing_delete.js
+++ b/dom/sms/tests/marionette/test_outgoing_delete.js
@@ -31,16 +31,17 @@ function sendSms() {
     smsId = sentSms.id;
     log("Sent SMS (id: " + smsId + ").");
     is(sentSms.body, msgText, "msg body");
     is(sentSms.delivery, "sent", "delivery");
     is(sentSms.deliveryStatus, "pending", "deliveryStatus");
     is(sentSms.read, true, "read");
     is(sentSms.receiver, destNumber, "receiver");
     is(sentSms.sender, null, "sender");
+    is(sentSms.messageClass, "normal", "messageClass");
     ok(sentSms.timestamp instanceof Date, "timestamp is istanceof date");
 
     if (gotSmsOnsent && gotReqOnsuccess) { verifySmsExists(smsId); }
   };
 
   let requestRet = sms.send(destNumber, msgText);
   ok(requestRet, "smsrequest obj returned");
 
--- a/dom/sms/tests/marionette/test_timestamp.js
+++ b/dom/sms/tests/marionette/test_timestamp.js
@@ -33,16 +33,17 @@ function simulateIncomingSms() {
     ok(incomingSms, "incoming sms");
     ok(incomingSms.id, "sms id");
     inSmsId = incomingSms.id;
     is(incomingSms.body, inText, "msg body");
     is(incomingSms.delivery, "received", "delivery");
     is(incomingSms.read, false, "read");
     is(incomingSms.receiver, null, "receiver");
     is(incomingSms.sender, remoteNumber, "sender");
+    is(incomingSms.messageClass, "normal", "messageClass");
     ok(incomingSms.timestamp instanceof Date, "timestamp is instanceof date");
     // The max resolution of the SCTS (SMS Centre TimeStamp) is one second
     // therefore we want to compare in seconds not milliseconds. No need to
     // round received sms timestamp, the value is in milliseconds but at
     // seconds resolution already (always ends with 000) so just convert
     inSmsTime = Math.floor(incomingSms.timestamp.getTime() / 1000);
     log("Received SMS (id: " + inSmsId + ") timestamp: " + inSmsTime + ".");
     if(outSmsTime) {
@@ -79,16 +80,17 @@ function sendSms() {
     ok(sentSms, "outgoing sms");
     ok(sentSms.id, "sms id");
     outSmsId = sentSms.id;
     is(sentSms.body, outText, "msg body");
     is(sentSms.delivery, "sent", "delivery");
     is(sentSms.read, true, "read");
     is(sentSms.receiver, remoteNumber, "receiver");
     is(sentSms.sender, null, "sender");
+    is(sentSms.messageClass, "normal", "messageClass");
     ok(sentSms.timestamp instanceof Date, "timestamp is instanceof date");
     // The max resolution of the SCTS (SMS Centre TimeStamp) is one second
     // therefore we want to compare in seconds not milliseconds. Round the
     // sent sms timestamp to nearest second.
     outSmsTime = Math.round(sentSms.timestamp.getTime() / 1000);
     log("Sent SMS (id: " + outSmsId + ") timestamp: " + outSmsTime + ".");
 
     if (gotSmsOnsent && gotReqOnsuccess) { verifyTimeStamps(); }
--- a/dom/sms/tests/test_smsservice_createsmsmessage.js
+++ b/dom/sms/tests/test_smsservice_createsmsmessage.js
@@ -27,36 +27,37 @@ function newMessage() {
 function run_test() {
   run_next_test();
 }
 
 /**
  * Ensure an SmsMessage object created has sensible initial values.
  */
 add_test(function test_interface() {
-  let sms = newMessage(null, "sent", "pending", null, null, null, new Date(),
-                       true);
+  let sms = newMessage(null, "sent", "pending", null, null, null, "normal",
+                       new Date(), true);
   do_check_true(sms instanceof Ci.nsIDOMMozSmsMessage);
   do_check_eq(sms.id, 0);
   do_check_eq(sms.delivery, "sent");
   do_check_eq(sms.deliveryStatus, "pending");
   do_check_eq(sms.receiver, null);
   do_check_eq(sms.sender, null);
   do_check_eq(sms.body, null);
+  do_check_eq(sms.messageClass, "normal");
   do_check_true(sms.timestamp instanceof Date);
   do_check_true(sms.read);
   run_next_test();
 });
 
 /**
  * Verify that attributes are read-only.
  */
 add_test(function test_readonly_attributes() {
   let sms = newMessage(null, "received", "success", null, null, null,
-                       new Date(), true);
+                       "normal", new Date(), true);
 
   sms.id = 1;
   do_check_eq(sms.id, 0);
 
   sms.delivery = "sent";
   do_check_eq(sms.delivery, "received");
 
   sms.deliveryStatus = "pending";
@@ -66,143 +67,170 @@ add_test(function test_readonly_attribut
   do_check_eq(sms.receiver, null);
 
   sms.sender = "a sender";
   do_check_eq(sms.sender, null);
 
   sms.body = "a body";
   do_check_eq(sms.body, null);
 
+  sms.messageClass = "class-0";
+  do_check_eq(sms.messageClass, "normal");
+
   let oldTimestamp = sms.timestamp.getTime();
   sms.timestamp = new Date();
   do_check_eq(sms.timestamp.getTime(), oldTimestamp);
 
   sms.read = false;
   do_check_true(sms.read);
 
   run_next_test();
 });
 
 /**
  * Test supplying the timestamp as a number of milliseconds.
  */
 add_test(function test_timestamp_number() {
   let ts = Date.now();
   let sms = newMessage(42, "sent", "pending", "the sender", "the receiver",
-                       "the body", ts, true);
+                       "the body", "normal", ts, true);
   do_check_eq(sms.id, 42);
   do_check_eq(sms.delivery, "sent");
   do_check_eq(sms.deliveryStatus, "pending");
   do_check_eq(sms.sender, "the sender");
   do_check_eq(sms.receiver, "the receiver");
   do_check_eq(sms.body, "the body");
+  do_check_eq(sms.messageClass, "normal");
   do_check_true(sms.timestamp instanceof Date);
   do_check_eq(sms.timestamp.getTime(), ts);
   do_check_true(sms.read);
   run_next_test();
 });
 
 /**
  * Test supplying the timestamp as a Date object.
  */
 add_test(function test_timestamp_date() {
   let date = new Date();
   let sms = newMessage(42, "sent", "pending", "the sender", "the receiver",
-                       "the body", date, true);
+                       "the body", "normal", date, true);
   do_check_eq(sms.id, 42);
   do_check_eq(sms.delivery, "sent");
   do_check_eq(sms.deliveryStatus, "pending");
   do_check_eq(sms.sender, "the sender");
   do_check_eq(sms.receiver, "the receiver");
   do_check_eq(sms.body, "the body");
+  do_check_eq(sms.messageClass, "normal");
   do_check_true(sms.timestamp instanceof Date);
   do_check_eq(sms.timestamp.getTime(), date.getTime());
   do_check_true(sms.read);
   run_next_test();
 });
 
 /**
  * Test that a floating point number for the timestamp is not allowed.
  */
 add_test(function test_invalid_timestamp_float() {
   do_check_throws(function() {
     newMessage(42, "sent", "pending", "the sender", "the receiver", "the body",
-               3.1415, true);
+               "normal", 3.1415, true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that a null value for the timestamp is not allowed.
  */
 add_test(function test_invalid_timestamp_null() {
   do_check_throws(function() {
     newMessage(42, "sent", "pending", "the sender", "the receiver", "the body",
-               null, true);
+               "normal", null, true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that undefined for the timestamp is not allowed.
  */
 add_test(function test_invalid_timestamp_undefined() {
   do_check_throws(function() {
     newMessage(42, "sent", "pending", "the sender", "the receiver", "the body",
-               undefined, true);
+               "normal", undefined, true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that a random object for the timestamp is not allowed.
  */
 add_test(function test_invalid_timestamp_object() {
   do_check_throws(function() {
     newMessage(42, "sent", "pending", "the sender", "the receiver", "the body",
-               {}, true);
+               "normal", {}, true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that an invalid delivery string is not accepted.
  */
 add_test(function test_invalid_delivery_string() {
   do_check_throws(function() {
     newMessage(42, "this is invalid", "pending", "the sender", "the receiver",
-               "the body", new Date(), true);
+               "the body", "normal", new Date(), true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that a number is not accepted for the 'delivery' argument.
  */
 add_test(function test_invalid_delivery_string() {
   do_check_throws(function() {
     newMessage(42, 1, "pending", "the sender", "the receiver", "the body",
-               new Date(), true);
+               "normal", new Date(), true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that an invalid delivery status string is not accepted.
  */
 add_test(function test_invalid_delivery_status_string() {
   do_check_throws(function() {
     newMessage(42, "sent", "this is invalid", "the sender", "the receiver",
-               "the body", new Date(), true);
+               "the body", "normal", new Date(), true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that a number is not accepted for the 'deliveryStatus' argument.
  */
 add_test(function test_invalid_delivery_status_string() {
   do_check_throws(function() {
     newMessage(42, "sent", 1, "the sender", "the receiver", "the body",
-               new Date(), true);
+               "normal", new Date(), true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
+
+/**
+ * Test that an invalid message class string is not accepted.
+ */
+add_test(function test_invalid_message_class_string() {
+  do_check_throws(function() {
+    newMessage(42, "sent", "pending", "the sender", "the receiver",
+               "the body", "this is invalid", new Date(), true);
+  }, Cr.NS_ERROR_INVALID_ARG);
+  run_next_test();
+});
+
+/**
+ * Test that a number is not accepted for the 'messageClass' argument.
+ */
+add_test(function test_invalid_message_class_string() {
+  do_check_throws(function() {
+    newMessage(42, "sent", "pending", "the sender", "the receiver", "the body",
+               1, new Date(), true);
+  }, Cr.NS_ERROR_INVALID_ARG);
+  run_next_test();
+});
--- a/dom/system/OSFileConstants.cpp
+++ b/dom/system/OSFileConstants.cpp
@@ -375,16 +375,23 @@ static dom::ConstantSpec gLibcProperties
 
 #if defined(DT_UNKNOWN)
   // Position of field |d_type| in |dirent|
   // Not strictly posix, but seems defined on all platforms
   // except mingw32.
   { "OSFILE_OFFSETOF_DIRENT_D_TYPE", INT_TO_JSVAL(offsetof (struct dirent, d_type)) },
 #endif // defined(DT_UNKNOWN)
 
+  // Under MacOS X, |dirfd| is a macro rather than a function, so we
+  // need a little help to get it to work
+#if defined(dirfd)
+  { "OSFILE_SIZEOF_DIR", INT_TO_JSVAL(sizeof (DIR)) },
+
+  { "OSFILE_OFFSETOF_DIR_DD_FD", INT_TO_JSVAL(offsetof (DIR, __dd_fd)) },
+#endif
 
   // Defining |stat|
 
   { "OSFILE_SIZEOF_STAT", INT_TO_JSVAL(sizeof (struct stat)) },
 
   { "OSFILE_OFFSETOF_STAT_ST_MODE", INT_TO_JSVAL(offsetof (struct stat, st_mode)) },
   { "OSFILE_OFFSETOF_STAT_ST_UID", INT_TO_JSVAL(offsetof (struct stat, st_uid)) },
   { "OSFILE_OFFSETOF_STAT_ST_GID", INT_TO_JSVAL(offsetof (struct stat, st_gid)) },
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -1225,37 +1225,40 @@ RadioInterfaceLayer.prototype = {
     if (mwi) {
       mwi.returnNumber = message.sender || null;
       mwi.returnMessage = message.fullBody || null;
       this._sendTargetMessage("voicemail", "RIL:VoicemailNotification", mwi);
       return;
     }
 
     let id = -1;
-    if (message.messageClass != RIL.PDU_DCS_MSG_CLASS_0) {
+    if (message.messageClass != RIL.GECKO_SMS_MESSAGE_CLASSES[RIL.PDU_DCS_MSG_CLASS_0]) {
       id = gSmsDatabaseService.saveReceivedMessage(message.sender || null,
                                                    message.fullBody || null,
+                                                   message.messageClass,
                                                    message.timestamp);
     }
     let sms = gSmsService.createSmsMessage(id,
                                            DOM_SMS_DELIVERY_RECEIVED,
                                            RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
                                            message.sender || null,
                                            message.receiver || null,
                                            message.fullBody || null,
+                                           message.messageClass,
                                            message.timestamp,
                                            false);
 
     gSystemMessenger.broadcastMessage("sms-received",
                                       {id: id,
                                        delivery: DOM_SMS_DELIVERY_RECEIVED,
                                        deliveryStatus: RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
                                        sender: message.sender || null,
                                        receiver: message.receiver || null,
                                        body: message.fullBody || null,
+                                       messageClass: message.messageClass,
                                        timestamp: message.timestamp,
                                        read: false});
     Services.obs.notifyObservers(sms, kSmsReceivedObserverTopic, null);
   },
 
   /**
    * Local storage for sent SMS messages.
    */
@@ -1275,25 +1278,27 @@ RadioInterfaceLayer.prototype = {
     debug("handleSmsSent: " + JSON.stringify(message));
 
     let options = this._sentSmsEnvelopes[message.envelopeId];
     if (!options) {
       return;
     }
 
     let timestamp = Date.now();
+    let messageClass = RIL.GECKO_SMS_MESSAGE_CLASSES[RIL.PDU_DCS_MSG_CLASS_NORMAL];
     let id = gSmsDatabaseService.saveSentMessage(options.number,
                                                  options.fullBody,
                                                  timestamp);
     let sms = gSmsService.createSmsMessage(id,
                                            DOM_SMS_DELIVERY_SENT,
                                            RIL.GECKO_SMS_DELIVERY_STATUS_PENDING,
                                            null,
                                            options.number,
                                            options.fullBody,
+                                           messageClass,
                                            timestamp,
                                            true);
 
     if (!options.requestStatusReport) {
       // No more used if STATUS-REPORT not requested.
       delete this._sentSmsEnvelopes[message.envelopeId];
     } else {
       options.id = id;
@@ -1309,24 +1314,26 @@ RadioInterfaceLayer.prototype = {
     debug("handleSmsDelivery: " + JSON.stringify(message));
 
     let options = this._sentSmsEnvelopes[message.envelopeId];
     if (!options) {
       return;
     }
     delete this._sentSmsEnvelopes[message.envelopeId];
 
+    let messageClass = RIL.GECKO_SMS_MESSAGE_CLASSES[RIL.PDU_DCS_MSG_CLASS_NORMAL];
     gSmsDatabaseService.setMessageDeliveryStatus(options.id,
                                                  message.deliveryStatus);
     let sms = gSmsService.createSmsMessage(options.id,
                                            DOM_SMS_DELIVERY_SENT,
                                            message.deliveryStatus,
                                            null,
                                            options.number,
                                            options.fullBody,
+                                           messageClass,
                                            options.timestamp,
                                            true);
 
     let topic = (message.deliveryStatus == RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS)
                 ? kSmsDeliverySuccessObserverTopic
                 : kSmsDeliveryErrorObserverTopic;
     Services.obs.notifyObservers(sms, topic, null);
   },
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -959,31 +959,38 @@ const PDU_PID_ANSI_136_R_DATA           
 const PDU_PID_ME_DATA_DOWNLOAD             = 0x7D;
 const PDU_PID_ME_DEPERSONALIZATION         = 0x7E;
 const PDU_PID_USIM_DATA_DOWNLOAD           = 0x7F;
 
 // DCS - Data Coding Scheme
 const PDU_DCS_MSG_CODING_7BITS_ALPHABET  = 0x00;
 const PDU_DCS_MSG_CODING_8BITS_ALPHABET  = 0x04;
 const PDU_DCS_MSG_CODING_16BITS_ALPHABET = 0x08;
-const PDU_DCS_MSG_CLASS_UNKNOWN          = 0xFF;
+const PDU_DCS_MSG_CLASS_NORMAL           = 0xFF;
 const PDU_DCS_MSG_CLASS_0                = 0x00;
-const PDU_DCS_MSG_CLASS_ME_SPECIFIC      = 0x01;
-const PDU_DCS_MSG_CLASS_SIM_SPECIFIC     = 0x02;
-const PDU_DCS_MSG_CLASS_TE_SPECIFIC      = 0x03;
+const PDU_DCS_MSG_CLASS_1                = 0x01;
+const PDU_DCS_MSG_CLASS_2                = 0x02;
+const PDU_DCS_MSG_CLASS_3                = 0x03;
 const PDU_DCS_CODING_GROUP_BITS          = 0xF0;
 const PDU_DCS_MSG_CLASS_BITS             = 0x03;
 const PDU_DCS_MWI_ACTIVE_BITS            = 0x08;
 const PDU_DCS_MWI_ACTIVE_VALUE           = 0x08;
 const PDU_DCS_MWI_TYPE_BITS              = 0x03;
 const PDU_DCS_MWI_TYPE_VOICEMAIL         = 0x00;
 const PDU_DCS_MWI_TYPE_FAX               = 0x01;
 const PDU_DCS_MWI_TYPE_EMAIL             = 0x02;
 const PDU_DCS_MWI_TYPE_OTHER             = 0x03;
 
+const GECKO_SMS_MESSAGE_CLASSES = {};
+GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL] = "normal";
+GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]      = "class-0";
+GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_1]      = "class-1";
+GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]      = "class-2";
+GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_3]      = "class-3";
+
 // Because service center timestamp omit the century. Yay.
 const PDU_TIMESTAMP_YEAR_OFFSET = 2000;
 
 // See 9.2.3.24 TP‑User Data (TP‑UD)
 const PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT         = 0x00;
 const PDU_IEI_SPECIAL_SMS_MESSAGE_INDICATION           = 0x01;
 const PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_8BIT  = 0x04;
 const PDU_IEI_APPLICATION_PORT_ADDRESSING_SCHEME_16BIT = 0x05;
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -3746,17 +3746,17 @@ let RIL = {
 
     if (message.epid == PDU_PID_SHORT_MESSAGE_TYPE_0) {
       // `A short message type 0 indicates that the ME must acknowledge receipt
       // of the short message but shall discard its contents.` ~ 3GPP TS 23.040
       // 9.2.3.9
       return PDU_FCS_OK;
     }
 
-    if (message.messageClass == PDU_DCS_MSG_CLASS_SIM_SPECIFIC) {
+    if (message.messageClass == GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]) {
       switch (message.epid) {
         case PDU_PID_ANSI_136_R_DATA:
         case PDU_PID_USIM_DATA_DOWNLOAD:
           if (this.isICCServiceAvailable("DATA_DOWNLOAD_SMS_PP")) {
             // `If the service "data download via SMS Point-to-Point" is
             // allocated and activated in the (U)SIM Service Table, ... then the
             // ME shall pass the message transparently to the UICC using the
             // ENVELOPE (SMS-PP DOWNLOAD).` ~ 3GPP TS 31.111 7.1.1.1
@@ -3772,23 +3772,23 @@ let RIL = {
           // EFsms in accordance with TS 31.102` ~ 3GPP TS 31.111 7.1.1.1
         default:
           this.writeSmsToSIM(message);
           break;
       }
     }
 
     // TODO: Bug 739143: B2G SMS: Support SMS Storage Full event
-    if ((message.messageClass != PDU_DCS_MSG_CLASS_0) && !true) {
+    if ((message.messageClass != GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]) && !true) {
       // `When a mobile terminated message is class 0..., the MS shall display
       // the message immediately and send a ACK to the SC ..., irrespective of
       // whether there is memory available in the (U)SIM or ME.` ~ 3GPP 23.038
       // clause 4.
 
-      if (message.messageClass == PDU_DCS_MSG_CLASS_SIM_SPECIFIC) {
+      if (message.messageClass == GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]) {
         // `If all the short message storage at the MS is already in use, the
         // MS shall return "memory capacity exceeded".` ~ 3GPP 23.038 clause 4.
         return PDU_FCS_MEMORY_CAPACITY_EXCEEDED;
       }
 
       return PDU_FCS_UNSPECIFIED;
     }
 
@@ -3804,17 +3804,17 @@ let RIL = {
       }
     }
 
     if (message) {
       message.rilMessageType = "sms-received";
       this.sendDOMMessage(message);
     }
 
-    if (message.messageClass == PDU_DCS_MSG_CLASS_SIM_SPECIFIC) {
+    if (message.messageClass == GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]) {
       // `MS shall ensure that the message has been to the SMS data field in
       // the (U)SIM before sending an ACK to the SC.`  ~ 3GPP 23.038 clause 4
       return PDU_FCS_RESERVED;
     }
 
     return PDU_FCS_OK;
   },
 
@@ -5920,17 +5920,17 @@ let GsmPDUHelper = {
    *
    * @see 3GPP TS 23.040 9.2.3.10, 3GPP TS 23.038 4.
    */
   readDataCodingScheme: function readDataCodingScheme(msg) {
     let dcs = this.readHexOctet();
     if (DEBUG) debug("PDU: read dcs: " + dcs);
 
     // No message class by default.
-    let messageClass = PDU_DCS_MSG_CLASS_UNKNOWN;
+    let messageClass = PDU_DCS_MSG_CLASS_NORMAL;
     // 7 bit is the default fallback encoding.
     let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
     switch (dcs & PDU_DCS_CODING_GROUP_BITS) {
       case 0x40: // bits 7..4 = 01xx
       case 0x50:
       case 0x60:
       case 0x70:
         // Bit 5..0 are coded exactly the same as Group 00xx
@@ -5997,17 +5997,17 @@ let GsmPDUHelper = {
 
       default:
         // Falling back to default encoding.
         break;
     }
 
     msg.dcs = dcs;
     msg.encoding = encoding;
-    msg.messageClass = messageClass;
+    msg.messageClass = GECKO_SMS_MESSAGE_CLASSES[messageClass];
 
     if (DEBUG) debug("PDU: message encoding is " + encoding + " bit.");
   },
 
   /**
    * Read GSM TP-Service-Centre-Time-Stamp(TP-SCTS).
    *
    * @see 3GPP TS 23.040 9.2.3.11
--- a/dom/system/gonk/tests/test_ril_worker_sms.js
+++ b/dom/system/gonk/tests/test_ril_worker_sms.js
@@ -101,82 +101,116 @@ add_test(function test_GsmPDUHelper_read
       do_check_eq(msg.mwi.active, mwi.active);
       do_check_eq(msg.mwi.discard, mwi.discard);
       do_check_eq(msg.mwi.msgCount, mwi.msgCount);
     }
   }
 
   // Group 00xx
   //   Bit 3 and 2 indicate the character set being used.
-  test_dcs(0x00, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
-  test_dcs(0x04, PDU_DCS_MSG_CODING_8BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
-  test_dcs(0x08, PDU_DCS_MSG_CODING_16BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
-  test_dcs(0x0C, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
+  test_dcs(0x00, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
+  test_dcs(0x04, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
+  test_dcs(0x08, PDU_DCS_MSG_CODING_16BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
+  test_dcs(0x0C, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
   //   Bit 4, if set to 0, indicates that bits 1 to 0 are reserved and have no
   //   message class meaning.
-  test_dcs(0x01, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
-  test_dcs(0x02, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
-  test_dcs(0x03, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
+  test_dcs(0x01, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
+  test_dcs(0x02, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
+  test_dcs(0x03, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
   //   Bit 4, if set to 1, indicates that bits 1 to 0 have a message class meaning.
-  test_dcs(0x10, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_0);
-  test_dcs(0x11, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_ME_SPECIFIC);
-  test_dcs(0x12, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_SIM_SPECIFIC);
-  test_dcs(0x13, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_TE_SPECIFIC);
+  test_dcs(0x10, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
+  test_dcs(0x11, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_1]);
+  test_dcs(0x12, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]);
+  test_dcs(0x13, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_3]);
 
   // Group 01xx
-  test_dcs(0x50, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_0);
+  test_dcs(0x50, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
 
   // Group 1000..1011: reserved
-  test_dcs(0x8F, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
-  test_dcs(0x9F, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
-  test_dcs(0xAF, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
-  test_dcs(0xBF, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN);
+  test_dcs(0x8F, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
+  test_dcs(0x9F, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
+  test_dcs(0xAF, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
+  test_dcs(0xBF, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
 
   // Group 1100: Message Waiting Indication Group: Discard Message
   //   Bit 3 indicates Indication Sense:
-  test_dcs(0xC0, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+  test_dcs(0xC0, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
            {active: false, discard: true, msgCount: 0});
-  test_dcs(0xC8, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+  test_dcs(0xC8, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
            {active: true, discard: true, msgCount: -1});
   //   Bit 2 is reserved, and set to 0:
-  test_dcs(0xCC, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+  test_dcs(0xCC, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
            {active: true, discard: true, msgCount: -1});
 
   // Group 1101: Message Waiting Indication Group: Store Message
   //   Bit 3 indicates Indication Sense:
-  test_dcs(0xD0, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+  test_dcs(0xD0, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
            {active: false, discard: false, msgCount: 0});
-  test_dcs(0xD8, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+  test_dcs(0xD8, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
            {active: true, discard: false, msgCount: -1});
   //   Bit 2 is reserved, and set to 0:
-  test_dcs(0xDC, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+  test_dcs(0xDC, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
            {active: true, discard: false, msgCount: -1});
 
   // Group 1110: Message Waiting Indication Group: Store Message, UCS2
   //   Bit 3 indicates Indication Sense:
-  test_dcs(0xE0, PDU_DCS_MSG_CODING_16BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+  test_dcs(0xE0, PDU_DCS_MSG_CODING_16BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
            {active: false, discard: false, msgCount: 0});
-  test_dcs(0xE8, PDU_DCS_MSG_CODING_16BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+  test_dcs(0xE8, PDU_DCS_MSG_CODING_16BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
            {active: true, discard: false, msgCount: -1});
   //   Bit 2 is reserved, and set to 0:
-  test_dcs(0xEC, PDU_DCS_MSG_CODING_16BITS_ALPHABET, PDU_DCS_MSG_CLASS_UNKNOWN,
+  test_dcs(0xEC, PDU_DCS_MSG_CODING_16BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
            {active: true, discard: false, msgCount: -1});
 
   // Group 1111
-  test_dcs(0xF0, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_0);
-  test_dcs(0xF1, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_ME_SPECIFIC);
-  test_dcs(0xF2, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_SIM_SPECIFIC);
-  test_dcs(0xF3, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_TE_SPECIFIC);
-  test_dcs(0xF4, PDU_DCS_MSG_CODING_8BITS_ALPHABET, PDU_DCS_MSG_CLASS_0);
-  test_dcs(0xF5, PDU_DCS_MSG_CODING_8BITS_ALPHABET, PDU_DCS_MSG_CLASS_ME_SPECIFIC);
-  test_dcs(0xF6, PDU_DCS_MSG_CODING_8BITS_ALPHABET, PDU_DCS_MSG_CLASS_SIM_SPECIFIC);
-  test_dcs(0xF7, PDU_DCS_MSG_CODING_8BITS_ALPHABET, PDU_DCS_MSG_CLASS_TE_SPECIFIC);
+  test_dcs(0xF0, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
+  test_dcs(0xF1, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_1]);
+  test_dcs(0xF2, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]);
+  test_dcs(0xF3, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_3]);
+  test_dcs(0xF4, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
+  test_dcs(0xF5, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_1]);
+  test_dcs(0xF6, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]);
+  test_dcs(0xF7, PDU_DCS_MSG_CODING_8BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_3]);
   //   Bit 3 is reserved and should be set to 0, but if it doesn't we should
   //   ignore it.
-  test_dcs(0xF8, PDU_DCS_MSG_CODING_7BITS_ALPHABET, PDU_DCS_MSG_CLASS_0);
+  test_dcs(0xF8, PDU_DCS_MSG_CODING_7BITS_ALPHABET,
+           GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0]);
 
   run_next_test();
 });
 
 /**
  * Verify RadioInterfaceLayer#_countGsm7BitSeptets() and
  * GsmPDUHelper#writeStringAsSeptets() algorithm match each other.
  */
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -397,33 +397,37 @@ Telephony::CallStateChanged(uint32_t aCa
     }
 
     // Change state.
     modifiedCall->ChangeState(aCallState);
 
     return NS_OK;
   }
 
-  // Didn't know anything about this call before now, must be incoming.
-  NS_ASSERTION(aCallState == nsIRadioInterfaceLayer::CALL_STATE_INCOMING,
+  // Didn't know anything about this call before now, could be 'incoming' or
+  // 'dialing' that was placed by others.
+  NS_ASSERTION(aCallState == nsIRadioInterfaceLayer::CALL_STATE_INCOMING ||
+               aCallState == nsIRadioInterfaceLayer::CALL_STATE_DIALING,
                "Serious logic problem here!");
 
   nsRefPtr<TelephonyCall> call =
     TelephonyCall::Create(this, aNumber, aCallState, aCallIndex);
   NS_ASSERTION(call, "This should never fail!");
 
   NS_ASSERTION(mCalls.Contains(call), "Should have auto-added new call!");
 
-  // Dispatch incoming event.
-  nsRefPtr<CallEvent> event = CallEvent::Create(call);
-  NS_ASSERTION(event, "This should never fail!");
+  if (aCallState == nsIRadioInterfaceLayer::CALL_STATE_INCOMING) {
+    // Dispatch incoming event.
+    nsRefPtr<CallEvent> event = CallEvent::Create(call);
+    NS_ASSERTION(event, "This should never fail!");
 
-  nsresult rv =
-    event->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("incoming"));
-  NS_ENSURE_SUCCESS(rv, rv);
+    nsresult rv =
+      event->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("incoming"));
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Telephony::EnumerateCallState(uint32_t aCallIndex, uint16_t aCallState,
                               const nsAString& aNumber, bool aIsActive,
                               bool* aContinue)
--- a/editor/libeditor/html/crashtests/407277-1.html
+++ b/editor/libeditor/html/crashtests/407277-1.html
@@ -1,7 +1,7 @@
 <html>
 <head>
 </head>
-<body style="margin: -moz-initial;" 
+<body style="margin: initial;" 
       contenteditable="true" 
       onload="document.execCommand('outdent', false, null);"></body>
 </html>
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -84,17 +84,17 @@ public class GeckoAppShell
     public static native void loadNSSLibsNative(String apkName, boolean shouldExtract);
     public static native void onChangeNetworkLinkStatus(String status);
     public static native void reportJavaCrash(String stack);
 
     public static native void processNextNativeEvent();
 
     public static native void notifyBatteryChange(double aLevel, boolean aCharging, double aRemainingTime);
 
-    public static native void notifySmsReceived(String aSender, String aBody, long aTimestamp);
+    public static native void notifySmsReceived(String aSender, String aBody, int aMessageClass, long aTimestamp);
     public static native int  saveMessageInSentbox(String aReceiver, String aBody, long aTimestamp);
     public static native void notifySmsSent(int aId, String aReceiver, String aBody, long aTimestamp, int aRequestId, long aProcessId);
     public static native void notifySmsDelivery(int aId, int aDeliveryStatus, String aReceiver, String aBody, long aTimestamp);
     public static native void notifySmsSendFailed(int aError, int aRequestId, long aProcessId);
     public static native void notifyGetSms(int aId, int aDeliveryStatus, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
     public static native void notifyGetSmsFailed(int aError, int aRequestId, long aProcessId);
     public static native void notifySmsDeleted(boolean aDeleted, int aRequestId, long aProcessId);
     public static native void notifySmsDeleteFailed(int aError, int aRequestId, long aProcessId);
--- a/embedding/android/GeckoSmsManager.java
+++ b/embedding/android/GeckoSmsManager.java
@@ -27,16 +27,18 @@ import android.net.Uri;
 
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage;
 
+import static android.telephony.SmsMessage.MessageClass;
+
 /**
  * This class is returning unique ids for PendingIntent requestCode attribute.
  * There are only |Integer.MAX_VALUE - Integer.MIN_VALUE| unique IDs available,
  * and they wrap around.
  */
 class PendingIntentUID
 {
   static private int sUID = Integer.MIN_VALUE;
@@ -335,16 +337,26 @@ public class GeckoSmsManager
    * android.provider.Telephony.Sms.STATUS_*. Duplicated because they're not
    * part of Android public API.
    */
   private final static int kInternalDeliveryStatusNone     = -1;
   private final static int kInternalDeliveryStatusComplete = 0;
   private final static int kInternalDeliveryStatusPending  = 32;
   private final static int kInternalDeliveryStatusFailed   = 64;
 
+  /*
+   * Keep the following values in sync with |MessageClass| in:
+   * dom/sms/src/Types.h
+   */
+  private final static int kMessageClassNormal  = 0;
+  private final static int kMessageClassClass0  = 1;
+  private final static int kMessageClassClass1  = 2;
+  private final static int kMessageClassClass2  = 3;
+  private final static int kMessageClassClass3  = 4;
+
   private final static String[] kRequiredMessageRows = new String[] { "_id", "address", "body", "date", "type", "status" };
 
   public GeckoSmsManager() {
     SmsIOThread.getInstance().start();
   }
 
   public void start() {
     IntentFilter smsFilter = new IntentFilter();
@@ -372,16 +384,17 @@ public class GeckoSmsManager
 
       Object[] pdus = (Object[]) bundle.get("pdus");
 
       for (int i=0; i<pdus.length; ++i) {
         SmsMessage msg = SmsMessage.createFromPdu((byte[])pdus[i]);
 
         GeckoAppShell.notifySmsReceived(msg.getDisplayOriginatingAddress(),
                                         msg.getDisplayMessageBody(),
+                                        getGeckoMessageClass(msg.getMessageClass()),
                                         System.currentTimeMillis());
       }
 
       return;
     }
 
     if (intent.getAction().equals(ACTION_SMS_SENT) ||
         intent.getAction().equals(ACTION_SMS_DELIVERED)) {
@@ -934,16 +947,31 @@ public class GeckoSmsManager
       return kDeliveryStatusError;
     }
     if (aDeliveryStatus >= kInternalDeliveryStatusPending) {
       return kDeliveryStatusPending;
     }
     return kDeliveryStatusSuccess;
   }
 
+  private int getGeckoMessageClass(MessageClass aMessageClass) {
+    switch (aMessageClass) {
+      case UNKNOWN:
+        return kMessageClassNormal;
+      case CLASS_0:
+        return kMessageClassClass0;
+      case CLASS_1:
+        return kMessageClassClass1;
+      case CLASS_2:
+        return kMessageClassClass2;
+      case CLASS_3:
+        return kMessageClassClass3;
+    }
+  }
+
   class IdTooHighException extends Exception {
     private static final long serialVersionUID = 395697882128640L;
   }
 
   class InvalidTypeException extends Exception {
     private static final long serialVersionUID = 23359904803795434L;
   }
 
--- a/gfx/2d/SourceSurfaceD2D.cpp
+++ b/gfx/2d/SourceSurfaceD2D.cpp
@@ -38,16 +38,20 @@ bool
 SourceSurfaceD2D::IsValid() const
 {
   return mDevice == Factory::GetDirect3D10Device();
 }
 
 TemporaryRef<DataSourceSurface>
 SourceSurfaceD2D::GetDataSurface()
 {
+  RefPtr<DataSourceSurfaceD2D> result = new DataSourceSurfaceD2D(this);
+  if (result->IsValid()) {
+    return result;
+  }
   return nullptr;
 }
 
 bool
 SourceSurfaceD2D::InitFromData(unsigned char *aData,
                                const IntSize &aSize,
                                int32_t aStride,
                                SurfaceFormat aFormat,
@@ -117,10 +121,129 @@ SourceSurfaceD2D::InitFromTexture(ID3D10
 }
 
 uint32_t
 SourceSurfaceD2D::GetByteSize() const
 {
   return mSize.width * mSize.height * BytesPerPixel(mFormat);
 }
 
+DataSourceSurfaceD2D::DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface)
+  : mTexture(nullptr)
+  , mFormat(aSourceSurface->mFormat)
+  , mSize(aSourceSurface->mSize)
+  , mMapped(false)
+{
+  // We allocate ourselves a regular D3D surface (sourceTexture) and paint the
+  // D2D bitmap into it via a DXGI render target. Then we need to copy
+  // sourceTexture into a staging texture (mTexture), which we will lazily map
+  // to get the data.
+
+  CD3D10_TEXTURE2D_DESC desc(DXGIFormat(mFormat), mSize.width, mSize.height);
+  desc.MipLevels = 1;
+  desc.Usage = D3D10_USAGE_DEFAULT;
+  desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
+  RefPtr<ID3D10Texture2D> sourceTexture;
+  HRESULT hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr,
+                                                        byRef(sourceTexture));
+  if (FAILED(hr)) {
+    gfxWarning() << "Failed to create texture. Code: " << hr;
+    return;
+  }
+
+  RefPtr<IDXGISurface> dxgiSurface;
+  hr = sourceTexture->QueryInterface((IDXGISurface**)byRef(dxgiSurface));
+  if (FAILED(hr)) {
+    gfxWarning() << "Failed to create DXGI surface. Code: " << hr;
+    return;
+  }
+
+  D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties(
+            D2D1_RENDER_TARGET_TYPE_DEFAULT,
+            D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
+
+  RefPtr<ID2D1RenderTarget> renderTarget;
+  hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(dxgiSurface,
+                                                               &rtProps,
+                                                               byRef(renderTarget));
+  if (FAILED(hr)) {
+    gfxWarning() << "Failed to create render target. Code: " << hr;
+    return;
+  }
+
+  renderTarget->BeginDraw();
+  renderTarget->DrawBitmap(aSourceSurface->mBitmap,
+                           D2D1::RectF(0, 0, mSize.width, mSize.height));
+  renderTarget->EndDraw();
+
+  desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
+  desc.Usage = D3D10_USAGE_STAGING;
+  desc.BindFlags = 0;
+  hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr, byRef(mTexture));
+  if (FAILED(hr)) {
+    gfxWarning() << "Failed to create staging texture. Code: " << hr;
+    mTexture = nullptr;
+    return;
+  }
+
+  aSourceSurface->mDevice->CopyResource(mTexture, sourceTexture);
+}
+
+DataSourceSurfaceD2D::~DataSourceSurfaceD2D()
+{
+  if (mMapped) {
+    mTexture->Unmap(0);
+  }
+}
+
+unsigned char*
+DataSourceSurfaceD2D::GetData()
+{
+  EnsureMappedTexture();
+  if (!mMapped) {
+    return nullptr;
+  }
+
+  return reinterpret_cast<unsigned char*>(mData.pData);
+}
+
+int32_t
+DataSourceSurfaceD2D::Stride()
+{
+  EnsureMappedTexture();
+  if (!mMapped) {
+    return 0;
+  }
+
+  return mData.RowPitch;
+}
+
+IntSize
+DataSourceSurfaceD2D::GetSize() const
+{
+  return mSize;
+}
+
+SurfaceFormat
+DataSourceSurfaceD2D::GetFormat() const
+{
+  return mFormat;
+}
+
+void
+DataSourceSurfaceD2D::EnsureMappedTexture()
+{
+  if (mMapped ||
+      !mTexture) {
+    return;
+  }
+
+  HRESULT hr = mTexture->Map(0, D3D10_MAP_READ, 0, &mData);
+  if (FAILED(hr)) {
+    gfxWarning() << "Failed to map texture. Code: " << hr;
+    mTexture = nullptr;
+  } else {
+    mMapped = true;
+  }
+}
+
 }
 }
--- a/gfx/2d/SourceSurfaceD2D.h
+++ b/gfx/2d/SourceSurfaceD2D.h
@@ -8,16 +8,18 @@
 
 #include "2D.h"
 #include "HelpersD2D.h"
 #include <vector>
 
 namespace mozilla {
 namespace gfx {
 
+class DataSourceSurfaceD2D;
+
 class SourceSurfaceD2D : public SourceSurface
 {
 public:
   SourceSurfaceD2D();
   ~SourceSurfaceD2D();
 
   virtual SurfaceType GetType() const { return SURFACE_D2D1_BITMAP; }
   virtual IntSize GetSize() const;
@@ -31,25 +33,54 @@ public:
   bool InitFromData(unsigned char *aData,
                     const IntSize &aSize,
                     int32_t aStride,
                     SurfaceFormat aFormat,
                     ID2D1RenderTarget *aRT);
   bool InitFromTexture(ID3D10Texture2D *aTexture,
                        SurfaceFormat aFormat,
                        ID2D1RenderTarget *aRT);
-
 private:
   friend class DrawTargetD2D;
+  friend class DataSourceSurfaceD2D;
 
   uint32_t GetByteSize() const;
 
   RefPtr<ID2D1Bitmap> mBitmap;
   // We need to keep this pointer here to check surface validity.
   RefPtr<ID3D10Device> mDevice;
   SurfaceFormat mFormat;
   IntSize mSize;
 };
 
+
+class DataSourceSurfaceD2D : public DataSourceSurface
+{
+public:
+  DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface);
+  virtual ~DataSourceSurfaceD2D();
+
+  virtual unsigned char* GetData();
+  virtual int32_t Stride();
+  virtual IntSize GetSize() const;
+  virtual SurfaceFormat GetFormat() const;
+
+  bool IsValid()
+  {
+    return mTexture;
+  }
+
+private:
+  void EnsureMappedTexture();
+
+  RefPtr<ID3D10Texture2D> mTexture;
+
+  D3D10_MAPPED_TEXTURE2D mData;
+
+  SurfaceFormat mFormat;
+  IntSize mSize;
+  bool mMapped;
+};
+
 }
 }
 
 #endif /* MOZILLA_GFX_SOURCESURFACED2D_H_ */
--- a/gfx/layers/TiledLayerBuffer.h
+++ b/gfx/layers/TiledLayerBuffer.h
@@ -241,17 +241,17 @@ TiledLayerBuffer<Derived, Tile>::Update(
   const int oldRetainedHeight = mRetainedHeight;
 
   // Pass 1: Recycle valid content from the old buffer
   // Recycle tiles from the old buffer that contain valid regions.
   // Insert placeholders tiles if we have no valid area for that tile
   // which we will allocate in pass 2.
   // TODO: Add a tile pool to reduce new allocation
   int tileX = 0;
-  int tileY;
+  int tileY = 0;
   // Iterate over the new drawing bounds in steps of tiles.
   for (int32_t x = newBound.x; x < newBound.XMost(); tileX++) {
     // Compute tileRect(x,y,width,height) in layer space coordinate
     // giving us the rect of the tile that hits the newBounds.
     int width = GetTileLength() - GetTileStart(x);
     if (x + width > newBound.XMost()) {
       width = newBound.x + newBound.width - x;
     }
--- a/gfx/layers/opengl/ReusableTileStoreOGL.cpp
+++ b/gfx/layers/opengl/ReusableTileStoreOGL.cpp
@@ -164,17 +164,17 @@ ReusableTileStoreOGL::HarvestTiles(Tiled
 
       // If the new valid region doesn't contain this tile region,
       // harvest the tile.
       nsIntRegion tileRegion;
       tileRegion.And(aOldValidRegion, nsIntRect(x, y, w, h));
 
       nsIntRegion intersectingRegion;
       bool retainTile = false;
-      if (aNewResolution != aOldResolution) {
+      if (fabs(aNewResolution.width - aOldResolution.width) > 1e-6) {
         // Reconcile resolution changes.
         // If the resolution changes, we know the backing layer will have been
         // invalidated, so retain tiles that are partially encompassed by the
         // new valid area, instead of just tiles that don't intersect at all.
         nsIntRegion transformedTileRegion(tileRegion);
         transformedTileRegion.ScaleRoundOut(scaleFactor.width, scaleFactor.height);
         if (!visibleRegion.Contains(transformedTileRegion))
           retainTile = true;
new file mode 100644
--- /dev/null
+++ b/gfx/skia/patches/0001-Bug-803063-Skia-cross-compilation-for-Windows-fails-.patch
@@ -0,0 +1,26 @@
+From 81ff1a8f5c2a7cc9e8b853101b995433a0c0fa37 Mon Sep 17 00:00:00 2001
+From: Jacek Caban <jacek@codeweavers.com>
+Date: Thu, 18 Oct 2012 15:25:08 +0200
+Subject: [PATCH] Bug 803063 - Skia cross compilation for Windows fails on
+ case sensitive OS
+
+---
+ gfx/skia/src/core/SkAdvancedTypefaceMetrics.cpp |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/gfx/skia/src/core/SkAdvancedTypefaceMetrics.cpp b/gfx/skia/src/core/SkAdvancedTypefaceMetrics.cpp
+index 370616e..b647ada 100644
+--- a/gfx/skia/src/core/SkAdvancedTypefaceMetrics.cpp
++++ b/gfx/skia/src/core/SkAdvancedTypefaceMetrics.cpp
+@@ -13,7 +13,7 @@
+ SK_DEFINE_INST_COUNT(SkAdvancedTypefaceMetrics)
+ 
+ #if defined(SK_BUILD_FOR_WIN)
+-#include <DWrite.h>
++#include <dwrite.h>
+ #endif
+ 
+ #if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID)
+-- 
+1.7.8.6
+
--- a/gfx/skia/src/core/SkAdvancedTypefaceMetrics.cpp
+++ b/gfx/skia/src/core/SkAdvancedTypefaceMetrics.cpp
@@ -8,17 +8,17 @@
 
 
 #include "SkAdvancedTypefaceMetrics.h"
 #include "SkTypes.h"
 
 SK_DEFINE_INST_COUNT(SkAdvancedTypefaceMetrics)
 
 #if defined(SK_BUILD_FOR_WIN)
-#include <DWrite.h>
+#include <dwrite.h>
 #endif
 
 #if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID)
 #include <ft2build.h>
 #include FT_FREETYPE_H
 #endif
 
 #ifdef SK_BUILD_FOR_MAC
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -332,33 +332,17 @@ nsDeviceContext::SetDPI()
 
             if (prefDPI < 0) {
                 dpi = NS_MAX(96.0f, dpi);
             }
         } else {
             dpi = 96.0f;
         }
 
-        // The number of device pixels per CSS pixel. A value <= 0 means choose
-        // automatically based on the DPI. A positive value is used as-is. This effectively
-        // controls the size of a CSS "px".
-        float devPixelsPerCSSPixel = -1.0;
-
-        nsAdoptingCString prefString = Preferences::GetCString("layout.css.devPixelsPerPx");
-        if (!prefString.IsEmpty()) {
-            devPixelsPerCSSPixel = static_cast<float>(atof(prefString));
-        }
-
-        if (devPixelsPerCSSPixel <= 0) {
-            if (mWidget) {
-                devPixelsPerCSSPixel = mWidget->GetDefaultScale();
-            } else {
-                devPixelsPerCSSPixel = 1.0;
-            }
-        }
+        double devPixelsPerCSSPixel = mWidget ? mWidget->GetDefaultScale() : 1.0;
 
         mAppUnitsPerDevNotScaledPixel =
             NS_MAX(1, NS_lround(AppUnitsPerCSSPixel() / devPixelsPerCSSPixel));
     }
 
     NS_ASSERTION(dpi != -1.0, "no dpi set");
 
     mAppUnitsPerPhysicalInch = NS_lround(dpi * mAppUnitsPerDevNotScaledPixel);
--- a/gfx/thebes/gfxQuartzNativeDrawing.cpp
+++ b/gfx/thebes/gfxQuartzNativeDrawing.cpp
@@ -14,18 +14,19 @@ enum {
 };
 
 // private Quartz routine needed here
 extern "C" {
     CG_EXTERN void CGContextSetCompositeOperation(CGContextRef, int);
 }
 
 gfxQuartzNativeDrawing::gfxQuartzNativeDrawing(gfxContext* ctx,
-                                               const gfxRect& nativeRect)
-    : mContext(ctx), mNativeRect(nativeRect)
+                                               const gfxRect& nativeRect,
+                                               gfxFloat aBackingScale)
+    : mContext(ctx), mNativeRect(nativeRect), mBackingScale(aBackingScale)
 {
     mNativeRect.RoundOut();
 }
 
 CGContextRef
 gfxQuartzNativeDrawing::BeginNativeDrawing()
 {
     NS_ASSERTION(!mQuartzSurface, "BeginNativeDrawing called when drawing already in progress");
@@ -70,24 +71,27 @@ gfxQuartzNativeDrawing::BeginNativeDrawi
 
         CGContextConcatCTM(mCGContext, CGAffineTransformMake(m.xx, m.yx,
                                                              m.xy, m.yy,
                                                              x0, y0));
 
         // bug 382049 - need to explicity set the composite operation to sourceOver
         CGContextSetCompositeOperation(mCGContext, kPrivateCGCompositeSourceOver);
     } else {
-        mQuartzSurface = new gfxQuartzSurface(mNativeRect.Size(),
+        nsIntSize backingSize(NSToIntFloor(mNativeRect.width * mBackingScale),
+                              NSToIntFloor(mNativeRect.height * mBackingScale));
+        mQuartzSurface = new gfxQuartzSurface(backingSize,
                                               gfxASurface::ImageFormatARGB32);
         if (mQuartzSurface->CairoStatus())
             return nullptr;
         mSurfaceContext = new gfxContext(mQuartzSurface);
 
         // grab the CGContextRef
         mCGContext = cairo_quartz_get_cg_context_with_clip(mSurfaceContext->GetCairo());
+        CGContextScaleCTM(mCGContext, mBackingScale, mBackingScale);
         CGContextTranslateCTM(mCGContext, -mNativeRect.X(), -mNativeRect.Y());
     }
 
     return mCGContext;
 }
 
 void
 gfxQuartzNativeDrawing::EndNativeDrawing()
@@ -96,11 +100,12 @@ gfxQuartzNativeDrawing::EndNativeDrawing
 
     cairo_quartz_finish_cg_context_with_clip(mSurfaceContext->GetCairo());
     mQuartzSurface->MarkDirty();
     if (mSurfaceContext != mContext) {
         gfxContextMatrixAutoSaveRestore save(mContext);
 
         // Copy back to destination
         mContext->Translate(mNativeRect.TopLeft());
-        mContext->DrawSurface(mQuartzSurface, mNativeRect.Size());
+        mContext->Scale(1.0f / mBackingScale, 1.0f / mBackingScale);
+        mContext->DrawSurface(mQuartzSurface, mQuartzSurface->GetSize());
     }
 }
--- a/gfx/thebes/gfxQuartzNativeDrawing.h
+++ b/gfx/thebes/gfxQuartzNativeDrawing.h
@@ -22,19 +22,31 @@ public:
      *   gfxQuartzNativeDrawing nativeDraw(ctx, nativeRect);
      *   CGContextRef cgContext = nativeDraw.BeginNativeDrawing();
      *   if (!cgContext)
      *     return NS_ERROR_FAILURE;
      *
      *     ... call Quartz operations on CGContextRef to draw to nativeRect ...
      *
      *   nativeDraw.EndNativeDrawing();
+     *
+     * aNativeRect is the size of the surface (in Quartz/Cocoa points) that
+     * will be created _if_ the gfxQuartzNativeDrawing decides to create a new
+     * surface and CGContext for its drawing operations, which it then
+     * composites into the target gfxContext.
+     *
+     * (Note that aNativeRect will be ignored if the gfxQuartzNativeDrawing
+     * uses the target gfxContext directly.)
+     *
+     * The optional aBackingScale parameter is a scaling factor that will be
+     * applied when creating and rendering into such a temporary surface.
      */
     gfxQuartzNativeDrawing(gfxContext *ctx,
-                           const gfxRect& nativeRect);
+                           const gfxRect& aNativeRect,
+                           gfxFloat aBackingScale = 1.0f);
 
     /* Returns a CGContextRef which may be used for native drawing.  This
      * CGContextRef is valid until EndNativeDrawing is called; if it is used
      * for drawing after that time, the result is undefined. */
     CGContextRef BeginNativeDrawing();
 
     /* Marks the end of native drawing */
     void EndNativeDrawing();
@@ -45,15 +57,16 @@ private:
     const gfxQuartzNativeDrawing& operator=(const gfxQuartzNativeDrawing&) MOZ_DELETE;
 
     // Final destination context
     nsRefPtr<gfxContext> mContext;
     // context that draws to mQuartzSurface; can be different from mContext
     // if mContext is not drawing to Quartz
     nsRefPtr<gfxContext> mSurfaceContext;
     gfxRect mNativeRect;
+    gfxFloat mBackingScale;
 
     // saved state
     nsRefPtr<gfxQuartzSurface> mQuartzSurface;
     CGContextRef mCGContext;
 };
 
 #endif
--- a/gfx/thebes/gfxXlibSurface.cpp
+++ b/gfx/thebes/gfxXlibSurface.cpp
@@ -210,16 +210,28 @@ gfxXlibSurface::CreateSimilarSurface(gfx
             }
         }
     }
 
     return gfxASurface::CreateSimilarSurface(aContent, aSize);
 }
 
 void
+gfxXlibSurface::Finish()
+{
+#if !defined(MOZ_PLATFORM_MAEMO)
+    if (mGLXPixmap) {
+        gl::sDefGLXLib.DestroyPixmap(mGLXPixmap);
+        mGLXPixmap = None;
+    }
+#endif
+    gfxASurface::Finish();
+}
+
+void
 gfxXlibSurface::DoSizeQuery()
 {
     // figure out width/height/depth
     Window root_ignore;
     int x_ignore, y_ignore;
     unsigned int bwidth_ignore, width, height, depth;
 
     XGetGeometry(mDisplay,
@@ -506,16 +518,24 @@ gfxXlibSurface::XRenderFormat()
     return cairo_xlib_surface_get_xrender_format(CairoSurface());
 }
 
 #if !defined(MOZ_PLATFORM_MAEMO)
 GLXPixmap
 gfxXlibSurface::GetGLXPixmap()
 {
     if (!mGLXPixmap) {
+#ifdef DEBUG
+        // cairo_surface_has_show_text_glyphs is used solely for the
+        // side-effect of setting the error on surface if
+        // cairo_surface_finish() has been called.
+        cairo_surface_has_show_text_glyphs(CairoSurface());
+        NS_ASSERTION(CairoStatus() != CAIRO_STATUS_SURFACE_FINISHED,
+            "GetGLXPixmap called after surface finished");
+#endif
         mGLXPixmap = gl::sDefGLXLib.CreatePixmap(this);
     }
     return mGLXPixmap;
 }
 #endif
 
 gfxASurface::MemoryLocation
 gfxXlibSurface::GetMemoryLocation() const
--- a/gfx/thebes/gfxXlibSurface.h
+++ b/gfx/thebes/gfxXlibSurface.h
@@ -42,16 +42,17 @@ public:
     static already_AddRefed<gfxXlibSurface>
     Create(Screen* screen, XRenderPictFormat *format, const gfxIntSize& size,
            Drawable relatedDrawable = None);
 
     virtual ~gfxXlibSurface();
 
     virtual already_AddRefed<gfxASurface>
     CreateSimilarSurface(gfxContentType aType, const gfxIntSize& aSize);
+    virtual void Finish() MOZ_OVERRIDE;
 
     virtual const gfxIntSize GetSize() const { return mSize; }
 
     Display* XDisplay() { return mDisplay; }
     Screen* XScreen();
     Drawable XDrawable() { return mDrawable; }
     XRenderPictFormat* XRenderFormat();
 
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -592,17 +592,17 @@ ProcessFile(JSContext *cx,
         startline = lineno;
         do {
             if (!GetLine(bufp, file, startline == lineno ? "js> " : "")) {
                 hitEOF = JS_TRUE;
                 break;
             }
             bufp += strlen(bufp);
             lineno++;
-        } while (!JS_BufferIsCompilableUnit(cx, JS_FALSE, obj, buffer, strlen(buffer)));
+        } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
 
         /* Clear any pending exception from previous failed compiles.  */
         JS_ClearPendingException(cx);
         script =
             JS_CompileScriptForPrincipals(cx, obj, env->GetPrincipal(), buffer,
                                           strlen(buffer), "typein", startline);
         if (script) {
             JSErrorReporter older;
@@ -753,16 +753,22 @@ FullTrustSecMan::GetSimpleCodebasePrinci
 NS_IMETHODIMP
 FullTrustSecMan::GetNoAppCodebasePrincipal(nsIURI *aURI,
                                            nsIPrincipal **_retval)
 {
     return GetSimpleCodebasePrincipal(aURI, _retval);
 }
 
 NS_IMETHODIMP
+FullTrustSecMan::GetCodebasePrincipal(nsIURI *aURI, nsIPrincipal **_retval)
+{
+    return GetSimpleCodebasePrincipal(aURI, _retval);
+}
+
+NS_IMETHODIMP
 FullTrustSecMan::GetAppCodebasePrincipal(nsIURI *aURI,
                                          uint32_t aAppId,
                                          bool aInMozBrowser,
                                          nsIPrincipal **_retval)
 {
     return GetSimpleCodebasePrincipal(aURI, _retval);
 }
 
--- a/js/src/config/makefiles/xpcshell.mk
+++ b/js/src/config/makefiles/xpcshell.mk
@@ -53,16 +53,17 @@ xpcshell-tests:
 	  $(LIBXUL_DIST)/bin/xpcshell \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 
 xpcshell-tests-remote: DM_TRANS?=adb
 xpcshell-tests-remote:
 	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/build \
 	  -I$(topsrcdir)/build/mobile \
+	  -I$(topsrcdir)/testing/mozbase/mozdevice/mozdevice \
 	  $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  $(EXTRA_TEST_ARGS) \
 	  --dm_trans=$(DM_TRANS) \
 	  --deviceIP=${TEST_DEVICE} \
 	  --objdir=$(DEPTH) \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -34,16 +34,124 @@
 #include "mozilla/StandardInteger.h"
 #include "mozilla/Scoped.h"
 
 using namespace std;
 
 namespace js {
 namespace ctypes {
 
+size_t
+GetDeflatedUTF8StringLength(JSContext *maybecx, const jschar *chars,
+                            size_t nchars)
+{
+    size_t nbytes;
+    const jschar *end;
+    unsigned c, c2;
+    char buffer[10];
+
+    nbytes = nchars;
+    for (end = chars + nchars; chars != end; chars++) {
+        c = *chars;
+        if (c < 0x80)
+            continue;
+        if (0xD800 <= c && c <= 0xDFFF) {
+            /* Surrogate pair. */
+            chars++;
+
+            /* nbytes sets 1 length since this is surrogate pair. */
+            nbytes--;
+            if (c >= 0xDC00 || chars == end)
+                goto bad_surrogate;
+            c2 = *chars;
+            if (c2 < 0xDC00 || c2 > 0xDFFF)
+                goto bad_surrogate;
+            c = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
+        }
+        c >>= 11;
+        nbytes++;
+        while (c) {
+            c >>= 5;
+            nbytes++;
+        }
+    }
+    return nbytes;
+
+  bad_surrogate:
+    if (maybecx) {
+        JS_snprintf(buffer, 10, "0x%x", c);
+        JS_ReportErrorFlagsAndNumber(maybecx, JSREPORT_ERROR, js_GetErrorMessage,
+                                     NULL, JSMSG_BAD_SURROGATE_CHAR, buffer);
+    }
+    return (size_t) -1;
+}
+
+bool
+DeflateStringToUTF8Buffer(JSContext *maybecx, const jschar *src, size_t srclen,
+                              char *dst, size_t *dstlenp)
+{
+    size_t i, utf8Len;
+    jschar c, c2;
+    uint32_t v;
+    uint8_t utf8buf[6];
+
+    size_t dstlen = *dstlenp;
+    size_t origDstlen = dstlen;
+
+    while (srclen) {
+        c = *src++;
+        srclen--;
+        if (c >= 0xDC00 && c <= 0xDFFF)
+            goto badSurrogate;
+        if (c < 0xD800 || c > 0xDBFF) {
+            v = c;
+        } else {
+            if (srclen < 1)
+                goto badSurrogate;
+            c2 = *src;
+            if ((c2 < 0xDC00) || (c2 > 0xDFFF))
+                goto badSurrogate;
+            src++;
+            srclen--;
+            v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
+        }
+        if (v < 0x0080) {
+            /* no encoding necessary - performance hack */
+            if (dstlen == 0)
+                goto bufferTooSmall;
+            *dst++ = (char) v;
+            utf8Len = 1;
+        } else {
+            utf8Len = js_OneUcs4ToUtf8Char(utf8buf, v);
+            if (utf8Len > dstlen)
+                goto bufferTooSmall;
+            for (i = 0; i < utf8Len; i++)
+                *dst++ = (char) utf8buf[i];
+        }
+        dstlen -= utf8Len;
+    }
+    *dstlenp = (origDstlen - dstlen);
+    return JS_TRUE;
+
+badSurrogate:
+    *dstlenp = (origDstlen - dstlen);
+    /* Delegate error reporting to the measurement function. */
+    if (maybecx)
+        GetDeflatedUTF8StringLength(maybecx, src - 1, srclen + 1);
+    return JS_FALSE;
+
+bufferTooSmall:
+    *dstlenp = (origDstlen - dstlen);
+    if (maybecx) {
+        JS_ReportErrorNumber(maybecx, js_GetErrorMessage, NULL,
+                             JSMSG_BUFFER_TOO_SMALL);
+    }
+    return JS_FALSE;
+}
+
 /*******************************************************************************
 ** JSAPI function prototypes
 *******************************************************************************/
 
 static JSBool ConstructAbstract(JSContext* cx, unsigned argc, jsval* vp);
 
 namespace CType {
   static JSBool ConstructData(JSContext* cx, unsigned argc, jsval* vp);
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -150,16 +150,25 @@ PrependString(Vector<jschar, N, AP> &v, 
 
   // Move vector data forward. This is safe since we've already resized.
   memmove(v.begin() + alen, v.begin(), vlen * sizeof(jschar));
 
   // Copy data to insert.
   memcpy(v.begin(), chars, alen * sizeof(jschar));
 }
 
+extern size_t
+GetDeflatedUTF8StringLength(JSContext *maybecx, const jschar *chars,
+                            size_t charsLength);
+
+bool
+DeflateStringToUTF8Buffer(JSContext *maybecx, const jschar *src, size_t srclen,
+                          char *dst, size_t *dstlenp);
+
+
 /*******************************************************************************
 ** Function and struct API definitions
 *******************************************************************************/
 
 JS_ALWAYS_INLINE void
 ASSERT_OK(JSBool ok)
 {
   JS_ASSERT(ok);
--- a/js/src/gc/Root.h
+++ b/js/src/gc/Root.h
@@ -493,45 +493,16 @@ struct RootKind<T *> { static ThingRootK
 template <typename T>
 struct RootMethods<T *>
 {
     static T *initial() { return NULL; }
     static ThingRootKind kind() { return RootKind<T *>::rootKind(); }
     static bool poisoned(T *v) { return IsPoisonedPtr(v); }
 };
 
-#if !defined(JSGC_ROOT_ANALYSIS) && !defined(JSGC_USE_EXACT_ROOTING)
-template <typename T>
-struct RootSink {
-    static inline void dispose(const T &) {}
-};
-
-/*
- * The *alleged* killer whale hack (see JS::Anchor<T> in jsapi.h) duplicated
- * here because using JS::Anchor causes clang to emit bad instructions.
- *
- * In exact-gc builds, Rooted<T> always keeps the T reachable. In non-exact-gc
- * builds, it does not, but conservative scanning usually picks up the slack.
- * However in the case where the Rooted pointer is no longer used, but some
- * subobject or malloc'd memory with the same lifetime may be used,
- * conservative scanning can fail. JSStableString's chars() method makes it
- * particularly attractive to use that way, so we use some voodoo to convince
- * the compiler to keep the string pointer on the stack for the full lifetime
- * of the Rooted<JSStableString *>.
- */
-template <>
-struct RootSink<JSStableString *> {
-    static void dispose(JSStableString *ptr) {
-        JSStableString * volatile sink;
-        sink = ptr;
-        (void)sink; // silence GCC unused-but-set-variable build warning
-    }
-};
-#endif
-
 template <typename T>
 class RootedBase {};
 
 /*
  * Local variable of type T whose value is always rooted. This is typically
  * used for local variables, or for non-rooted values being passed to a
  * function that requires a handle, e.g. Foo(Root<T>(cx, x)).
  *
@@ -611,18 +582,16 @@ class Rooted : public RootedBase<T>
         init(cx);
     }
 
     ~Rooted()
     {
 #if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
         JS_ASSERT(*stack == this);
         *stack = prev;
-#else
-        RootSink<T>::dispose(ptr);
 #endif
     }
 
 #if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
     Rooted<T> *previous() { return prev; }
 #endif
 
     operator T () const { return ptr; }
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -387,23 +387,28 @@ CodeGenerator::visitTableSwitchV(LTableS
     MTableSwitch *mir = ins->mir();
     Label *defaultcase = mir->getDefault()->lir()->label();
 
     Register index = ToRegister(ins->tempInt());
     ValueOperand value = ToValue(ins, LTableSwitchV::InputValue);
     Register tag = masm.extractTag(value, index);
     masm.branchTestNumber(Assembler::NotEqual, tag, defaultcase);
 
-    Label isInt;
-    masm.branchTestInt32(Assembler::Equal, tag, &isInt);
+    Label unboxInt, isInt;
+    masm.branchTestInt32(Assembler::Equal, tag, &unboxInt);
     {
         FloatRegister floatIndex = ToFloatRegister(ins->tempFloat());
         masm.unboxDouble(value, floatIndex);
         emitDoubleToInt32(floatIndex, index, defaultcase, false);
+        masm.jump(&isInt);
     }
+
+    masm.bind(&unboxInt);
+    masm.unboxInt32(value, index);
+
     masm.bind(&isInt);
 
     return emitTableSwitchDispatch(mir, index, ToRegisterOrInvalid(ins->tempPointer()));
 }
 
 bool
 CodeGenerator::visitParameter(LParameter *lir)
 {
--- a/js/src/ion/LIR-Common.h
+++ b/js/src/ion/LIR-Common.h
@@ -1322,16 +1322,26 @@ class LMinMaxD : public LInstructionHelp
     const LDefinition *output() {
         return this->getDef(0);
     }
     MMinMax *mir() const {
         return mir_->toMinMax();
     }
 };
 
+// Negative of a double.
+class LNegD : public LInstructionHelper<1, 1, 0>
+{
+  public:
+    LIR_HEADER(NegD);
+    LNegD(const LAllocation &num) {
+        setOperand(0, num);
+    }
+};
+
 // Absolute value of an integer.
 class LAbsI : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(AbsI);
     LAbsI(const LAllocation &num) {
         setOperand(0, num);
     }
--- a/js/src/ion/LOpcodes.h
+++ b/js/src/ion/LOpcodes.h
@@ -61,16 +61,17 @@
     _(CompareAndBranch)             \
     _(CompareDAndBranch)            \
     _(CompareB)                     \
     _(CompareBAndBranch)            \
     _(IsNullOrUndefined)            \
     _(IsNullOrUndefinedAndBranch)   \
     _(MinMaxI)                      \
     _(MinMaxD)                      \
+    _(NegD)                         \
     _(AbsI)                         \
     _(AbsD)                         \
     _(SqrtD)                        \
     _(PowI)                         \
     _(PowD)                         \
     _(Random)                       \
     _(MathFunctionD)                \
     _(NotI)                         \
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -850,16 +850,25 @@ LIRGenerator::visitMul(MMul *ins)
 
     if (ins->specialization() == MIRType_Int32) {
         JS_ASSERT(lhs->type() == MIRType_Int32);
         ReorderCommutative(&lhs, &rhs);
         return lowerMulI(ins, lhs, rhs);
     }
     if (ins->specialization() == MIRType_Double) {
         JS_ASSERT(lhs->type() == MIRType_Double);
+
+        // If our LHS is a constant -1.0, we can optimize to an LNegD.
+        if (lhs->isConstant() && lhs->toConstant()->value() == DoubleValue(-1.0))
+            return defineReuseInput(new LNegD(useRegisterAtStart(rhs)), ins, 0);
+
+        // We can do the same for the RHS, if we just swap the operands.
+        if (rhs->isConstant() && rhs->toConstant()->value() == DoubleValue(-1.0))
+            return defineReuseInput(new LNegD(useRegisterAtStart(lhs)), ins, 0);
+
         return lowerForFPU(new LMathD(JSOP_MUL), ins, lhs, rhs);
     }
 
     return lowerBinaryV(JSOP_MUL, ins);
 }
 
 bool
 LIRGenerator::visitDiv(MDiv *ins)
--- a/js/src/ion/arm/CodeGenerator-arm.cpp
+++ b/js/src/ion/arm/CodeGenerator-arm.cpp
@@ -316,16 +316,25 @@ CodeGeneratorARM::visitMinMaxD(LMinMaxD 
     masm.bind(&returnSecond);
     masm.ma_vmov(second, output);
 
     masm.bind(&done);
     return true;
 }
 
 bool
+CodeGeneratorARM::visitNegD(LNegD *ins)
+{
+    FloatRegister input = ToFloatRegister(ins->input());
+    JS_ASSERT(input == ToFloatRegister(ins->output()));
+    masm.as_vneg(input, input);
+    return true;
+}
+
+bool
 CodeGeneratorARM::visitAbsD(LAbsD *ins)
 {
     FloatRegister input = ToFloatRegister(ins->input());
     JS_ASSERT(input == ToFloatRegister(ins->output()));
     masm.as_vabs(input, input);
     return true;
 }
 
--- a/js/src/ion/arm/CodeGenerator-arm.h
+++ b/js/src/ion/arm/CodeGenerator-arm.h
@@ -64,16 +64,17 @@ class CodeGeneratorARM : public CodeGene
     // true, and the false block if |cond| is false.
     void emitBranch(Assembler::Condition cond, MBasicBlock *ifTrue, MBasicBlock *ifFalse);
 
     bool emitTableSwitchDispatch(MTableSwitch *mir, const Register &index, const Register &base);
 
   public:
     // Instruction visitors.
     virtual bool visitMinMaxD(LMinMaxD *ins);
+    virtual bool visitNegD(LNegD *ins);
     virtual bool visitAbsD(LAbsD *ins);
     virtual bool visitSqrtD(LSqrtD *ins);
     virtual bool visitAddI(LAddI *ins);
     virtual bool visitSubI(LSubI *ins);
     virtual bool visitBitNotI(LBitNotI *ins);
     virtual bool visitBitOpI(LBitOpI *ins);
 
     virtual bool visitMulI(LMulI *ins);
--- a/js/src/ion/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/ion/shared/CodeGenerator-x86-shared.cpp
@@ -442,16 +442,31 @@ CodeGeneratorX86Shared::visitMinMaxD(LMi
     masm.bind(&returnSecond);
     masm.movsd(second, output);
 
     masm.bind(&done);
     return true;
 }
 
 bool
+CodeGeneratorX86Shared::visitNegD(LNegD *ins)
+{
+    // XOR the float in a float register with -0.0.
+    FloatRegister input = ToFloatRegister(ins->input());
+    JS_ASSERT(input == ToFloatRegister(ins->output()));
+
+    // From MacroAssemblerX86Shared::maybeInlineDouble
+    masm.pcmpeqw(ScratchFloatReg, ScratchFloatReg);
+    masm.psllq(Imm32(63), ScratchFloatReg);
+
+    masm.xorpd(ScratchFloatReg, input); // s ^ 0x80000000000000
+    return true;
+}
+
+bool
 CodeGeneratorX86Shared::visitAbsD(LAbsD *ins)
 {
     FloatRegister input = ToFloatRegister(ins->input());
     JS_ASSERT(input == ToFloatRegister(ins->output()));
     masm.xorpd(ScratchFloatReg, ScratchFloatReg);
     masm.subsd(input, ScratchFloatReg); // negate the sign bit.
     masm.andpd(ScratchFloatReg, input); // s & ~s
     return true;
--- a/js/src/ion/shared/CodeGenerator-x86-shared.h
+++ b/js/src/ion/shared/CodeGenerator-x86-shared.h
@@ -83,16 +83,17 @@ class CodeGeneratorX86Shared : public Co
     bool emitTableSwitchDispatch(MTableSwitch *mir, const Register &index, const Register &base);
 
   public:
     CodeGeneratorX86Shared(MIRGenerator *gen, LIRGraph &graph);
 
   public:
     // Instruction visitors.
     virtual bool visitMinMaxD(LMinMaxD *ins);
+    virtual bool visitNegD(LNegD *ins);
     virtual bool visitAbsD(LAbsD *ins);
     virtual bool visitSqrtD(LSqrtD *ins);
     virtual bool visitPowHalfD(LPowHalfD *ins);
     virtual bool visitAddI(LAddI *ins);
     virtual bool visitSubI(LSubI *ins);
     virtual bool visitMulI(LMulI *ins);
     virtual bool visitDivI(LDivI *ins);
     virtual bool visitModI(LModI *ins);
deleted file mode 100644
--- a/js/src/jit-test/tests/gc/bug-787703.js
+++ /dev/null
@@ -1,5 +0,0 @@
-eval(" function x() {}" + Array(241).join(" "));
-for (var i = 0; i < 100; i++) {
-    gczeal(4, 2);
-    String(x);
-}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug804064.js
@@ -0,0 +1,22 @@
+function f (v, i) {
+    var c = v[i];
+    switch (c) {
+    case 0:
+        assertEq(v[i], 0);
+        break;
+    case 1:
+        assertEq(v[i], 1);
+        break;
+    default:
+        assertEq(c === 0 || c === 1, false);
+    }
+}
+
+var v = [
+  0, 0.0, 0.1, 1, 1.0, 1.1,
+  null, undefined, true, false, {}, "", "0", "1",
+  { valueOf: function () { return 0; } },
+  { valueOf: function () { return 1; } }
+];
+for (var i = 0; i < 100; i++)
+    f(v, i % v.length);
--- a/js/src/jsapi-tests/Makefile.in
+++ b/js/src/jsapi-tests/Makefile.in
@@ -55,17 +55,16 @@ CPPSRCS = \
   testResolveRecursion.cpp \
   testSameValue.cpp \
   testScriptInfo.cpp \
   testScriptObject.cpp \
   testSetProperty.cpp \
   testStringBuffer.cpp \
   testTrap.cpp \
   testTypedArrays.cpp \
-  testUTF8.cpp \
   testValueABI.cpp \
   testVersion.cpp \
   testXDR.cpp \
   testProfileStrings.cpp \
   testJSEvaluateScript.cpp \
   testErrorCopying.cpp \
   $(NULL)
 
deleted file mode 100644
--- a/js/src/jsapi-tests/testUTF8.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sw=4 et tw=99:
- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-
-#include "tests.h"
-
-BEGIN_TEST(testUTF8_bug589917)
-{
-    const jschar surrogate_pair[] = { 0xd800, 0xdc00 };
-    char output_buffer[10];
-    size_t utf8_len = sizeof(output_buffer);
-
-    CHECK(JS_EncodeCharacters(cx, surrogate_pair, 2, output_buffer, &utf8_len));
-    CHECK_EQUAL(utf8_len, 4);
-
-    CHECK(JS_EncodeCharacters(cx, surrogate_pair, 2, NULL, &utf8_len));
-    CHECK_EQUAL(utf8_len, 4);
-
-    return true;
-}
-END_TEST(testUTF8_bug589917)
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -20,20 +20,22 @@ CompileScriptForPrincipalsVersionOrigin(
 {
     size_t nchars;
     if (!JS_DecodeBytes(cx, bytes, nbytes, NULL, &nchars))
         return NULL;
     jschar *chars = static_cast<jschar *>(JS_malloc(cx, nchars * sizeof(jschar)));
     if (!chars)
         return NULL;
     JS_ALWAYS_TRUE(JS_DecodeBytes(cx, bytes, nbytes, chars, &nchars));
-    JSScript *script = JS_CompileUCScriptForPrincipalsVersionOrigin(cx, obj,
-                                                                    principals, originPrincipals,
-                                                                    chars, nchars,
-                                                                    filename, lineno, version);
+    JS::CompileOptions options(cx);
+    options.setPrincipals(principals)
+           .setOriginPrincipals(originPrincipals)
+           .setFileAndLine(filename, lineno)
+           .setVersion(version);
+    JSScript *script = JS::Compile(cx, obj, options, chars, nchars);
     free(chars);
     return script;
 }
 
 JSScript *
 FreezeThaw(JSContext *cx, JSScript *script)
 {
     // freeze
--- a/js/src/jsapi-tests/tests.cpp
+++ b/js/src/jsapi-tests/tests.cpp
@@ -71,18 +71,16 @@ JSObject * JSAPITest::createGlobal(JSPri
 }
 
 int main(int argc, char *argv[])
 {
     int total = 0;
     int failures = 0;
     const char *filter = (argc == 2) ? argv[1] : NULL;
 
-    JS_SetCStringsAreUTF8();
-
     for (JSAPITest *test = JSAPITest::list; test; test = test->next) {
         const char *name = test->name();
         if (filter && strstr(name, filter) == NULL)
             continue;
 
         total += 1;
 
         printf("%s\n", name);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -663,19 +663,18 @@ JS_PUBLIC_API(JSBool)
 JS_IsBuiltinFunctionConstructor(JSFunction *fun)
 {
     return IsBuiltinFunctionConstructor(fun);
 }
 
 /************************************************************************/
 
 /*
- * Has a new runtime ever been created?  This flag is used to detect unsafe
- * changes to js_CStringsAreUTF8 after a runtime has been created, and to
- * control things that should happen only once across all runtimes.
+ * Has a new runtime ever been created?  This flag is used to control things
+ * that should happen only once across all runtimes.
  */
 static JSBool js_NewRuntimeWasCalled = JS_FALSE;
 
 /*
  * Thread Local Storage slot for storing the runtime for a thread.
  */
 namespace JS {
 mozilla::ThreadLocal<JSRuntime *> TlsRuntime;
@@ -5206,17 +5205,17 @@ JS::Compile(JSContext *cx, HandleObject 
 }
 
 JSScript *
 JS::Compile(JSContext *cx, HandleObject obj, CompileOptions options,
             const char *bytes, size_t length)
 {
     jschar *chars;
     if (options.utf8)
-        chars = InflateString(cx, bytes, &length, CESU8Encoding);
+        chars = InflateUTF8String(cx, bytes, &length);
     else
         chars = InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
 
     JSScript *script = Compile(cx, obj, options, chars, length);
     js_free(chars);
     return script;
@@ -5239,50 +5238,16 @@ JS::Compile(JSContext *cx, HandleObject 
     AutoFile file;
     if (!file.open(cx, filename))
         return NULL;
     options = options.setFileAndLine(filename, 1);
     JSScript *script = Compile(cx, obj, options, file.fp());
     return script;
 }
 
-extern JS_PUBLIC_API(JSScript *)
-JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *objArg,
-                                       JSPrincipals *principals,
-                                       const jschar *chars, size_t length,
-                                       const char *filename, unsigned lineno,
-                                       JSVersion version)
-{
-    RootedObject obj(cx, objArg);
-    CompileOptions options(cx);
-    options.setPrincipals(principals)
-           .setFileAndLine(filename, lineno)
-           .setVersion(version);
-
-    return Compile(cx, obj, options, chars, length);
-}
-
-extern JS_PUBLIC_API(JSScript *)
-JS_CompileUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *objArg,
-                                             JSPrincipals *principals,
-                                             JSPrincipals *originPrincipals,
-                                             const jschar *chars, size_t length,
-                                             const char *filename, unsigned lineno,
-                                             JSVersion version)
-{
-    RootedObject obj(cx, objArg);
-    CompileOptions options(cx);
-    options.setPrincipals(principals)
-           .setOriginPrincipals(originPrincipals)
-           .setFileAndLine(filename, lineno)
-           .setVersion(version);
-
-    return Compile(cx, obj, options, chars, length);
-}
-
 JS_PUBLIC_API(JSScript *)
 JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *objArg, JSPrincipals *principals,
                                 const jschar *chars, size_t length,
                                 const char *filename, unsigned lineno)
 {
     RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
@@ -5298,72 +5263,52 @@ JS_CompileUCScript(JSContext *cx, JSObje
     RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setFileAndLine(filename, lineno);
 
     return Compile(cx, obj, options, chars, length);
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_CompileScriptForPrincipalsVersion(JSContext *cx, JSObject *objArg,
-                                     JSPrincipals *principals,
-                                     const char *bytes, size_t length,
-                                     const char *filename, unsigned lineno,
-                                     JSVersion version)
-{
-    RootedObject obj(cx, objArg);
-    CompileOptions options(cx);
-    options.setPrincipals(principals)
-           .setFileAndLine(filename, lineno)
-           .setVersion(version);
-
-    return Compile(cx, obj, options, bytes, length);
-}
-
-JS_PUBLIC_API(JSScript *)
 JS_CompileScriptForPrincipals(JSContext *cx, JSObject *objArg,
                               JSPrincipals *principals,
-                              const char *bytes, size_t length,
+                              const char *ascii, size_t length,
                               const char *filename, unsigned lineno)
 {
     RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
            .setFileAndLine(filename, lineno);
 
-    return Compile(cx, obj, options, bytes, length);
+    return Compile(cx, obj, options, ascii, length);
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_CompileScript(JSContext *cx, JSObject *objArg, const char *bytes, size_t length,
+JS_CompileScript(JSContext *cx, JSObject *objArg, const char *ascii, size_t length,
                  const char *filename, unsigned lineno)
 {
     RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setFileAndLine(filename, lineno);
 
-    return Compile(cx, obj, options, bytes, length);
-}
-
-JS_PUBLIC_API(JSBool)
-JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8, JSObject *objArg, const char *bytes, size_t length)
+    return Compile(cx, obj, options, ascii, length);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_BufferIsCompilableUnit(JSContext *cx, JSObject *objArg, const char *utf8, size_t length)
 {
     RootedObject obj(cx, objArg);
-    jschar *chars;
     JSBool result;
     JSExceptionState *exnState;
     JSErrorReporter older;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
-    if (bytes_are_utf8)
-        chars = InflateString(cx, bytes, &length, CESU8Encoding);
-    else
-        chars = InflateString(cx, bytes, &length);
+    jschar *chars = InflateUTF8String(cx, utf8, &length);
     if (!chars)
         return JS_TRUE;
 
     /*
      * Return true on any out-of-memory error, so our caller doesn't try to
      * collect more buffered source.
      */
     result = JS_TRUE;
@@ -5411,30 +5356,16 @@ JS_CompileUTF8FileHandleForPrincipals(JS
     options.setUTF8(true)
            .setFileAndLine(filename, 1)
            .setPrincipals(principals);
 
     return Compile(cx, obj, options, file);
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_CompileUTF8FileHandleForPrincipalsVersion(JSContext *cx, JSObject *objArg, const char *filename,
-                                             FILE *file, JSPrincipals *principals, JSVersion version)
-{
-    RootedObject obj(cx, objArg);
-    CompileOptions options(cx);
-    options.setUTF8(true)
-           .setFileAndLine(filename, 1)
-           .setPrincipals(principals)
-           .setVersion(version);
-
-    return Compile(cx, obj, options, file);
-}
-
-JS_PUBLIC_API(JSScript *)
 JS_CompileUTF8FileHandle(JSContext *cx, JSObject *objArg, const char *filename, FILE *file)
 {
     RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setUTF8(true)
            .setFileAndLine(filename, 1);
 
     return Compile(cx, obj, options, file);
@@ -5499,99 +5430,66 @@ JS::CompileFunction(JSContext *cx, Handl
 
 JS_PUBLIC_API(JSFunction *)
 JS::CompileFunction(JSContext *cx, HandleObject obj, CompileOptions options,
                     const char *name, unsigned nargs, const char **argnames,
                     const char *bytes, size_t length)
 {
     jschar *chars;
     if (options.utf8)
-        chars = InflateString(cx, bytes, &length, CESU8Encoding);
+        chars = InflateUTF8String(cx, bytes, &length);
     else
         chars = InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
 
     JSFunction *fun = CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
     js_free(chars);
     return fun;
 }
 
 JS_PUBLIC_API(JSFunction *)
-JS_CompileUCFunctionForPrincipalsVersion(JSContext *cx, JSObject *obj_,
-                                         JSPrincipals *principals, const char *name,
-                                         unsigned nargs, const char **argnames,
-                                         const jschar *chars, size_t length,
-                                         const char *filename, unsigned lineno,
-                                         JSVersion version)
-{
-    RootedObject obj(cx, obj_);
-
-    CompileOptions options(cx);
-    options.setPrincipals(principals)
-           .setFileAndLine(filename, lineno)
-           .setVersion(version);
-
-    return CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
-}
-
-JS_PUBLIC_API(JSFunction *)
-JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *objArg,
-                                  JSPrincipals *principals, const char *name,
-                                  unsigned nargs, const char **argnames,
-                                  const jschar *chars, size_t length,
-                                  const char *filename, unsigned lineno)
-{
-    RootedObject obj(cx, objArg);
-    CompileOptions options(cx);
-    options.setPrincipals(principals)
-           .setFileAndLine(filename, lineno);
-
-    return CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
-}
-
-JS_PUBLIC_API(JSFunction *)
 JS_CompileUCFunction(JSContext *cx, JSObject *objArg, const char *name,
                      unsigned nargs, const char **argnames,
                      const jschar *chars, size_t length,
                      const char *filename, unsigned lineno)
 {
     RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setFileAndLine(filename, lineno);
 
     return CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *objArg,
                                 JSPrincipals *principals, const char *name,
                                 unsigned nargs, const char **argnames,
-                                const char *bytes, size_t length,
+                                const char *ascii, size_t length,
                                 const char *filename, unsigned lineno)
 {
     RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
            .setFileAndLine(filename, lineno);
 
-    return CompileFunction(cx, obj, options, name, nargs, argnames, bytes, length);
+    return CompileFunction(cx, obj, options, name, nargs, argnames, ascii, length);
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_CompileFunction(JSContext *cx, JSObject *objArg, const char *name,
                    unsigned nargs, const char **argnames,
-                   const char *bytes, size_t length,
+                   const char *ascii, size_t length,
                    const char *filename, unsigned lineno)
 {
     RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setFileAndLine(filename, lineno);
 
-    return CompileFunction(cx, obj, options, name, nargs, argnames, bytes, length);
+    return CompileFunction(cx, obj, options, name, nargs, argnames, ascii, length);
 }
 
 JS_PUBLIC_API(JSString *)
 JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, unsigned indent)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
 
     AssertHeapIsIdle(cx);
@@ -5698,17 +5596,17 @@ JS::Evaluate(JSContext *cx, HandleObject
 }
 
 extern JS_PUBLIC_API(bool)
 JS::Evaluate(JSContext *cx, HandleObject obj, CompileOptions options,
              const char *bytes, size_t length, jsval *rval)
 {
     jschar *chars;
     if (options.utf8)
-        chars = InflateString(cx, bytes, &length, CESU8Encoding);
+        chars = InflateUTF8String(cx, bytes, &length);
     else
         chars = InflateString(cx, bytes, &length);
     if (!chars)
         return false;
 
     bool ok = Evaluate(cx, obj, options, chars, length, rval);
     js_free(chars);
     return ok;
@@ -6278,36 +6176,16 @@ JS_PUBLIC_API(const jschar *)
 JS_UndependString(JSContext *cx, JSString *str)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     return str->getCharsZ(cx);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst, size_t *dstlenp)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-
-    size_t n;
-    if (!dst) {
-        n = GetDeflatedStringLength(cx, src, srclen);
-        if (n == (size_t)-1) {
-            *dstlenp = 0;
-            return JS_FALSE;
-        }
-        *dstlenp = n;
-        return JS_TRUE;
-    }
-
-    return DeflateStringToBuffer(cx, src, srclen, dst, dstlenp);
-}
-
-JS_PUBLIC_API(JSBool)
 JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, size_t *dstlenp)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     return InflateStringToBuffer(cx, src, srclen, dst, dstlenp);
 }
 
 JS_PUBLIC_API(JSBool)
@@ -6363,21 +6241,17 @@ JS_EncodeStringToBuffer(JSString *str, c
     if (DeflateStringToBuffer(NULL, chars, str->length(), buffer, &writtenLength)) {
         JS_ASSERT(writtenLength <= length);
         return writtenLength;
     }
     JS_ASSERT(writtenLength <= length);
     size_t necessaryLength = GetDeflatedStringLength(NULL, chars, str->length());
     if (necessaryLength == size_t(-1))
         return size_t(-1);
-    if (writtenLength != length) {
-        /* Make sure that the buffer contains only valid UTF-8 sequences. */
-        JS_ASSERT(js_CStringsAreUTF8);
-        PodZero(buffer + writtenLength, length - writtenLength);
-    }
+    JS_ASSERT(writtenLength == length); // C strings are NOT encoded.
     return necessaryLength;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacerArg, jsval space,
              JSONWriteCallback callback, void *data)
 {
     RootedObject replacer(cx, replacerArg);
@@ -6634,41 +6508,16 @@ JS_WriteUint32Pair(JSStructuredCloneWrit
 }
 
 JS_PUBLIC_API(JSBool)
 JS_WriteBytes(JSStructuredCloneWriter *w, const void *p, size_t len)
 {
     return w->output().writeBytes(p, len);
 }
 
-/*
- * The following determines whether C Strings are to be treated as UTF-8
- * or ISO-8859-1.  For correct operation, it must be set prior to the
- * first call to JS_NewRuntime.
- */
-#ifndef JS_C_STRINGS_ARE_UTF8
-JSBool js_CStringsAreUTF8 = JS_FALSE;
-#endif
-
-JS_PUBLIC_API(JSBool)
-JS_CStringsAreUTF8()
-{
-    return js_CStringsAreUTF8;
-}
-
-JS_PUBLIC_API(void)
-JS_SetCStringsAreUTF8()
-{
-    JS_ASSERT(!js_NewRuntimeWasCalled);
-
-#ifndef JS_C_STRINGS_ARE_UTF8
-    js_CStringsAreUTF8 = JS_TRUE;
-#endif
-}
-
 /************************************************************************/
 
 JS_PUBLIC_API(void)
 JS_ReportError(JSContext *cx, const char *format, ...)
 {
     va_list ap;
 
     AssertHeapIsIdle(cx);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1969,17 +1969,17 @@ typedef enum JSExnType {
         JSEXN_REFERENCEERR,
         JSEXN_SYNTAXERR,
         JSEXN_TYPEERR,
         JSEXN_URIERR,
         JSEXN_LIMIT
 } JSExnType;
 
 typedef struct JSErrorFormatString {
-    /* The error format string (UTF-8 if js_CStringsAreUTF8). */
+    /* The error format string in ASCII. */
     const char *format;
 
     /* The number of arguments to expand in the formatted error message. */
     uint16_t argCount;
 
     /* One of the JSExnType constants above. */
     int16_t exnType;
 } JSErrorFormatString;
@@ -4943,84 +4943,52 @@ JS_CloneFunctionObject(JSContext *cx, JS
 /*
  * Given a buffer, return JS_FALSE if the buffer might become a valid
  * javascript statement with the addition of more lines.  Otherwise return
  * JS_TRUE.  The intent is to support interactive compilation - accumulate
  * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to
  * the compiler.
  */
 extern JS_PUBLIC_API(JSBool)
-JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8,
-                          JSObject *obj, const char *bytes, size_t length);
+JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, const char *utf8, size_t length);
 
 extern JS_PUBLIC_API(JSScript *)
 JS_CompileScript(JSContext *cx, JSObject *obj,
-                 const char *bytes, size_t length,
+                 const char *ascii, size_t length,
                  const char *filename, unsigned lineno);
 
 extern JS_PUBLIC_API(JSScript *)
 JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
                               JSPrincipals *principals,
-                              const char *bytes, size_t length,
+                              const char *ascii, size_t length,
                               const char *filename, unsigned lineno);
 
 extern JS_PUBLIC_API(JSScript *)
-JS_CompileScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
-                                     JSPrincipals *principals,
-                                     const char *bytes, size_t length,
-                                     const char *filename, unsigned lineno,
-                                     JSVersion version);
-
-extern JS_PUBLIC_API(JSScript *)
 JS_CompileUCScript(JSContext *cx, JSObject *obj,
                    const jschar *chars, size_t length,
                    const char *filename, unsigned lineno);
 
 extern JS_PUBLIC_API(JSScript *)
 JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
                                 JSPrincipals *principals,
                                 const jschar *chars, size_t length,
                                 const char *filename, unsigned lineno);
 
 extern JS_PUBLIC_API(JSScript *)
-JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
-                                       JSPrincipals *principals,
-                                       const jschar *chars, size_t length,
-                                       const char *filename, unsigned lineno,
-                                       JSVersion version);
-/*
- * If originPrincipals is null, then the value of principals is used as origin
- * principals for the compiled script.
- */
-extern JS_PUBLIC_API(JSScript *)
-JS_CompileUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
-                                             JSPrincipals *principals,
-                                             JSPrincipals *originPrincipals,
-                                             const jschar *chars, size_t length,
-                                             const char *filename, unsigned lineno,
-                                             JSVersion version);
-
-extern JS_PUBLIC_API(JSScript *)
 JS_CompileUTF8File(JSContext *cx, JSObject *obj, const char *filename);
 
 extern JS_PUBLIC_API(JSScript *)
 JS_CompileUTF8FileHandle(JSContext *cx, JSObject *obj, const char *filename,
                          FILE *fh);
 
 extern JS_PUBLIC_API(JSScript *)
 JS_CompileUTF8FileHandleForPrincipals(JSContext *cx, JSObject *obj,
                                       const char *filename, FILE *fh,
                                       JSPrincipals *principals);
 
-extern JS_PUBLIC_API(JSScript *)
-JS_CompileUTF8FileHandleForPrincipalsVersion(JSContext *cx, JSObject *obj,
-                                             const char *filename, FILE *fh,
-                                             JSPrincipals *principals,
-                                             JSVersion version);
-
 extern JS_PUBLIC_API(JSObject *)
 JS_GetGlobalFromScript(JSScript *script);
 
 extern JS_PUBLIC_API(JSFunction *)
 JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
                    unsigned nargs, const char **argnames,
                    const char *bytes, size_t length,
                    const char *filename, unsigned lineno);
@@ -5033,31 +5001,16 @@ JS_CompileFunctionForPrincipals(JSContex
                                 const char *filename, unsigned lineno);
 
 extern JS_PUBLIC_API(JSFunction *)
 JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
                      unsigned nargs, const char **argnames,
                      const jschar *chars, size_t length,
                      const char *filename, unsigned lineno);
 
-extern JS_PUBLIC_API(JSFunction *)
-JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
-                                  JSPrincipals *principals, const char *name,
-                                  unsigned nargs, const char **argnames,
-                                  const jschar *chars, size_t length,
-                                  const char *filename, unsigned lineno);
-
-extern JS_PUBLIC_API(JSFunction *)
-JS_CompileUCFunctionForPrincipalsVersion(JSContext *cx, JSObject *obj,
-                                         JSPrincipals *principals, const char *name,
-                                         unsigned nargs, const char **argnames,
-                                         const jschar *chars, size_t length,
-                                         const char *filename, unsigned lineno,
-                                         JSVersion version);
-
 #ifdef __cplusplus
 JS_END_EXTERN_C
 
 namespace JS {
 
 /* Options for JavaScript compilation. */
 struct JS_PUBLIC_API(CompileOptions) {
     JSPrincipals *principals;
@@ -5532,57 +5485,28 @@ JS_ConcatStrings(JSContext *cx, JSString
 /*
  * Convert a dependent string into an independent one.  This function does not
  * change the string's mutability, so the thread safety comments above apply.
  */
 extern JS_PUBLIC_API(const jschar *)
 JS_UndependString(JSContext *cx, JSString *str);
 
 /*
- * Return JS_TRUE if C (char []) strings passed via the API and internally
- * are UTF-8.
- */
-JS_PUBLIC_API(JSBool)
-JS_CStringsAreUTF8(void);
-
-/*
- * Update the value to be returned by JS_CStringsAreUTF8(). Once set, it
- * can never be changed. This API must be called before the first call to
- * JS_NewRuntime.
- */
-JS_PUBLIC_API(void)
-JS_SetCStringsAreUTF8(void);
-
-/*
- * Character encoding support.
- *
- * For both JS_EncodeCharacters and JS_DecodeBytes, set *dstlenp to the size
- * of the destination buffer before the call; on return, *dstlenp contains the
- * number of bytes (JS_EncodeCharacters) or jschars (JS_DecodeBytes) actually
- * stored.  To determine the necessary destination buffer size, make a sizing
- * call that passes NULL for dst.
+ * For JS_DecodeBytes, set *dstlenp to the size of the destination buffer before
+ * the call; on return, *dstlenp contains the number of jschars actually stored.
+ * To determine the necessary destination buffer size, make a sizing call that
+ * passes NULL for dst.
  *
  * On errors, the functions report the error. In that case, *dstlenp contains
  * the number of characters or bytes transferred so far.  If cx is NULL, no
  * error is reported on failure, and the functions simply return JS_FALSE.
  *
- * NB: Neither function stores an additional zero byte or jschar after the
+ * NB: This function does not store an additional zero byte or jschar after the
  * transcoded string.
- *
- * If JS_CStringsAreUTF8() is true then JS_EncodeCharacters encodes to
- * UTF-8, and JS_DecodeBytes decodes from UTF-8, which may create additional
- * errors if the character sequence is malformed.  If UTF-8 support is
- * disabled, the functions deflate and inflate, respectively.
- *
- * JS_DecodeUTF8() always behaves the same independently of JS_CStringsAreUTF8().
- */
-JS_PUBLIC_API(JSBool)
-JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst,
-                    size_t *dstlenp);
-
+ */
 JS_PUBLIC_API(JSBool)
 JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst,
                size_t *dstlenp);
 
 JS_PUBLIC_API(JSBool)
 JS_DecodeUTF8(JSContext *cx, const char *src, size_t srclen, jschar *dst,
               size_t *dstlenp);
 
@@ -5603,21 +5527,16 @@ JS_GetStringEncodingLength(JSContext *cx
 
 /*
  * Encode string into a buffer. The function does not stores an additional
  * zero byte. The function returns (size_t) -1 if the string can not be
  * encoded into bytes with no error reported. Otherwise it returns the number
  * of bytes that are necessary to encode the string. If that exceeds the
  * length parameter, the string will be cut and only length bytes will be
  * written into the buffer.
- *
- * If JS_CStringsAreUTF8() is true, the string does not fit into the buffer
- * and the the first length bytes ends in the middle of utf-8 encoding for
- * some character, then such partial utf-8 encoding is replaced by zero bytes.
- * This way the result always represents the valid UTF-8 sequence.
  */
 JS_PUBLIC_API(size_t)
 JS_EncodeStringToBuffer(JSString *str, char *buffer, size_t length);
 
 #ifdef __cplusplus
 
 class JSAutoByteString {
   public:
--- a/js/src/jsatom.cpp
+++ b/js/src/jsatom.cpp
@@ -314,17 +314,17 @@ js::AtomizeString(JSContext *cx, JSStrin
 
     const jschar *chars = stable->chars().get();
     size_t length = stable->length();
     JS_ASSERT(length <= JSString::MAX_LENGTH);
     return AtomizeInline(cx, &chars, length, ib);
 }
 
 JSAtom *
-js::Atomize(JSContext *cx, const char *bytes, size_t length, InternBehavior ib, FlationCoding fc)
+js::Atomize(JSContext *cx, const char *bytes, size_t length, InternBehavior ib)
 {
     CHECK_REQUEST(cx);
 
     if (!JSString::validateLength(cx, length))
         return NULL;
 
     /*
      * Avoiding the malloc in InflateString on shorter strings saves us
@@ -335,25 +335,22 @@ js::Atomize(JSContext *cx, const char *b
      */
     static const unsigned ATOMIZE_BUF_MAX = 32;
     jschar inflated[ATOMIZE_BUF_MAX];
     size_t inflatedLength = ATOMIZE_BUF_MAX - 1;
 
     const jschar *chars;
     OwnCharsBehavior ocb = CopyChars;
     if (length < ATOMIZE_BUF_MAX) {
-        if (fc == CESU8Encoding)
-            InflateUTF8StringToBuffer(cx, bytes, length, inflated, &inflatedLength, fc);
-        else
-            InflateStringToBuffer(cx, bytes, length, inflated, &inflatedLength);
+        InflateStringToBuffer(cx, bytes, length, inflated, &inflatedLength);
         inflated[inflatedLength] = 0;
         chars = inflated;
     } else {
         inflatedLength = length;
-        chars = InflateString(cx, bytes, &inflatedLength, fc);
+        chars = InflateString(cx, bytes, &inflatedLength);
         if (!chars)
             return NULL;
         ocb = TakeCharOwnership;
     }
 
     JSAtom *atom = AtomizeInline(cx, &chars, inflatedLength, ib, ocb);
     if (ocb == TakeCharOwnership && chars)
         js_free((void *)chars);
--- a/js/src/jsatom.h
+++ b/js/src/jsatom.h
@@ -114,39 +114,16 @@ struct AtomHasher
     };
 
     static HashNumber hash(const Lookup &l) { return HashChars(l.chars, l.length); }
     static inline bool match(const AtomStateEntry &entry, const Lookup &lookup);
 };
 
 typedef HashSet<AtomStateEntry, AtomHasher, SystemAllocPolicy> AtomSet;
 
-/*
- * On encodings:
- *
- * - Some string functions have an optional FlationCoding argument that allow
- *   the caller to force CESU-8 encoding handling.
- * - Functions that don't take a FlationCoding base their NormalEncoding
- *   behavior on the js_CStringsAreUTF8 value. NormalEncoding is either raw
- *   (simple zero-extension) or UTF-8 depending on js_CStringsAreUTF8.
- * - Functions that explicitly state their encoding do not use the
- *   js_CStringsAreUTF8 value.
- *
- * CESU-8 (Compatibility Encoding Scheme for UTF-16: 8-bit) is a variant of
- * UTF-8 that allows us to store any wide character string as a narrow
- * character string. For strings containing mostly ascii, it saves space.
- * http://www.unicode.org/reports/tr26/
- */
-
-enum FlationCoding
-{
-    NormalEncoding,
-    CESU8Encoding
-};
-
 class PropertyName;
 
 }  /* namespace js */
 
 extern bool
 AtomIsInterned(JSContext *cx, JSAtom *atom);
 
 /* Well-known predefined C strings. */
@@ -241,18 +218,17 @@ FinishCommonNames(JSRuntime *rt);
 enum InternBehavior
 {
     DoNotInternAtom = false,
     InternAtom = true
 };
 
 extern JSAtom *
 Atomize(JSContext *cx, const char *bytes, size_t length,
-        js::InternBehavior ib = js::DoNotInternAtom,
-        js::FlationCoding fc = js::NormalEncoding);
+        js::InternBehavior ib = js::DoNotInternAtom);
 
 extern JSAtom *
 AtomizeChars(JSContext *cx, const jschar *chars, size_t length,
              js::InternBehavior ib = js::DoNotInternAtom);
 
 extern JSAtom *
 AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib = js::DoNotInternAtom);
 
--- a/js/src/jsclone.cpp
+++ b/js/src/jsclone.cpp
@@ -330,17 +330,17 @@ SCInput::readChars(jschar *p, size_t nch
 
 bool
 SCInput::readPtr(void **p)
 {
     // On a 32 bit system the void* variable we have to write to is only
     // 32 bits, so we create a 64 temporary and discard the unused bits.
     uint64_t tmp;
     bool ret = read(&tmp);
-    *p = (void *) tmp;
+    *p = reinterpret_cast<void*>(tmp);
     return ret;
 }
 
 SCOutput::SCOutput(JSContext *cx) : cx(cx), buf(cx) {}
 
 bool
 SCOutput::write(uint64_t u)
 {
--- a/js/src/jsprf.cpp
+++ b/js/src/jsprf.cpp
@@ -663,18 +663,16 @@ static int dosprintf(SprintfState *ss, c
     static const char hex[] = "0123456789abcdef";
     static const char HEX[] = "0123456789ABCDEF";
     const char *hexp;
     int rv, i;
     struct NumArgState *nas = NULL;
     struct NumArgState nasArray[ NAS_DEFAULT_NUM ];
     char pattern[20];
     const char *dolPt = NULL;  /* in "%4$.2f", dolPt will poiont to . */
-    uint8_t utf8buf[6];
-    int utf8len;
 
     /*
     ** build an argument array, IF the fmt is numbered argument
     ** list style, to contain the Numbered Argument list pointers
     */
 
     nas = BuildArgArray( fmt, ap, &rv, nasArray );
     if( rv < 0 ){
@@ -901,23 +899,16 @@ static int dosprintf(SprintfState *ss, c
                     rv = (*ss->stuff)(ss, " ", 1);
                     if (rv < 0) {
                         return rv;
                     }
                 }
             }
             switch (type) {
               case TYPE_INT16:
-                /* Treat %hc as %c unless js_CStringsAreUTF8. */
-                if (js_CStringsAreUTF8) {
-                    u.wch = va_arg(ap, int);
-                    utf8len = js_OneUcs4ToUtf8Char (utf8buf, u.wch);
-                    rv = (*ss->stuff)(ss, (char *)utf8buf, utf8len);
-                    break;
-                }
               case TYPE_INTN:
                 u.ch = va_arg(ap, int);
                 rv = (*ss->stuff)(ss, &u.ch, 1);
                 break;
             }
             if (rv < 0) {
                 return rv;
             }
@@ -952,20 +943,16 @@ static int dosprintf(SprintfState *ss, c
           case 'G':
             /* XXX not supported I suppose */
             JS_ASSERT(0);
             break;
 #endif
 
           case 's':
             if(type == TYPE_INT16) {
-                /*
-                 * This would do a simple string/byte conversion
-                 * unless js_CStringsAreUTF8.
-                 */
                 u.ws = va_arg(ap, const jschar*);
                 rv = cvt_ws(ss, u.ws, width, prec, flags);
             } else {
                 u.s = va_arg(ap, const char*);
                 rv = cvt_s(ss, u.s, width, prec, flags);
             }
             if (rv < 0) {
                 return rv;
--- a/js/src/jsprf.h
+++ b/js/src/jsprf.h
@@ -11,20 +11,19 @@
 **      %d - decimal
 **      %u - unsigned decimal
 **      %x - unsigned hex
 **      %X - unsigned uppercase hex
 **      %o - unsigned octal
 **      %hd, %hu, %hx, %hX, %ho - 16-bit versions of above
 **      %ld, %lu, %lx, %lX, %lo - 32-bit versions of above
 **      %lld, %llu, %llx, %llX, %llo - 64 bit versions of above
-**      %s - string
-**      %hs - 16-bit version of above (only available if js_CStringsAreUTF8)
+**      %s - ascii string
+**      %hs - ucs2 string
 **      %c - character
-**      %hc - 16-bit version of above (only available if js_CStringsAreUTF8)
 **      %p - pointer (deals with machine dependent pointer size)
 **      %f - float
 **      %g - float
 */
 #include "jstypes.h"
 #include <stdio.h>
 #include <stdarg.h>
 
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -374,21 +374,11 @@ typedef JSObject *
 
 /*
  * Hook that creates an iterator object for a given object. Returns the
  * iterator object or null if an error or exception was thrown on cx.
  */
 typedef JSObject *
 (* JSIteratorOp)(JSContext *cx, JSHandleObject obj, JSBool keysonly);
 
-/*
- * The following determines whether JS_EncodeCharacters and JS_DecodeBytes
- * treat char[] as utf-8 or simply as bytes that need to be inflated/deflated.
- */
-#ifdef JS_C_STRINGS_ARE_UTF8
-# define js_CStringsAreUTF8 JS_TRUE
-#else
-extern JSBool js_CStringsAreUTF8;
-#endif
-
 JS_END_EXTERN_C
 
 #endif /* jsprvtd_h___ */
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -198,17 +198,16 @@ typedef struct JSStackFrame             
 typedef struct JSScript          JSScript;
 typedef struct JSStructuredCloneCallbacks   JSStructuredCloneCallbacks;
 typedef struct JSStructuredCloneReader      JSStructuredCloneReader;
 typedef struct JSStructuredCloneWriter      JSStructuredCloneWriter;
 typedef struct JSTracer                     JSTracer;
 
 #ifdef __cplusplus
 class                                       JSFlatString;
-class                                       JSStableString;  // long story
 class                                       JSString;
 #else
 typedef struct JSFlatString                 JSFlatString;
 typedef struct JSString                     JSString;
 #endif /* !__cplusplus */
 
 #ifdef JS_THREADSAFE
 typedef struct PRCallOnceType    JSCallOnceType;
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -3292,33 +3292,21 @@ NewShortString(JSContext *cx, const char
 {
     JS_ASSERT(JSShortString::lengthFits(length));
     JSInlineString *str = JSInlineString::lengthFits(length)
                           ? JSInlineString::new_(cx)
                           : JSShortString::new_(cx);
     if (!str)
         return NULL;
 
-    jschar *storage = str->init(length);
-    if (js_CStringsAreUTF8) {
-#ifdef DEBUG
-        size_t oldLength = length;
-#endif
-        if (!InflateUTF8StringToBuffer(cx, chars, length, storage, &length))
-            return NULL;
-        JS_ASSERT(length <= oldLength);
-        storage[length] = 0;
-        str->resetLength(length);
-    } else {
-        size_t n = length;
-        jschar *p = storage;
-        while (n--)
-            *p++ = (unsigned char)*chars++;
-        *p = 0;
-    }
+    size_t n = length;
+    jschar *p = str->init(length);
+    while (n--)
+        *p++ = (unsigned char)*chars++;
+    *p = 0;
     Probes::createString(cx, str, length);
     return str;
 }
 
 JSLinearString *
 js_NewDependentString(JSContext *cx, JSString *baseArg, size_t start, size_t length)
 {
     if (length == 0)
@@ -3610,41 +3598,59 @@ js_strchr_limit(const jschar *s, jschar 
         s++;
     }
     return NULL;
 }
 
 namespace js {
 
 jschar *
-InflateString(JSContext *cx, const char *bytes, size_t *lengthp, FlationCoding fc)
+InflateString(JSContext *cx, const char *bytes, size_t *lengthp)
+{
+    AssertCanGC();
+    size_t nchars;
+    jschar *chars;
+    size_t nbytes = *lengthp;
+
+    nchars = nbytes;
+    chars = cx->pod_malloc<jschar>(nchars + 1);
+    if (!chars)
+        goto bad;
+    for (size_t i = 0; i < nchars; i++)
+        chars[i] = (unsigned char) bytes[i];
+    *lengthp = nchars;
+    chars[nchars] = 0;
+    return chars;
+
+  bad:
+    /*
+     * For compatibility with callers of JS_DecodeBytes we must zero lengthp
+     * on errors.
+     */
+    *lengthp = 0;
+    return NULL;
+}
+
+jschar *
+InflateUTF8String(JSContext *cx, const char *bytes, size_t *lengthp)
 {
     AssertCanGC();
     size_t nchars;
     jschar *chars;
     size_t nbytes = *lengthp;
 
     // Malformed UTF8 chars could trigger errors and hence GC
     MaybeCheckStackRoots(cx);
 
-    if (js_CStringsAreUTF8 || fc == CESU8Encoding) {
-        if (!InflateUTF8StringToBuffer(cx, bytes, nbytes, NULL, &nchars, fc))
-            goto bad;
-        chars = cx->pod_malloc<jschar>(nchars + 1);
-        if (!chars)
-            goto bad;
-        JS_ALWAYS_TRUE(InflateUTF8StringToBuffer(cx, bytes, nbytes, chars, &nchars, fc));
-    } else {
-        nchars = nbytes;
-        chars = cx->pod_malloc<jschar>(nchars + 1);
-        if (!chars)
-            goto bad;
-        for (size_t i = 0; i < nchars; i++)
-            chars[i] = (unsigned char) bytes[i];
-    }
+    if (!InflateUTF8StringToBuffer(cx, bytes, nbytes, NULL, &nchars))
+        goto bad;
+    chars = cx->pod_malloc<jschar>(nchars + 1);
+    if (!chars)
+        goto bad;
+    JS_ALWAYS_TRUE(InflateUTF8StringToBuffer(cx, bytes, nbytes, chars, &nchars));
     *lengthp = nchars;
     chars[nchars] = 0;
     return chars;
 
   bad:
     /*
      * For compatibility with callers of JS_DecodeBytes we must zero lengthp
      * on errors.
@@ -3652,244 +3658,107 @@ InflateString(JSContext *cx, const char 
     *lengthp = 0;
     return NULL;
 }
 
 /*
  * May be called with null cx.
  */
 char *
-DeflateString(JSContext *cx, const jschar *chars, size_t nchars)
+DeflateString(JSContext *maybecx, const jschar *chars, size_t nchars)
 {
-    size_t nbytes, i;
-    char *bytes;
-
-    if (js_CStringsAreUTF8) {
-        nbytes = GetDeflatedStringLength(cx, chars, nchars);
-        if (nbytes == (size_t) -1)
-            return NULL;
-        bytes = (char *) (cx ? cx->malloc_(nbytes + 1) : js_malloc(nbytes + 1));
-        if (!bytes)
-            return NULL;
-        JS_ALWAYS_TRUE(DeflateStringToBuffer(cx, chars, nchars, bytes, &nbytes));
-    } else {
-        nbytes = nchars;
-        bytes = (char *) (cx ? cx->malloc_(nbytes + 1) : js_malloc(nbytes + 1));
-        if (!bytes)
-            return NULL;
-        for (i = 0; i < nbytes; i++)
-            bytes[i] = (char) chars[i];
-    }
+    AutoAssertNoGC nogc;
+    size_t nbytes = nchars;
+    char *bytes = maybecx
+                  ? maybecx->pod_malloc<char>(nbytes + 1)
+                  : js_pod_malloc<char>(nbytes + 1);
+    if (!bytes)
+        return NULL;
+    for (size_t i = 0; i < nbytes; i++)
+        bytes[i] = (char) chars[i];
     bytes[nbytes] = 0;
     return bytes;
 }
 
 size_t
 GetDeflatedStringLength(JSContext *cx, const jschar *chars, size_t nchars)
 {
-    if (!js_CStringsAreUTF8)
-        return nchars;
-
-    return GetDeflatedUTF8StringLength(cx, chars, nchars);
-}
-
-/*
- * May be called with null cx through public API, see below.
- */
-size_t
-GetDeflatedUTF8StringLength(JSContext *cx, const jschar *chars,
-                                size_t nchars, FlationCoding fc)
-{
-    size_t nbytes;
-    const jschar *end;
-    unsigned c, c2;
-    char buffer[10];
-    bool useCESU8 = fc == CESU8Encoding;
-
-    nbytes = nchars;
-    for (end = chars + nchars; chars != end; chars++) {
-        c = *chars;
-        if (c < 0x80)
-            continue;
-        if (0xD800 <= c && c <= 0xDFFF && !useCESU8) {
-            /* Surrogate pair. */
-            chars++;
-
-            /* nbytes sets 1 length since this is surrogate pair. */
-            nbytes--;
-            if (c >= 0xDC00 || chars == end)
-                goto bad_surrogate;
-            c2 = *chars;
-            if (c2 < 0xDC00 || c2 > 0xDFFF)
-                goto bad_surrogate;
-            c = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
-        }
-        c >>= 11;
-        nbytes++;
-        while (c) {
-            c >>= 5;
-            nbytes++;
-        }
-    }
-    return nbytes;
-
-  bad_surrogate:
-    if (cx) {
-        JS_snprintf(buffer, 10, "0x%x", c);
-        JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
-                                     NULL, JSMSG_BAD_SURROGATE_CHAR, buffer);
-    }
-    return (size_t) -1;
+    return nchars;
 }
 
 bool
-DeflateStringToBuffer(JSContext *cx, const jschar *src, size_t srclen,
+DeflateStringToBuffer(JSContext *maybecx, const jschar *src, size_t srclen,
                           char *dst, size_t *dstlenp)
 {
-    size_t dstlen, i;
-
-    dstlen = *dstlenp;
-    if (!js_CStringsAreUTF8) {
+    size_t dstlen = *dstlenp;
+    if (srclen > dstlen) {
+        for (size_t i = 0; i < dstlen; i++)
+            dst[i] = (char) src[i];
+        if (maybecx) {
+            JS_ReportErrorNumber(maybecx, js_GetErrorMessage, NULL,
+                                 JSMSG_BUFFER_TOO_SMALL);
+        }
+        return JS_FALSE;
+    }
+    for (size_t i = 0; i < srclen; i++)
+        dst[i] = (char) src[i];
+    *dstlenp = srclen;
+    return JS_TRUE;
+}
+
+
+bool
+InflateStringToBuffer(JSContext *maybecx, const char *src, size_t srclen,
+                          jschar *dst, size_t *dstlenp)
+{
+    if (dst) {
+        size_t dstlen = *dstlenp;
         if (srclen > dstlen) {
-            for (i = 0; i < dstlen; i++)
-                dst[i] = (char) src[i];
-            if (cx) {
-                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+            for (size_t i = 0; i < dstlen; i++)
+                dst[i] = (unsigned char) src[i];
+            if (maybecx) {
+                JS_ReportErrorNumber(maybecx, js_GetErrorMessage, NULL,
                                      JSMSG_BUFFER_TOO_SMALL);
             }
             return JS_FALSE;
         }
-        for (i = 0; i < srclen; i++)
-            dst[i] = (char) src[i];
-        *dstlenp = srclen;
-        return JS_TRUE;
-    }
-
-    return DeflateStringToUTF8Buffer(cx, src, srclen, dst, dstlenp);
-}
-
-bool
-DeflateStringToUTF8Buffer(JSContext *cx, const jschar *src, size_t srclen,
-                              char *dst, size_t *dstlenp, FlationCoding fc)
-{
-    size_t i, utf8Len;
-    jschar c, c2;
-    uint32_t v;
-    uint8_t utf8buf[6];
-
-    bool useCESU8 = fc == CESU8Encoding;
-    size_t dstlen = *dstlenp;
-    size_t origDstlen = dstlen;
-
-    while (srclen) {
-        c = *src++;
-        srclen--;
-        if ((c >= 0xDC00) && (c <= 0xDFFF) && !useCESU8)
-            goto badSurrogate;
-        if (c < 0xD800 || c > 0xDBFF || useCESU8) {
-            v = c;
-        } else {
-            if (srclen < 1)
-                goto badSurrogate;
-            c2 = *src;
-            if ((c2 < 0xDC00) || (c2 > 0xDFFF))
-                goto badSurrogate;
-            src++;
-            srclen--;
-            v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
-        }
-        if (v < 0x0080) {
-            /* no encoding necessary - performance hack */
-            if (dstlen == 0)
-                goto bufferTooSmall;
-            *dst++ = (char) v;
-            utf8Len = 1;
-        } else {
-            utf8Len = js_OneUcs4ToUtf8Char(utf8buf, v);
-            if (utf8Len > dstlen)
-                goto bufferTooSmall;
-            for (i = 0; i < utf8Len; i++)
-                *dst++ = (char) utf8buf[i];
-        }
-        dstlen -= utf8Len;
-    }
-    *dstlenp = (origDstlen - dstlen);
-    return JS_TRUE;
-
-badSurrogate:
-    *dstlenp = (origDstlen - dstlen);
-    /* Delegate error reporting to the measurement function. */
-    if (cx)
-        GetDeflatedStringLength(cx, src - 1, srclen + 1);
-    return JS_FALSE;
-
-bufferTooSmall:
-    *dstlenp = (origDstlen - dstlen);
-    if (cx) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                             JSMSG_BUFFER_TOO_SMALL);
-    }
-    return JS_FALSE;
-}
-
-bool
-InflateStringToBuffer(JSContext *cx, const char *src, size_t srclen,
-                          jschar *dst, size_t *dstlenp)
-{
-    size_t dstlen, i;
-
-    if (js_CStringsAreUTF8)
-        return InflateUTF8StringToBuffer(cx, src, srclen, dst, dstlenp);
-
-    if (dst) {
-        dstlen = *dstlenp;
-        if (srclen > dstlen) {
-            for (i = 0; i < dstlen; i++)
-                dst[i] = (unsigned char) src[i];
-            if (cx) {
-                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                                     JSMSG_BUFFER_TOO_SMALL);
-            }
-            return JS_FALSE;
-        }
-        for (i = 0; i < srclen; i++)
+        for (size_t i = 0; i < srclen; i++)
             dst[i] = (unsigned char) src[i];
     }
     *dstlenp = srclen;
     return JS_TRUE;
 }
 
 bool
 InflateUTF8StringToBuffer(JSContext *cx, const char *src, size_t srclen,
-                              jschar *dst, size_t *dstlenp, FlationCoding fc)
+                              jschar *dst, size_t *dstlenp)
 {
     size_t dstlen, origDstlen, offset, j, n;
     uint32_t v;
 
     dstlen = dst ? *dstlenp : (size_t) -1;
     origDstlen = dstlen;
     offset = 0;
-    bool useCESU8 = fc == CESU8Encoding;
 
     while (srclen) {
         v = (uint8_t) *src;
         n = 1;
         if (v & 0x80) {
             while (v & (0x80 >> n))
                 n++;
             if (n > srclen)
                 goto bufferTooSmall;
             if (n == 1 || n > 4)
                 goto badCharacter;
             for (j = 1; j < n; j++) {
                 if ((src[j] & 0xC0) != 0x80)
                     goto badCharacter;
             }
             v = Utf8ToOneUcs4Char((uint8_t *)src, n);
-            if (v >= 0x10000 && !useCESU8) {
+            if (v >= 0x10000) {
                 v -= 0x10000;
                 if (v > 0xFFFFF || dstlen < 2) {
                     *dstlenp = (origDstlen - dstlen);
                     if (cx) {
                         char buffer[10];
                         JS_snprintf(buffer, 10, "0x%x", v + 0x10000);
                         JS_ReportErrorFlagsAndNumber(cx,
                                                      JSREPORT_ERROR,
--- a/js/src/jsstr.h
+++ b/js/src/jsstr.h
@@ -203,23 +203,30 @@ js_strncpy(jschar *dst, const jschar *sr
 }
 
 extern jschar *
 js_strdup(JSContext *cx, const jschar *s);
 
 namespace js {
 
 /*
- * Inflate bytes to jschars. Return null on error, otherwise return the jschar
- * or byte vector that was malloc'ed. length is updated to the length of the
+ * Inflate bytes in ASCII encoding to jschars. Return null on error, otherwise
+ * return the jschar that was malloc'ed. length is updated to the length of the
  * new string (in jschars).
  */
 extern jschar *
-InflateString(JSContext *cx, const char *bytes, size_t *length,
-              FlationCoding fc = NormalEncoding);
+InflateString(JSContext *cx, const char *bytes, size_t *length);
+
+/*
+ * Inflate bytes in UTF-8 encoding to jschars. Return null on error, otherwise
+ * return the jschar vector that was malloc'ed. length is updated to the length
+ * of the new string (in jschars).
+ */
+extern jschar *
+InflateUTF8String(JSContext *cx, const char *bytes, size_t *length);
 
 extern char *
 DeflateString(JSContext *cx, const jschar *chars, size_t length);
 
 /*
  * Inflate bytes to JS chars in an existing buffer. 'chars' must be large
  * enough for 'length' jschars. The buffer is NOT null-terminated.
  *
@@ -227,48 +234,33 @@ DeflateString(JSContext *cx, const jscha
  * return, will contain on return the number of copied chars.
  */
 extern bool
 InflateStringToBuffer(JSContext *cx, const char *bytes, size_t length,
                       jschar *chars, size_t *charsLength);
 
 extern bool
 InflateUTF8StringToBuffer(JSContext *cx, const char *bytes, size_t length,
-                          jschar *chars, size_t *charsLength,
-                          FlationCoding fc = NormalEncoding);
+                          jschar *chars, size_t *charsLength);
 
 /* Get number of bytes in the deflated sequence of characters. */
 extern size_t
 GetDeflatedStringLength(JSContext *cx, const jschar *chars, size_t charsLength);
 
-/* This function will never fail (return -1) in CESU-8 mode. */
-extern size_t
-GetDeflatedUTF8StringLength(JSContext *cx, const jschar *chars,
-                            size_t charsLength,
-                            FlationCoding fc = NormalEncoding);
-
 /*
  * Deflate JS chars to bytes into a buffer. 'bytes' must be large enough for
  * 'length chars. The buffer is NOT null-terminated. The destination length
  * must to be initialized with the buffer size and will contain on return the
- * number of copied bytes. Conversion behavior depends on js_CStringsAreUTF8.
+ * number of copied bytes.
  */
 extern bool
 DeflateStringToBuffer(JSContext *cx, const jschar *chars,
                       size_t charsLength, char *bytes, size_t *length);
 
 /*
- * Same as DeflateStringToBuffer, but treats 'bytes' as UTF-8 or CESU-8.
- */
-extern bool
-DeflateStringToUTF8Buffer(JSContext *cx, const jschar *chars,
-                          size_t charsLength, char *bytes, size_t *length,
-                          FlationCoding fc = NormalEncoding);
-
-/*
  * The String.prototype.replace fast-native entry point is exported for joined
  * function optimization in js{interp,tracer}.cpp.
  */
 extern JSBool
 str_replace(JSContext *cx, unsigned argc, js::Value *vp);
 
 extern JSBool
 str_fromCharCode(JSContext *cx, unsigned argc, Value *vp);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -354,19 +354,16 @@ SetContextOptions(JSContext *cx)
 /*
  * Some UTF-8 files, notably those written using Notepad, have a Unicode
  * Byte-Order-Mark (BOM) as their first character. This is useless (byte-order
  * is meaningless for UTF-8) but causes a syntax error unless we skip it.
  */
 static void
 SkipUTF8BOM(FILE* file)
 {
-    if (!js_CStringsAreUTF8)
-        return;
-
     int ch1 = fgetc(file);
     int ch2 = fgetc(file);
     int ch3 = fgetc(file);
 
     // Skip the BOM
     if (ch1 == 0xEF && ch2 == 0xBB && ch3 == 0xBF)
         return;
 
@@ -504,17 +501,17 @@ Process(JSContext *cx, JSObject *obj_, c
                 len = newlen;
                 free(line);
             }
             lineno++;
             if (!ScheduleWatchdog(cx->runtime, gTimeoutInterval)) {
                 hitEOF = true;
                 break;
             }
-        } while (!JS_BufferIsCompilableUnit(cx, true, obj, buffer, len));
+        } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, len));
 
         if (hitEOF && !buffer)
             break;
 
         if (!JS_DecodeUTF8(cx, buffer, len, NULL, &uc_len)) {
             JS_ReportError(cx, "Invalid UTF-8 in input");
             gExitCode = EXITCODE_RUNTIME_ERROR;
             return;
@@ -2295,23 +2292,16 @@ ToInt32(JSContext *cx, unsigned argc, js
     int32_t i;
 
     if (!JS_ValueToInt32(cx, argc == 0 ? JSVAL_VOID : vp[2], &i))
         return false;
     *vp = JS_NumberValue(i);
     return true;
 }
 
-static JSBool
-StringsAreUTF8(JSContext *cx, unsigned argc, jsval *vp)
-{
-    *vp = JS_CStringsAreUTF8() ? JSVAL_TRUE : JSVAL_FALSE;
-    return true;
-}
-
 static const char* badUTF8 = "...\xC0...";
 static const char* bigUTF8 = "...\xFB\xBF\xBF\xBF\xBF...";
 static const jschar badSurrogate[] = { 'A', 'B', 'C', 0xDEEE, 'D', 'E', 0 };
 
 static JSBool
 TestUTF8(JSContext *cx, unsigned argc, jsval *vp)
 {
     int32_t mode = 1;
@@ -2329,17 +2319,17 @@ TestUTF8(JSContext *cx, unsigned argc, j
         JS_NewStringCopyZ(cx, badUTF8);
         break;
       /* mode 2: big UTF-8 character. */
       case 2:
         JS_NewStringCopyZ(cx, bigUTF8);
         break;
       /* mode 3: bad surrogate character. */
       case 3:
-        JS_EncodeCharacters(cx, badSurrogate, 6, bytes, &bytesLength);
+        DeflateStringToBuffer(cx, badSurrogate, 6, bytes, &bytesLength);
         break;
       /* mode 4: use a too small buffer. */
       case 4:
         JS_DecodeBytes(cx, "1234567890", 10, chars, &charsLength);
         break;
       default:
         JS_ReportError(cx, "invalid mode parameter");
         return false;
@@ -3536,20 +3526,16 @@ static JSFunctionSpecWithHelp shell_func
     JS_FN_HELP("line2pc", LineToPC, 0, 0,
 "line2pc([fun,] line)",
 "  Map line number to PC."),
 
     JS_FN_HELP("pc2line", PCToLine, 0, 0,
 "pc2line(fun[, pc])",
 "  Map PC to line number."),
 
-    JS_FN_HELP("stringsAreUTF8", StringsAreUTF8, 0, 0,
-"stringsAreUTF8()",
-"  Check if strings are UTF-8 encoded."),
-
     JS_FN_HELP("testUTF8", TestUTF8, 1, 0,
 "testUTF8(mode)",
 "  Perform UTF-8 tests (modes are 1 to 4)."),
 
     JS_FN_HELP("throwError", ThrowError, 0, 0,
 "throwError()",
 "  Throw an error from JS_ReportError."),
 
@@ -4868,17 +4854,16 @@ main(int argc, char **argv, char **envp)
         || !op.addBoolOption('a', "always-mjit",
                              "Do not try to run in the interpreter before method jitting.")
         || !op.addBoolOption('D', "dump-bytecode", "Dump bytecode with exec count for all scripts")
         || !op.addBoolOption('b', "print-timing", "Print sub-ms runtime for each file that's run")
 #ifdef DEBUG
         || !op.addIntOption('A', "oom-after", "COUNT", "Trigger OOM after COUNT allocations", -1)
         || !op.addBoolOption('O', "print-alloc", "Print the number of allocations at exit")
 #endif
-        || !op.addBoolOption('U', "utf8", "C strings passed to the JSAPI are UTF-8 encoded")
         || !op.addOptionalStringArg("script", "A script to execute (after all options)")
         || !op.addOptionalMultiStringArg("scriptArgs",
                                          "String arguments to bind as |arguments| in the "
                                          "shell's global")
         || !op.addBoolOption('\0', "ion", "Enable IonMonkey (default)")
         || !op.addBoolOption('\0', "no-ion", "Disable IonMonkey")
         || !op.addStringOption('\0', "ion-gvn", "[mode]",
                                "Specify Ion global value numbering:\n"
@@ -4933,20 +4918,16 @@ main(int argc, char **argv, char **envp)
      * allocations as possible.
      */
     if (op.getIntOption('A') >= 0)
         OOM_maxAllocations = op.getIntOption('A');
     if (op.getBoolOption('O'))
         OOM_printAllocationCount = true;
 #endif
 
-    /* Must be done before we create the JSRuntime. */
-    if (op.getBoolOption('U'))
-        JS_SetCStringsAreUTF8();
-
 #ifdef XP_WIN
     // Set the timer calibration delay count to 0 so we get high
     // resolution right away, which we need for precise benchmarking.
     extern int CALIBRATION_DELAY_COUNT;
     CALIBRATION_DELAY_COUNT = 0;
 #endif
 
     /* Use the same parameters as the browser in xpcjsruntime.cpp. */
--- a/js/src/tests/js1_5/Regress/regress-511859.js
+++ b/js/src/tests/js1_5/Regress/regress-511859.js
@@ -141,24 +141,10 @@ function test()
   printBugNumber(BUGNUMBER);
   printStatus(summary);
 
   for (var i=0; i<UBound; i++)
   {
     reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]);
   }
 
-  for (var i=5; i<=9; i++)
-    status = summary + ': UTF-8 test: bad UTF-8 sequence ' + i;
-    expect = 'Error';
-    actual = 'No error!';
-    try
-    {
-      testUTF8(i);
-    }
-    catch (e)
-    {
-      actual = 'Error';
-    }
-    reportCompare(expect, actual, status);
-
   exitFunc('test');
 }
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -4602,17 +4602,17 @@ DebuggerEnv_getType(JSContext *cx, unsig
     const char *s;
     if (IsDeclarative(env))
         s = "declarative";
     else if (IsWith(env))
         s = "with";
     else
         s = "object";
 
-    JSAtom *str = Atomize(cx, s, strlen(s), InternAtom, NormalEncoding);
+    JSAtom *str = Atomize(cx, s, strlen(s), InternAtom);
     if (!str)
         return false;
     args.rval().setString(str);
     return true;
 }
 
 static JSBool
 DebuggerEnv_getParent(JSContext *cx, unsigned argc, Value *vp)
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -1034,17 +1034,17 @@ ProcessFile(JSContext *cx, JSObject *obj
         startline = lineno;
         do {
             if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) {
                 hitEOF = true;
                 break;
             }
             bufp += strlen(bufp);
             lineno++;
-        } while (!JS_BufferIsCompilableUnit(cx, false, obj, buffer, strlen(buffer)));
+        } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
 
         DoBeginRequest(cx);
         /* Clear any pending exception from previous failed compiles.  */
         JS_ClearPendingException(cx);
         script = JS_CompileScriptForPrincipals(cx, obj, gJSPrincipals, buffer,
                                                strlen(buffer), "typein", startline);
         if (script) {
             JSErrorReporter older;
@@ -1390,16 +1390,23 @@ FullTrustSecMan::GetSimpleCodebasePrinci
 
 /* [noscript] nsIPrincipal getNoAppCodebasePrincipal (in nsIURI aURI); */
 NS_IMETHODIMP
 FullTrustSecMan::GetNoAppCodebasePrincipal(nsIURI *aURI, nsIPrincipal **_retval)
 {
     return GetSimpleCodebasePrincipal(aURI, _retval);
 }
 
+/* [noscript] nsIPrincipal getCodebasePrincipal (in nsIURI aURI); */
+NS_IMETHODIMP
+FullTrustSecMan::GetCodebasePrincipal(nsIURI *aURI, nsIPrincipal **_retval)
+{
+    return GetSimpleCodebasePrincipal(aURI, _retval);
+}
+
 /* [noscript] nsIPrincipal getAppCodebasePrincipal (in nsIURI aURI, unsigned long appid, bool inMozBrowser); */
 NS_IMETHODIMP
 FullTrustSecMan::GetAppCodebasePrincipal(nsIURI *aURI, uint32_t aAppId, bool aInMozBrowser, nsIPrincipal **_retval)
 {
     return GetSimpleCodebasePrincipal(aURI, _retval);
 }
 
 /* [noscript] nsIPrincipal getDocShellCodebasePrincipal (in nsIURI aURI, nsIDocShell docShell); */
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -2357,17 +2357,16 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
    mVariantRoots(nullptr),
    mWrappedJSRoots(nullptr),
    mObjectHolderRoots(nullptr),
    mWatchdogLock(nullptr),
    mWatchdogWakeup(nullptr),
    mWatchdogThread(nullptr),
    mWatchdogHibernating(false),
    mLastActiveTime(-1),
-   mReleaseRunnable(nullptr),
    mExceptionManagerNotAvailable(false)
 {
 #ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
     DEBUG_WrappedNativeHashtable =
         JS_NewDHashTable(JS_DHashGetStubOps(), nullptr,
                          sizeof(JSDHashEntryStub), 128);
 #endif
 
--- a/js/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/xpconnect/src/dom_quickstubs.qsconf
@@ -136,19 +136,17 @@ members = [
     'nsIDOMNodeSelector.querySelectorAll',
     'nsIDOMText.splitText',
     'nsIDOMDOMStringList.*',
     'nsIDOMXULDocument.getBoxObjectFor',
     'nsIDOMMutationRecord.*',
 
     # dom/interfaces/css
     'nsIDOMElementCSSInlineStyle.*',
-    'nsIDOMCSS2Properties.*',
     'nsIDOMRect.*',
-    'nsIDOMCSSStyleDeclaration.*',
 
     # dom/interfaces/events
     'nsIDOMEventTarget.addEventListener',
     'nsIDOMEventTarget.removeEventListener',
     'nsIDOMEventTarget.dispatchEvent',
 
     'nsIDOMEvent.type',
     'nsIDOMEvent.target',
@@ -660,25 +658,16 @@ customMethodCalls = {
         'thisType': 'nsHTMLDocument',
         'code': '    nsRefPtr<nsContentList> result = '
                 'self->GetElementsByName(arg0);',
         'canFail': False
         },
     'nsIDOMStorage_Clear': {
         'code': nsIDOMStorage_Clear_customMethodCallCode
         },
-    'nsIDOMCSS2Properties_': {
-        'thisType': 'nsICSSDeclaration',
-        'additionalArguments': 'const nsCSSProperty prop',
-        'additionalArgumentValues': 'QS_CSS_PROP_%s',
-        'getter_code': '    nsString result;\n' + 
-                       '    rv = self->GetPropertyValue(prop, result);',
-        'setter_code': '    rv = self->SetPropertyValue(prop, arg0);',
-        'canFail': True
-        },
     'nsIDOMElement_GetScrollTop': {
         'thisType': 'nsGenericElement',
         'code': '    int32_t result = self->GetScrollTop();',
         'canFail': False
         },
     'nsIDOMElement_SetScrollTop': {
         'thisType': 'nsGenericElement',
         'canFail': False
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -960,17 +960,17 @@ private:
     XPCRootSetElem *mObjectHolderRoots;
     nsDataHashtable<nsPtrHashKey<void>, nsScriptObjectTracer*> mJSHolders;
     PRLock *mWatchdogLock;
     PRCondVar *mWatchdogWakeup;
     PRThread *mWatchdogThread;
     nsTArray<JSGCCallback> extraGCCallbacks;
     bool mWatchdogHibernating;
     PRTime mLastActiveTime; // -1 if active NOW
-    XPCIncrementalReleaseRunnable *mReleaseRunnable;
+    nsRefPtr<XPCIncrementalReleaseRunnable> mReleaseRunnable;
     js::GCSliceCallback mPrevGCSliceCallback;
 
     nsCOMPtr<nsIException>   mPendingException;
     nsCOMPtr<nsIExceptionManager> mExceptionManager;
     bool mExceptionManagerNotAvailable;
 
 #define XPCCCX_STRING_CACHE_SIZE 2
 
--- a/js/xpconnect/tests/chrome/Makefile.in
+++ b/js/xpconnect/tests/chrome/Makefile.in
@@ -53,16 +53,17 @@ MOCHITEST_CHROME_FILES = \
 		test_cows.xul \
 		test_documentdomain.xul \
 		test_doublewrappedcompartments.xul \
 		test_evalInSandbox.xul \
 		file_evalInSandbox.html \
 		test_exnstack.xul \
 		test_expandosharing.xul \
 		file_expandosharing.jsm \
+		test_exposeInDerived.xul \
 		test_getweakmapkeys.xul \
 		test_mozMatchesSelector.xul \
 		test_nodelists.xul \
 		test_precisegc.xul \
 		test_sandboxImport.xul \
 		test_weakmaps.xul \
 		test_weakmap_keys_preserved.xul \
 		test_weakmap_keys_preserved2.xul \
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/chrome/test_exposeInDerived.xul
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=804630
+-->
+<window title="Mozilla Bug 804630"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=804630"
+     target="_blank">Mozilla Bug 804630</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript">
+  <![CDATA[
+  /** Test to make sure that COWed objects can expose properties from their prototypes. **/
+  const Cu = Components.utils;
+
+  // Set up the sandbox.
+  var sb = new Cu.Sandbox('http://www.example.com');
+  sb.ok = ok;
+  sb.is = is;
+
+  // Make a chrome object that exposes objects off its prototype.
+  sb.proto = { read: 42, readWrite: 32, __exposedProps__: {} };
+  sb.proto.__defineSetter__('setterProp', function(val) { this._setterProp = val; });
+  sb.obj = { __exposedProps__: { read: 'r', readWrite: 'rw', setterProp: 'w' } };
+  sb.obj.__proto__ = sb.proto;
+
+  // Make sure we can't access any of the properties on the prototype directly.
+  Cu.evalInSandbox('is(proto.read, undefined, "proto.read inaccessible");', sb);
+  Cu.evalInSandbox('var wrote = false; ' +
+                   'try { proto.readWrite = 12; wrote = true; } catch(e) {} ' +
+                   ' ok(!wrote, "Should not write proto property");', sb);
+  Cu.evalInSandbox('var wrote = false; ' +
+                   'try { proto.setterProp = 12; wrote = true; } catch(e) {} ' +
+                   ' ok(!wrote, "Should not write proto setter");', sb);
+
+  // Make sure we can access the exposed properties via the derived object.
+  Cu.evalInSandbox('is(obj.read, 42, "obj.read accessible");', sb);
+  Cu.evalInSandbox('is(obj.readWrite, 32, "obj.readWrite is readable");', sb);
+  Cu.evalInSandbox('obj.readWrite = 8; is(obj.readWrite, 8, "obj.readWrite is writable");', sb);
+  Cu.evalInSandbox('obj.setterProp = 3;', sb);
+  is(sb.obj._setterProp, 3, "obj.setterProp works");
+
+  ]]>
+  </script>
+</window>
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -8216,48 +8216,56 @@ nsCSSFrameConstructor::ProcessRestyledFr
       if ((hint & nsChangeHint_UpdateOverflow) && !didReflowThisFrame) {
         if (hint & nsChangeHint_ChildrenOnlyTransform) {
           // Update overflow areas of children first:
           nsIFrame* childFrame =
             GetFrameForChildrenOnlyTransformHint(frame)->GetFirstPrincipalChild();
           for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
             NS_ABORT_IF_FALSE(childFrame->IsFrameOfType(nsIFrame::eSVG),
                               "Not expecting non-SVG children");
-            childFrame->UpdateOverflow();
+            if (!(childFrame->GetStateBits() &
+                  (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
+              childFrame->UpdateOverflow();
+            }
             NS_ASSERTION(!nsLayoutUtils::GetNextContinuationOrSpecialSibling(childFrame),
                          "SVG frames should not have continuations or special siblings");
             NS_ASSERTION(childFrame->GetParent() == frame,
                          "SVG child frame not expected to have different parent");
           }
         }
-        while (frame) {
-          nsOverflowAreas* pre = static_cast<nsOverflowAreas*>
-            (frame->Properties().Get(frame->PreTransformOverflowAreasProperty()));
-          if (pre) {
-            // FinishAndStoreOverflow will change the overflow areas passed in,
-            // so make a copy.
-            nsOverflowAreas overflowAreas = *pre;
-            frame->FinishAndStoreOverflow(overflowAreas, frame->GetSize());
-          } else {
-            frame->UpdateOverflow();
-          }
-
-          nsIFrame* next =
-            nsLayoutUtils::GetNextContinuationOrSpecialSibling(frame);
-          // Update the ancestors' overflow after we have updated the overflow
-          // for all the continuations with the same parent.
-          if (!next || frame->GetParent() != next->GetParent()) {
-            for (nsIFrame* ancestor = frame->GetParent(); ancestor;
-                 ancestor = ancestor->GetParent()) {
-              if (!ancestor->UpdateOverflow()) {
-                break;
+        // If |frame| is dirty or has dirty children, we don't bother updating
+        // overflows since that will happen when it's reflowed.
+        if (!(frame->GetStateBits() &
+              (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
+          while (frame) {
+            nsOverflowAreas* pre = static_cast<nsOverflowAreas*>
+              (frame->Properties().Get(frame->PreTransformOverflowAreasProperty()));
+            if (pre) {
+              // FinishAndStoreOverflow will change the overflow areas passed in,
+              // so make a copy.
+              nsOverflowAreas overflowAreas = *pre;
+              frame->FinishAndStoreOverflow(overflowAreas, frame->GetSize());
+            } else {
+              frame->UpdateOverflow();
+            }
+
+            nsIFrame* next =
+              nsLayoutUtils::GetNextContinuationOrSpecialSibling(frame);
+            // Update the ancestors' overflow after we have updated the overflow
+            // for all the continuations with the same parent.
+            if (!next || frame->GetParent() != next->GetParent()) {
+              for (nsIFrame* ancestor = frame->GetParent(); ancestor;
+                   ancestor = ancestor->GetParent()) {
+                if (!ancestor->UpdateOverflow()) {
+                  break;
+                }
               }
             }
+            frame = next;
           }
-          frame = next;
         }
       }
       if (hint & nsChangeHint_UpdateCursor) {
         mPresShell->SynthesizeMouseMove(false);
       }
     }
   }
 
--- a/layout/doc/adding-style-props.html
+++ b/layout/doc/adding-style-props.html
@@ -11,17 +11,17 @@
 <blockquote>
   <h4>Document history:</h4>
   <ul>
     <li>03/21/2002: Marc Attinasi (attinasi@netscape.com) created document
 / implementing -moz-force-broken-image-icon for bug <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=58646">
 58646</a></li>
     <li>
       6/18/2002: David Baron (dbaron@dbaron.org): corrected support
-      for 'inherit' and '-moz-initial' (didn't test with code, though),
+      for 'inherit' and 'initial' (didn't test with code, though),
       and explained what the final boolean in CheckPropertyData is for.
     </li>
     <li>
       11/09/2002: Christopher Aillon (caillon@returnzero.com): updated
       nsCSSPropList.h macro description and added information about
       nsIDOMCSS2Properties.idl.
     </li>
   </ul>
@@ -420,17 +420,17 @@ to the style struct:<br>
   else if (eCSSUnit_None == uiData.mResizer.GetUnit()) {
     ui-&gt;mResizer = NS_STYLE_RESIZER_NONE;
   }
   else if (eCSSUnit_Inherit == uiData.mResizer.GetUnit()) {
     inherited = PR_TRUE;
     ui-&gt;mResizer = parentUI-&gt;mResizer;
   }
 
-  <b>// force-broken-image-icons: integer, inherit, -moz-initial
+  <b>// force-broken-image-icons: integer, inherit, initial
   if (eCSSUnit_Integer == uiData.mForceBrokenImageIcons.GetUnit()) {
     ui-&gt;mForceBrokenImageIcons = uiData.mForceBrokenImageIcons.GetIntValue();
   } else if (eCSSUnit_Inherit == uiData.mForceBrokenImageIcons.GetUnit()) {
     inherited = PR_TRUE;
     ui-&gt;mForceBrokenImageIcons = parentUI-&gt;mForceBrokenImageIcons;
   } else if (eCSSUnit_Initial == uiData.mForceBrokenImageIcons.GetUnit()) {
     ui-&gt;mForceBrokenImageIcons = 0;
   }</b>
@@ -447,30 +447,21 @@ to the style struct:<br>
     // Propagate the bit down.
     PropagateDependentBit(NS_STYLE_INHERIT_UI_RESET, aHighestNode);
   }
   ...
 </pre>
   <h3><a name="DOM">DOM</a></h3>
 Users in scripts, or anywhere outside of layout/ or content/ may need to access
 the new property.  This is done using the CSS OM, specifically
-<code>nsIDOMCSSStyleDeclaration</code> and <code>nsIDOMCSS2Properties</code>.
+<code>nsIDOMCSSStyleDeclaration</code> and <code>CSS2Properties</code>.
 By the magic of C++ pre-processing, the
-CSS2Properties interfaces will be implemented automatically when you
+CSS2Properties bits will be implemented automatically when you
 <a href="#CSSPropList">add your property</a> to <a href="http://lxr.mozilla.org/seamonkey/source/content/shared/public/nsCSSPropList.h">
-nsCSSPropList.h</a>. Because of this, if you fail to add your property to the
-DOM interface, you will be rewarded with compiler errors.  All you have to do
-is modify <a href="http://lxr.mozilla.org/mozilla/source/dom/public/idl/css/nsIDOMCSS2Properties.idl">
-nsIDOMCSS2Properties.idl</a> and add the appropriate attribute to the
-<code>nsIDOMNSCSS2Properties</code> interface (lower in the file).
-For example:<br>
-  <pre>           attribute DOMString        MozForceBrokenImageIcon;
-                                        // raises(DOMException) on setting
-
-</pre>
+nsCSSPropList.h</a>.
   <h3><a name="Layout">Layout</a></h3>
 OK, finally the style system is supporting the new property. It is time to
 actually make use of it now.<br>
   <br>
 In layout, retrieve the styleStruct that has the new property from the frame's
 style context. Access the new property and get its value. It is that simple.
 For this example, it looks like this, in nsImageFrame:<br>
   <pre>        PRBool forceIcon = PR_FALSE;
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -639,21 +639,22 @@ nsComboboxControlFrame::GetAvailableDrop
   nsRect screen = nsFormControlFrame::GetUsableScreenRect(PresContext());
   if (mLastDropDownBelowScreenY == nscoord_MIN) {
     nsRect thisScreenRect = GetScreenRectInAppUnits();
     mLastDropDownBelowScreenY = thisScreenRect.YMost() + aTranslation->y;
     mLastDropDownAboveScreenY = thisScreenRect.y + aTranslation->y;
   }
 
   nscoord minY;
-  if (!PresContext()->IsChrome()) {
-    nsIFrame* root = PresContext()->PresShell()->GetRootFrame();
+  nsPresContext* pc = PresContext()->GetToplevelContentDocumentPresContext();
+  nsIFrame* root = pc ? pc->PresShell()->GetRootFrame() : nullptr;
+  if (root) {
     minY = root->GetScreenRectInAppUnits().y;
-    if (mLastDropDownBelowScreenY < root->GetScreenRectInAppUnits().y) {
-      // Don't allow the drop-down to be placed above the top of the root frame.
+    if (mLastDropDownBelowScreenY < minY) {
+      // Don't allow the drop-down to be placed above the content area.
       return;
     }
   } else {
     minY = screen.y;
   }
 
   nscoord below = screen.YMost() - mLastDropDownBelowScreenY;
   nscoord above = mLastDropDownAboveScreenY - minY;
@@ -675,20 +676,22 @@ nsComboboxControlFrame::GetAvailableDrop
 nsComboboxControlFrame::DropDownPositionState
 nsComboboxControlFrame::AbsolutelyPositionDropDown()
 {
   nsPoint translation;
   nscoord above, below;
   mLastDropDownBelowScreenY = nscoord_MIN;
   GetAvailableDropdownSpace(&above, &below, &translation);
   if (above <= 0 && below <= 0) {
-    // Hide the view immediately to minimize flicker.
-    nsIView* view = mDropdownFrame->GetView();
-    view->GetViewManager()->SetViewVisibility(view, nsViewVisibility_kHide);
-    NS_DispatchToCurrentThread(new nsAsyncRollup(this));
+    if (IsDroppedDown()) {
+      // Hide the view immediately to minimize flicker.
+      nsIView* view = mDropdownFrame->GetView();
+      view->GetViewManager()->SetViewVisibility(view, nsViewVisibility_kHide);
+      NS_DispatchToCurrentThread(new nsAsyncRollup(this));
+    }
     return eDropDownPositionSuppressed;
   }
 
   nsSize dropdownSize = mDropdownFrame->GetSize();
   nscoord height = NS_MAX(above, below);
   nsListControlFrame* lcf = static_cast<nsListControlFrame*>(mDropdownFrame);
   if (height < dropdownSize.height) {
     if (lcf->GetNumDisplayRows() > 1) {
--- a/layout/generic/crashtests/383089-1.html
+++ b/layout/generic/crashtests/383089-1.html
@@ -1,9 +1,9 @@
-<html style="width: 1px;" class="reftest-wait"><head style="float: left; position: fixed; display: -moz-initial;" id="head">
+<html style="width: 1px;" class="reftest-wait"><head style="float: left; position: fixed; display: initial;" id="head">
 <meta http-equiv="content-type" content="text/html; charset=UTF-8">
 
 
 
 <script style="display: none;" type="text/javascript;version=1.7">
 
 var iter;
 var interv;
@@ -56,31 +56,31 @@ function foo()
   br5.style.display = "inline";
   br3.style.clear = "both";
   br6.style.visibility = "visible";
   yield;
 
   tableRow.style.display = "list-item";
   br3.style.width = "auto";
   br2.style.clear = "none";
-  head.style.display = "-moz-initial"; // doesn't seem to crash when this is "block"!
+  head.style.display = "initial"; // doesn't seem to crash when this is "block"!
   docElem.style.width = "1px";
   
   document.documentElement.removeAttribute("class");
 }
 
 </script>
 
 <style>
 </style>
 
 </head><body onload="setTimeout(olo, 30);">
 
 <br style="overflow: visible;" id="br1">
 <br style="clear: none;" id="br2">
 <br style="height: auto; clear: both; width: auto;" id="br3">
 <br style="position: static;" id="br4">
-<br style="background: yellow none repeat scroll 0% 0%; background-clip: -moz-initial; background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; display: inline;" id="br5">
+<br style="background: yellow none repeat scroll 0% 0%; background-clip: initial; background-origin: initial; -moz-background-inline-policy: initial; display: inline;" id="br5">
 <br style="width: 1px; visibility: visible;" id="br6">
 <br style="color: black; width: 2px; display: table-cell;" id="br7">
 <table border="1"><tbody><tr style="display: list-item;" id="tableRow"><td>x</td></tr></tbody></table>
 
 </body></html>
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -1236,21 +1236,17 @@ nsObjectFrame::BuildDisplayList(nsDispla
     mInstanceOwner->GetWindow(window);
     bool isVisible = window && window->width > 0 && window->height > 0;
     if (isVisible && aBuilder->ShouldSyncDecodeImages()) {
   #ifndef XP_MACOSX
       mInstanceOwner->UpdateWindowVisibility(true);
   #endif
     }
 
-    nsRefPtr<ImageContainer> container = GetImageContainer();
-    if (container && (container->HasCurrentImage() || !isVisible ||
-        container->GetCurrentSize() != gfxIntSize(window->width, window->height))) {
-      mInstanceOwner->NotifyPaintWaiter(aBuilder);
-    }
+    mInstanceOwner->NotifyPaintWaiter(aBuilder);
   }
 
   // determine if we are printing
   if (type == nsPresContext::eContext_Print) {
     rv = replacedContent.AppendNewToTop(new (aBuilder)
         nsDisplayGeneric(aBuilder, this, PaintPrintPlugin, "PrintPlugin",
                          nsDisplayItem::TYPE_PRINT_PLUGIN));
   } else {
@@ -1519,30 +1515,16 @@ nsObjectFrame::PrintPlugin(nsRenderingCo
 
   // XXX Nav 4.x always sent a SetWindow call after print. Should we do the same?
   // XXX Calling DidReflow here makes no sense!!!
   nsDidReflowStatus status = NS_FRAME_REFLOW_FINISHED; // should we use a special status?
   frame->DidReflow(presContext,
                    nullptr, status);  // DidReflow will take care of it
 }
 
-already_AddRefed<ImageContainer>
-nsObjectFrame::GetImageContainer()
-{
-  nsRefPtr<ImageContainer> container = mImageContainer;
-
-  if (container) {
-    return container.forget();
-  }
-
-  container = mImageContainer = LayerManager::CreateImageContainer();
-
-  return container.forget();
-}
-
 nsRect
 nsObjectFrame::GetPaintedRect(nsDisplayPlugin* aItem)
 {
   if (!mInstanceOwner)
     return nsRect();
   nsRect r = GetContentRectRelativeToSelf();
   if (!mInstanceOwner->UseAsyncRendering())
     return r;
@@ -1559,21 +1541,16 @@ nsObjectFrame::UpdateImageLayer(const gf
 {
   if (!mInstanceOwner) {
     return;
   }
 
 #ifdef XP_MACOSX
   if (!mInstanceOwner->UseAsyncRendering()) {
     mInstanceOwner->DoCocoaEventDrawRect(aRect, nullptr);
-    // This makes sure the image on the container is up to date.
-    // XXX - Eventually we probably just want to make sure DoCocoaEventDrawRect
-    // updates the image container, to make this truly use 'push' semantics
-    // too.
-    mInstanceOwner->GetImageContainer();
   }
 #endif
 }
 
 LayerState
 nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder,
                              LayerManager* aManager)
 {
@@ -1613,24 +1590,16 @@ nsObjectFrame::BuildLayer(nsDisplayListB
   NPWindow* window = nullptr;
   mInstanceOwner->GetWindow(window);
   if (!window)
     return nullptr;
 
   if (window->width <= 0 || window->height <= 0)
     return nullptr;
 
-  // Create image
-  nsRefPtr<ImageContainer> container = mInstanceOwner->GetImageContainer();
-
-  if (!container) {
-    // This can occur if our instance is gone.
-    return nullptr;
-  }
-
   // window is in "display pixels", but size needs to be in device pixels
   double scaleFactor = 1.0;
   if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
     scaleFactor = 1.0;
   }
   int intScaleFactor = ceil(scaleFactor);
   gfxIntSize size(window->width * intScaleFactor, window->height * intScaleFactor);
 
@@ -1645,18 +1614,24 @@ nsObjectFrame::BuildLayer(nsDisplayListB
     if (!layer) {
       mInstanceOwner->NotifyPaintWaiter(aBuilder);
       // Initialize ImageLayer
       layer = aManager->CreateImageLayer();
       if (!layer)
         return nullptr;
     }
 
+    // Create image
+    nsRefPtr<ImageContainer> container = mInstanceOwner->GetImageContainer();
+    if (!container) {
+      // This can occur if our instance is gone.
+      return nullptr;
+    }
+
     NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "Bad layer type");
-
     ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
     UpdateImageLayer(r);
 
     imglayer->SetScaleToSize(size, ImageLayer::SCALE_STRETCH);
     imglayer->SetContainer(container);
     gfxPattern::GraphicsFilter filter =
       nsLayoutUtils::GetGraphicsFilterForFrame(this);
 #ifdef MOZ_GFX_OPTIMIZE_MOBILE
--- a/layout/generic/nsObjectFrame.h
+++ b/layout/generic/nsObjectFrame.h
@@ -168,17 +168,16 @@ public:
   already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                      LayerManager* aManager,
                                      nsDisplayItem* aItem,
                                      const ContainerParameters& aContainerParameters);
 
   LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                            LayerManager* aManager);
 
-  already_AddRefed<ImageContainer> GetImageContainer();
   /**
    * Get the rectangle (relative to this frame) which it will paint. Normally
    * the frame's content-box but may be smaller if the plugin is rendering
    * asynchronously and has a different-sized image temporarily.
    */
   nsRect GetPaintedRect(nsDisplayPlugin* aItem);
 
   /**
@@ -285,20 +284,16 @@ private:
   /**
    * Clip region that we should set the plugin's widget to
    * in the next composite. Only meaningful for plugins with widgets.
    */
   nsTArray<nsIntRect>             mNextConfigurationClipRegion;
 
   bool mReflowCallbackPosted;
 
-  // A reference to the ImageContainer which contains the current frame
-  // of plugin to display.
-  nsRefPtr<ImageContainer> mImageContainer;
-
   // We keep this reference to ensure we can always unregister the
   // plugins we register on the root PresContext.
   // This is only non-null while we have a plugin registered for geometry
   // updates.
   nsRefPtr<nsRootPresContext> mRootPresContextRegisteredWith;
 };
 
 class nsDisplayPlugin : public nsDisplayItem {
--- a/layout/reftests/bugs/455105-1.html
+++ b/layout/reftests/bugs/455105-1.html
@@ -11,17 +11,17 @@ div#below {
 }
 div#above {
   position: absolute;
   top: 10px; left: 10px;
   width: 40px;
   height: 40px;
   border-width: 10px;
   border-style: solid;
-  border-color: -moz-initial;
+  border-color: initial;
   color: rgba(0,0,0,0);
   background-image: url("data:image/gif;base64,\
 R0lGODlhAQABAPAAAACAAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==");
 }
 </style>
 </head><body>
 <div id="below"></div>
 <div id="above"></div>
--- a/layout/reftests/css-visited/border-1.html
+++ b/layout/reftests/css-visited/border-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE HTML>
 <title>Test for privacy restrictions on :visited (Bug 147777)</title>
 <style type="text/css">
 
-a { text-decoration: none; color: -moz-initial; display: block; margin: 2px; }
+a { text-decoration: none; color: initial; display: block; margin: 2px; }
 :link { border: medium solid olive; border-top: dashed thin blue; }
 :visited { border: thick dotted fuchsia; border-right: thin double silver; }
 
 </style>
 <a href="unvisited-page.html">unvisited</a>
 <a href="visited-page.html">visited</a>
--- a/layout/reftests/css-visited/border-collapse-1.html
+++ b/layout/reftests/css-visited/border-collapse-1.html
@@ -1,15 +1,15 @@
 <!DOCTYPE HTML>
 <title>Test for privacy restrictions on :visited (Bug 147777)</title>
 <style type="text/css">
 
 div.table { display: table; border-collapse: collapse }
 div.row { display: table-row }
-a { text-decoration: none; color: -moz-initial; display: table-cell }
+a { text-decoration: none; color: initial; display: table-cell }
 
 .row1 :link { border: medium solid blue }
 .row1 :visited { border: thick dashed fuchsia }
 
 .row2 :link { border: thin dotted black }
 .row2 :visited { border: thick hidden rgba(255, 0, 0, 0.5) }
 
 .row3 :link { border: 7px double gray }
--- a/layout/reftests/css-visited/color-choice-1.html
+++ b/layout/reftests/css-visited/color-choice-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE HTML>
 <title>Test for privacy restrictions on :visited (Bug 147777)</title>
 <style type="text/css">
 
-a { text-decoration: none; color: -moz-initial; }
+a { text-decoration: none; color: initial; }
 :link { background: rgba(179, 25, 87, 0.72); }
 :visited { background: rgba(28, 215, 119, 0.31); }
 
 </style>
 <a href="unvisited-page.html">unvisited</a>
 <a href="visited-page.html">visited</a>
--- a/layout/reftests/css-visited/column-rule-1.html
+++ b/layout/reftests/css-visited/column-rule-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE HTML>
 <title>Test for privacy restrictions on :visited (Bug 147777)</title>
 <style type="text/css">
 
-a { text-decoration: none; color: -moz-initial; display: block; margin: 8px; -moz-column-count: 2; }
+a { text-decoration: none; color: initial; display: block; margin: 8px; -moz-column-count: 2; }
 :link { -moz-column-rule: medium dotted blue; }
 :visited { -moz-column-rule: thick dashed silver; }
 
 </style>
 <a href="unvisited-page.html">unvisited<br>link</a>
 <a href="visited-page.html">visited<br>link</a>
--- a/layout/reftests/css-visited/content-on-link-before-1.html
+++ b/layout/reftests/css-visited/content-on-link-before-1.html
@@ -1,8 +1,8 @@
 <!DOCTYPE HTML>
 <title>Test for privacy restrictions on :visited (Bug 147777)</title>
 <style type="text/css">
-* { color: -moz-initial; text-decoration: none }
+* { color: initial; text-decoration: none }
 :link:before { content: "link"; }
 :visited:before { content: "visited"; }
 </style>
 <a href="unvisited-page.html"></a>
--- a/layout/reftests/css-visited/content-on-visited-before-1.html
+++ b/layout/reftests/css-visited/content-on-visited-before-1.html
@@ -1,8 +1,8 @@
 <!DOCTYPE HTML>
 <title>Test for privacy restrictions on :visited (Bug 147777)</title>
 <style type="text/css">
-* { color: -moz-initial; text-decoration: none }
+* { color: initial; text-decoration: none }
 :link:before { content: "link"; }
 :visited:before { content: "visited"; }
 </style>
 <a href="visited-page.html"></a>
--- a/layout/reftests/css-visited/outline-1.html
+++ b/layout/reftests/css-visited/outline-1.html
@@ -1,11 +1,11 @@
 <!DOCTYPE HTML>
 <title>Test for privacy restrictions on :visited (Bug 147777)</title>
 <style type="text/css">
 
-a { text-decoration: none; color: -moz-initial; display: block; margin: 8px; }
+a { text-decoration: none; color: initial; display: block; margin: 8px; }
 :link { outline: medium dotted blue; }
 :visited { outline: thick dashed silver; }
 
 </style>
 <a href="unvisited-page.html">unvisited</a>
 <a href="visited-page.html">visited</a>
--- a/layout/reftests/flexbox/flexbox-align-self-horiz-1-block.xhtml
+++ b/layout/reftests/flexbox/flexbox-align-self-horiz-1-block.xhtml
@@ -12,17 +12,17 @@
         border: 1px dashed blue;
         height: 200px;
         width: -moz-fit-content;
         display: flex;
         font-size: 10px;
         line-height: 10px;
 
         /* Any children whose align-self is 'auto' (or unspecified, or
-           -moz-initial) will end up taking this value from us: */
+           initial) will end up taking this value from us: */
         align-items: center;
 
         /* Any children whose align-self is 'inherit' will end up
            inheriting this value from us: */
         align-self: flex-end;
       }
 
       .flexbox > div {
@@ -60,17 +60,17 @@
         background: yellow;
         align-self: auto;
       }
       .unspecified {
         background: lightgreen;
       }
       .initial {
         background: aqua;
-        align-self: -moz-initial;
+        align-self: initial;
       }
       .inherit {
         background: violet;
         align-self: inherit;
       }
    </style>
   </head>
   <body>
--- a/layout/reftests/flexbox/flexbox-align-self-horiz-1-table.xhtml
+++ b/layout/reftests/flexbox/flexbox-align-self-horiz-1-table.xhtml
@@ -12,17 +12,17 @@
         border: 1px dashed blue;
         height: 200px;
         width: -moz-fit-content;
         display: flex;
         font-size: 10px;
         line-height: 10px;
 
         /* Any children whose align-self is 'auto' (or unspecified, or
-           -moz-initial) will end up taking this value from us: */
+           initial) will end up taking this value from us: */
         align-items: center;
 
         /* Any children whose align-self is 'inherit' will end up
            inheriting this value from us: */
         align-self: flex-end;
       }
 
       .flexbox > * {
@@ -62,17 +62,17 @@
         background: yellow;
         align-self: auto;
       }
       .unspecified {
         background: lightgreen;
       }
       .initial {
         background: aqua;
-        align-self: -moz-initial;
+        align-self: initial;
       }
       .inherit {
         background: violet;
         align-self: inherit;
       }
    </style>
   </head>
   <body>
--- a/layout/reftests/flexbox/flexbox-align-self-horiz-3.xhtml
+++ b/layout/reftests/flexbox/flexbox-align-self-horiz-3.xhtml
@@ -55,17 +55,17 @@
         background: yellow;
         align-self: auto;
       }
       .unspecified {
         background: lightgreen;
       }
       .initial {
         background: aqua;
-        align-self: -moz-initial;
+        align-self: initial;
       }
       .inherit {
         background: violet;
         align-self: inherit;
       }
    </style>
   </head>
   <body>
--- a/layout/reftests/flexbox/flexbox-align-self-vert-1.xhtml
+++ b/layout/reftests/flexbox/flexbox-align-self-vert-1.xhtml
@@ -11,17 +11,17 @@
       .flexbox {
         border: 1px dashed blue;
         width: 200px;
         display: flex;
         flex-direction: column;
         font-size: 10px;
 
         /* Any children whose align-self is 'auto' (or unspecified, or
-           -moz-initial) will end up taking this value from us: */
+           initial) will end up taking this value from us: */
         align-items: center;
 
         /* Any children whose align-self is 'inherit' will end up
            inheriting this value from us: */
         align-self: flex-end;
       }
 
       .big {
@@ -54,17 +54,17 @@
         background: yellow;
         align-self: auto;
       }
       .unspecified {
         background: lightgreen;
       }
       .initial {
         background: aqua;
-        align-self: -moz-initial;
+        align-self: initial;
       }
       .inherit {
         background: violet;
         align-self: inherit;
       }
    </style>
   </head>
   <body>
--- a/layout/reftests/flexbox/flexbox-align-self-vert-rtl-1.xhtml
+++ b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-1.xhtml
@@ -14,17 +14,17 @@
         width: 200px;
         display: flex;
         flex-direction: column;
         direction: rtl;
         font-family: sans-serif;
         font-size: 10px;
 
         /* Any children whose align-self is 'auto' (or unspecified, or
-           -moz-initial) will end up taking this value from us: */
+           initial) will end up taking this value from us: */
         align-items: center;
 
         /* Any children whose align-self is 'inherit' will end up
            inheriting this value from us: */
         align-self: flex-end;
       }
 
       .big {
@@ -57,17 +57,17 @@
         background: yellow;
         align-self: auto;
       }
       .unspecified {
         background: lightgreen;
       }
       .initial {
         background: aqua;
-        align-self: -moz-initial;
+        align-self: initial;
       }
       .inherit {
         background: violet;
         align-self: inherit;
       }
    </style>
   </head>
   <body>
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -280,16 +280,17 @@ CSS_KEY(interlace, interlace)
 CSS_KEY(inactive, inactive)
 CSS_KEY(inactiveborder, inactiveborder)
 CSS_KEY(inactivecaption, inactivecaption)
 CSS_KEY(inactivecaptiontext, inactivecaptiontext)
 CSS_KEY(infinite, infinite)
 CSS_KEY(infobackground, infobackground)
 CSS_KEY(infotext, infotext)
 CSS_KEY(inherit, inherit)
+CSS_KEY(initial, initial)
 CSS_KEY(inline, inline)
 CSS_KEY(inline-axis, inline_axis)
 CSS_KEY(inline-block, inline_block)
 CSS_KEY(inline-flex, inline_flex)
 CSS_KEY(inline-table, inline_table)
 CSS_KEY(inset, inset)
 CSS_KEY(inside, inside)
 CSS_KEY(interpolatematrix, interpolatematrix)
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -4710,17 +4710,18 @@ CSSParserImpl::ParseVariant(nsCSSValue& 
       if ((aVariantMask & VARIANT_INHERIT) != 0) {
         // XXX Should we check IsParsingCompoundProperty, or do all
         // callers handle it?  (Not all callers set it, though, since
         // they want the quirks that are disabled by setting it.)
         if (eCSSKeyword_inherit == keyword) {
           aValue.SetInheritValue();
           return true;
         }
-        else if (eCSSKeyword__moz_initial == keyword) { // anything that can inherit can also take an initial val.
+        else if (eCSSKeyword__moz_initial == keyword ||
+                 eCSSKeyword_initial == keyword) { // anything that can inherit can also take an initial val.
           aValue.SetInitialValue();
           return true;
         }
       }
       if ((aVariantMask & VARIANT_NONE) != 0) {
         if (eCSSKeyword_none == keyword) {
           aValue.SetNoneValue();
           return true;
@@ -6479,17 +6480,18 @@ CSSParserImpl::ParseBackgroundItem(CSSPa
       // show up as one.
       break;
     }
 
     if (tt == eCSSToken_Ident) {
       nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
       int32_t dummy;
       if (keyword == eCSSKeyword_inherit ||
-          keyword == eCSSKeyword__moz_initial) {
+          keyword == eCSSKeyword__moz_initial ||
+          keyword == eCSSKeyword_initial) {
         return false;
       } else if (keyword == eCSSKeyword_none) {
         if (haveImage)
           return false;
         haveImage = true;
         if (!ParseSingleValueProperty(aState.mImage->mValue,
                                       eCSSProperty_background_image)) {
           NS_NOTREACHED("should be able to parse");
@@ -7273,31 +7275,31 @@ CSSParserImpl::ParseBorderImageRepeat(bo
   return true;
 }
 
 bool
 CSSParserImpl::ParseBorderImage()
 {
   nsAutoParseCompoundProperty compound(this);
 
-  // border-image: inherit | -moz-initial |
+  // border-image: inherit | initial |
   // <border-image-source> ||
   // <border-image-slice>
   //   [ / <border-image-width> |
   //     / <border-image-width>? / <border-image-outset> ]? ||
   // <border-image-repeat>
 
   nsCSSValue value;
   if (ParseVariant(value, VARIANT_INHERIT, nullptr)) {
     AppendValue(eCSSProperty_border_image_source, value);
     AppendValue(eCSSProperty_border_image_slice, value);
     AppendValue(eCSSProperty_border_image_width, value);
     AppendValue(eCSSProperty_border_image_outset, value);
     AppendValue(eCSSProperty_border_image_repeat, value);
-    // Keyword "inherit" (and "-moz-initial") can't be mixed, so we are done.
+    // Keyword "inherit" (and "initial") can't be mixed, so we are done.
     return true;
   }
 
   // No empty property.
   if (CheckEndProperty()) {
     return false;
   }
 
@@ -7857,16 +7859,17 @@ CSSParserImpl::ParseRect(nsCSSProperty a
         val.SetAutoValue();
         break;
       case eCSSKeyword_inherit:
         if (!ExpectEndProperty()) {
           return false;
         }
         val.SetInheritValue();
         break;
+      case eCSSKeyword_initial:
       case eCSSKeyword__moz_initial:
         if (!ExpectEndProperty()) {
           return false;
         }
         val.SetInitialValue();
         break;
       default:
         UngetToken();
@@ -8692,17 +8695,17 @@ CSSParserImpl::ParseFamily(nsCSSValue& a
     return false;
 
   if (eCSSToken_Ident == mToken.mType) {
     nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
     if (keyword == eCSSKeyword_inherit) {
       aValue.SetInheritValue();
       return true;
     }
-    if (keyword == eCSSKeyword__moz_initial) {
+    if (keyword == eCSSKeyword__moz_initial || keyword == eCSSKeyword_initial) {
       aValue.SetInitialValue();
       return true;
     }
     if (keyword == eCSSKeyword__moz_use_system_font &&
         !IsParsingCompoundProperty()) {
       aValue.SetSystemFontValue();
       return true;
     }
@@ -9511,17 +9514,17 @@ AppendValueToList(nsCSSValue& aContainer
 CSSParserImpl::ParseAnimationOrTransitionShorthandResult
 CSSParserImpl::ParseAnimationOrTransitionShorthand(
                  const nsCSSProperty* aProperties,
                  const nsCSSValue* aInitialValues,
                  nsCSSValue* aValues,
                  size_t aNumProperties)
 {
   nsCSSValue tempValue;
-  // first see if 'inherit' or '-moz-initial' is specified.  If one is,
+  // first see if 'inherit' or 'initial' is specified.  If one is,
   // it can be the only thing specified, so don't attempt to parse any
   // additional properties
   if (ParseVariant(tempValue, VARIANT_INHERIT, nullptr)) {
     for (uint32_t i = 0; i < aNumProperties; ++i) {
       AppendValue(aProperties[i], tempValue);
     }
     return eParseAnimationOrTransitionShorthand_Inherit;
   }
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -1432,32 +1432,29 @@ AppendSerializedUnicodeRange(nsCSSValue 
 // Mapping from nsCSSFontDesc codes to nsCSSFontFaceStyleDecl fields.
 nsCSSValue nsCSSFontFaceStyleDecl::* const
 nsCSSFontFaceStyleDecl::Fields[] = {
 #define CSS_FONT_DESC(name_, method_) &nsCSSFontFaceStyleDecl::m##method_,
 #include "nsCSSFontDescList.h"
 #undef CSS_FONT_DESC
 };
 
-DOMCI_DATA(CSSFontFaceStyleDecl, nsCSSFontFaceStyleDecl)
-
 // QueryInterface implementation for nsCSSFontFaceStyleDecl
 NS_INTERFACE_MAP_BEGIN(nsCSSFontFaceStyleDecl)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleDeclaration)
   NS_INTERFACE_MAP_ENTRY(nsICSSDeclaration)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   // We forward the cycle collection interfaces to ContainingRule(), which is
   // never null (in fact, we're part of that object!)
   if (aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ||
       aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
     return ContainingRule()->QueryInterface(aIID, aInstancePtr);
   }
   else
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSFontFaceStyleDecl)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
 NS_IMPL_RELEASE_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
 
 // helper for string GetPropertyValue and RemovePropertyValue
 nsresult
 nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID,
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -1067,17 +1067,17 @@ nsCSSValue::AppendToString(nsCSSProperty
         break;
     }
   }
 
   switch (unit) {
     case eCSSUnit_Null:         break;
     case eCSSUnit_Auto:         aResult.AppendLiteral("auto");     break;
     case eCSSUnit_Inherit:      aResult.AppendLiteral("inherit");  break;
-    case eCSSUnit_Initial:      aResult.AppendLiteral("-moz-initial"); break;
+    case eCSSUnit_Initial:      aResult.AppendLiteral("initial");  break;
     case eCSSUnit_None:         aResult.AppendLiteral("none");     break;
     case eCSSUnit_Normal:       aResult.AppendLiteral("normal");   break;
     case eCSSUnit_System_Font:  aResult.AppendLiteral("-moz-use-system-font"); break;
     case eCSSUnit_All:          aResult.AppendLiteral("all"); break;
     case eCSSUnit_Dummy:
     case eCSSUnit_DummyInherit:
       NS_ABORT_IF_FALSE(false, "should never serialize");
       break;
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -7,17 +7,16 @@
 /* DOM object returned from element.getComputedStyle() */
 
 #include "mozilla/Util.h"
 
 #include "nsComputedDOMStyle.h"
 
 #include "nsError.h"
 #include "nsDOMString.h"
-#include "nsIDOMCSS2Properties.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMCSSPrimitiveValue.h"
 #include "nsStyleContext.h"
 #include "nsIScrollableFrame.h"
 #include "nsContentUtils.h"
 #include "prprf.h"
 
 #include "nsCSSProps.h"
--- a/layout/style/nsDOMCSSDeclaration.cpp
+++ b/layout/style/nsDOMCSSDeclaration.cpp
@@ -13,34 +13,29 @@
 #include "nsIStyleRule.h"
 #include "mozilla/css/Rule.h"
 #include "mozilla/css/Declaration.h"
 #include "nsCSSProps.h"
 #include "nsCOMPtr.h"
 #include "nsIURL.h"
 #include "nsReadableUtils.h"
 #include "nsIPrincipal.h"
-#include "nsDOMClassInfoID.h"
 #include "mozAutoDocUpdate.h"
 
 namespace css = mozilla::css;
 
 nsDOMCSSDeclaration::~nsDOMCSSDeclaration()
 {
 }
 
-DOMCI_DATA(CSSStyleDeclaration, nsDOMCSSDeclaration)
-
 NS_INTERFACE_TABLE_HEAD(nsDOMCSSDeclaration)
-  NS_INTERFACE_TABLE3(nsDOMCSSDeclaration,
+  NS_INTERFACE_TABLE2(nsDOMCSSDeclaration,
                       nsICSSDeclaration,
-                      nsIDOMCSSStyleDeclaration,
-                      nsIDOMCSS2Properties)
+                      nsIDOMCSSStyleDeclaration)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSStyleDeclaration)
 NS_INTERFACE_MAP_END
 
 NS_IMETHODIMP
 nsDOMCSSDeclaration::GetPropertyValue(const nsCSSProperty aPropID,
                                       nsAString& aValue)
 {
   NS_PRECONDITION(aPropID != eCSSProperty_UNKNOWN,
                   "Should never pass eCSSProperty_UNKNOWN around");
@@ -298,40 +293,8 @@ nsDOMCSSDeclaration::RemoveProperty(cons
   // between when we mutate the declaration and when we set the new
   // rule (see stack in bug 209575).
   mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
 
   decl = decl->EnsureMutable();
   decl->RemoveProperty(aPropID);
   return SetCSSDeclaration(decl);
 }
-
-// nsIDOMCSS2Properties
-
-#define CSS_PROP_DOMPROP_PREFIXED(prop_) Moz ## prop_
-#define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_,          \
-                 kwtable_, stylestruct_, stylestructoffset_, animtype_)      \
-  NS_IMETHODIMP                                                              \
-  nsDOMCSSDeclaration::Get##method_(nsAString& aValue)                       \
-  {                                                                          \
-    return GetPropertyValue(eCSSProperty_##id_, aValue);                     \
-  }                                                                          \
-                                                                             \
-  NS_IMETHODIMP                                                              \
-  nsDOMCSSDeclaration::Set##method_(const nsAString& aValue)                 \
-  {                                                                          \
-    return SetPropertyValue(eCSSProperty_##id_, aValue);                     \
-  }
-
-#define CSS_PROP_LIST_EXCLUDE_INTERNAL
-#define CSS_PROP_SHORTHAND(name_, id_, method_, flags_, pref_)  \
-  CSS_PROP(name_, id_, method_, flags_, pref_, X, X, X, X, X)
-#include "nsCSSPropList.h"
-
-#define CSS_PROP_ALIAS(aliasname_, propid_, aliasmethod_, pref_)  \
-  CSS_PROP(X, propid_, aliasmethod_, X, pref_, X, X, X, X, X)
-#include "nsCSSPropAliasList.h"
-#undef CSS_PROP_ALIAS
-
-#undef CSS_PROP_SHORTHAND
-#undef CSS_PROP_LIST_EXCLUDE_INTERNAL
-#undef CSS_PROP
-#undef CSS_PROP_DOMPROP_PREFIXED
--- a/layout/style/nsDOMCSSDeclaration.h
+++ b/layout/style/nsDOMCSSDeclaration.h
@@ -5,35 +5,33 @@
 
 /* base class for DOM objects for element.style and cssStyleRule.style */
 
 #ifndef nsDOMCSSDeclaration_h___
 #define nsDOMCSSDeclaration_h___
 
 #include "mozilla/Attributes.h"
 #include "nsICSSDeclaration.h"
-#include "nsIDOMCSS2Properties.h"
 #include "nsCOMPtr.h"
 #include "mozilla/dom/CSS2PropertiesBinding.h"
 
 class nsCSSParser;
 class nsIURI;
 class nsIPrincipal;
 class nsIDocument;
 
 namespace mozilla {
 namespace css {
 class Declaration;
 class Loader;
 class Rule;
 }
 }
 
-class nsDOMCSSDeclaration : public nsICSSDeclaration,
-                            public nsIDOMCSS2Properties
+class nsDOMCSSDeclaration : public nsICSSDeclaration
 {
 public:
   // Only implement QueryInterface; subclasses have the responsibility
   // of implementing AddRef/Release.
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
 
   // Declare addref and release so they can be called on us, but don't
   // implement them.  Our subclasses must handle their own
@@ -56,20 +54,16 @@ public:
                             nsAString & _retval);
   NS_IMETHOD GetPropertyPriority(const nsAString & propertyName,
                                  nsAString & _retval) MOZ_OVERRIDE;
   NS_IMETHOD SetProperty(const nsAString & propertyName,
                          const nsAString & value, const nsAString & priority) MOZ_OVERRIDE;
   NS_IMETHOD GetLength(uint32_t *aLength) MOZ_OVERRIDE;
   NS_IMETHOD GetParentRule(nsIDOMCSSRule * *aParentRule) MOZ_OVERRIDE = 0;
 
-  // We implement this as a shim which forwards to GetPropertyValue
-  // and SetPropertyValue; subclasses need not.
-  NS_DECL_NSIDOMCSS2PROPERTIES
-
   // WebIDL interface for CSS2Properties
 #define CSS_PROP_DOMPROP_PREFIXED(prop_) Moz ## prop_
 #define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_,          \
                  kwtable_, stylestruct_, stylestructoffset_, animtype_)      \
   void                                                                       \
   Get##method_(nsAString& aValue, mozilla::ErrorResult& rv)                  \
   {                                                                          \
     rv = GetPropertyValue(eCSSProperty_##id_, aValue);                       \
--- a/layout/style/quirk.css
+++ b/layout/style/quirk.css
@@ -39,30 +39,30 @@ li > ol:-moz-first-node {
 }
 
 
 /* Quirk: prevent bullet from resizing with the list item
  *   see bug 97351
  */
 
 li::-moz-list-bullet {
-  font-size: -moz-initial;
+  font-size: initial;
 }
 
 
 table {
   text-align: start;
   white-space: normal; /* compatible with IE & spec */
   line-height: normal;
 
   /* Quirk: cut off all font inheritance in tables except for family. */
-  font-siz