Merge inbound to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 16 Dec 2013 16:58:27 -0500
changeset 160710 8aa46cd4c63c17147e0227325b40eb450b463b3d
parent 160709 fcb3b07e715475c65f624ffa403d717b38a5395b (current diff)
parent 160662 b2c07abf977a7d1d71a454eaa1b218af9a6ca2fa (diff)
child 160711 93eccb617652b06e18714204a7b38f3d8ac6b7ea
child 160759 c12ebde00d1525610508c21fb9a8ba5bb9a7694b
child 160760 a67bbbff877261d3db37901ab3cdc1c2c671af5d
push id37671
push userryanvm@gmail.com
push dateMon, 16 Dec 2013 21:59:33 +0000
treeherdermozilla-inbound@93eccb617652 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to m-c.
dom/base/nsGlobalWindow.cpp
dom/browser-element/mochitest/browserElementTestHelpers.js
layout/style/nsDOMMediaQueryList.cpp
layout/style/nsDOMMediaQueryList.h
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -3262,46 +3262,46 @@ KeyBinding::ToPlatformFormat(nsAString& 
     stringBundleService->CreateBundle(
       "chrome://global-platform/locale/platformKeys.properties",
       getter_AddRefs(keyStringBundle));
 
   if (!keyStringBundle)
     return;
 
   nsAutoString separator;
-  keyStringBundle->GetStringFromName(NS_LITERAL_STRING("MODIFIER_SEPARATOR").get(),
+  keyStringBundle->GetStringFromName(MOZ_UTF16("MODIFIER_SEPARATOR"),
                                      getter_Copies(separator));
 
   nsAutoString modifierName;
   if (mModifierMask & kControl) {
-    keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_CONTROL").get(),
+    keyStringBundle->GetStringFromName(MOZ_UTF16("VK_CONTROL"),
                                        getter_Copies(modifierName));
 
     aValue.Append(modifierName);
     aValue.Append(separator);
   }
 
   if (mModifierMask & kAlt) {
-    keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_ALT").get(),
+    keyStringBundle->GetStringFromName(MOZ_UTF16("VK_ALT"),
                                        getter_Copies(modifierName));
 
     aValue.Append(modifierName);
     aValue.Append(separator);
   }
 
   if (mModifierMask & kShift) {
-    keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_SHIFT").get(),
+    keyStringBundle->GetStringFromName(MOZ_UTF16("VK_SHIFT"),
                                        getter_Copies(modifierName));
 
     aValue.Append(modifierName);
     aValue.Append(separator);
   }
 
   if (mModifierMask & kMeta) {
-    keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_META").get(),
+    keyStringBundle->GetStringFromName(MOZ_UTF16("VK_META"),
                                        getter_Copies(modifierName));
 
     aValue.Append(modifierName);
     aValue.Append(separator);
   }
 
   aValue.Append(mKey);
 }
--- a/accessible/src/generic/ApplicationAccessible.cpp
+++ b/accessible/src/generic/ApplicationAccessible.cpp
@@ -77,17 +77,17 @@ ApplicationAccessible::Name(nsString& aN
 
   nsCOMPtr<nsIStringBundle> bundle;
   nsresult rv = bundleService->CreateBundle("chrome://branding/locale/brand.properties",
                                             getter_AddRefs(bundle));
   if (NS_FAILED(rv))
     return eNameOK;
 
   nsXPIDLString appName;
-  rv = bundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
+  rv = bundle->GetStringFromName(MOZ_UTF16("brandShortName"),
                                  getter_Copies(appName));
   if (NS_FAILED(rv) || appName.IsEmpty()) {
     NS_WARNING("brandShortName not found, using default app name");
     appName.AssignLiteral("Gecko based application");
   }
 
   aName.Assign(appName);
   return eNameOK;
--- a/browser/components/shell/src/nsGNOMEShellService.cpp
+++ b/browser/components/shell/src/nsGNOMEShellService.cpp
@@ -280,17 +280,17 @@ nsGNOMEShellService::SetDefaultBrowser(b
       do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIStringBundle> brandBundle;
     rv = bundleService->CreateBundle(BRAND_PROPERTIES, getter_AddRefs(brandBundle));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsString brandShortName;
-    brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
+    brandBundle->GetStringFromName(MOZ_UTF16("brandShortName"),
                                    getter_Copies(brandShortName));
 
     // use brandShortName as the application id.
     NS_ConvertUTF16toUTF8 id(brandShortName);
     nsCOMPtr<nsIGIOMimeApp> appInfo;
     rv = giovfs->CreateAppFromCommand(mAppPath,
                                       id,
                                       getter_AddRefs(appInfo));
@@ -425,17 +425,17 @@ nsGNOMEShellService::SetDesktopBackgroun
   nsString brandName;
   nsCID bundleCID = NS_STRINGBUNDLESERVICE_CID;
   nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(bundleCID));
   if (bundleService) {
     nsCOMPtr<nsIStringBundle> brandBundle;
     rv = bundleService->CreateBundle(BRAND_PROPERTIES,
                                      getter_AddRefs(brandBundle));
     if (NS_SUCCEEDED(rv) && brandBundle) {
-      rv = brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
+      rv = brandBundle->GetStringFromName(MOZ_UTF16("brandShortName"),
                                           getter_Copies(brandName));
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   // build the file name
   filePath.Append('/');
   filePath.Append(NS_ConvertUTF16toUTF8(brandName));
--- a/browser/components/shell/src/nsWindowsShellService.cpp
+++ b/browser/components/shell/src/nsWindowsShellService.cpp
@@ -862,17 +862,17 @@ nsWindowsShellService::SetDesktopBackgro
   nsCOMPtr<nsIStringBundle> shellBundle;
   rv = bundleService->CreateBundle(SHELLSERVICE_PROPERTIES,
                                    getter_AddRefs(shellBundle));
   NS_ENSURE_SUCCESS(rv, rv);
  
   // e.g. "Desktop Background.bmp"
   nsString fileLeafName;
   rv = shellBundle->GetStringFromName
-                      (NS_LITERAL_STRING("desktopBackgroundLeafNameWin").get(),
+                      (MOZ_UTF16("desktopBackgroundLeafNameWin"),
                        getter_Copies(fileLeafName));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // get the profile root directory
   nsCOMPtr<nsIFile> file;
   rv = NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR,
                               getter_AddRefs(file));
   NS_ENSURE_SUCCESS(rv, rv);
--- a/browser/metro/shell/commandexecutehandler/CEHHelper.cpp
+++ b/browser/metro/shell/commandexecutehandler/CEHHelper.cpp
@@ -103,34 +103,32 @@ IsProcessRunning(const wchar_t *processN
       }
     }
   }
 
   CloseHandle(snapshot);
   return exists;
 }
 
-
+/*
+ * Retrieve the last front end ui we launched so we can target it
+ * again. This value is updated down in nsAppRunner when the browser
+ * starts up.
+ */
 AHE_TYPE
 GetLastAHE()
 {
   DWORD ahe;
   if (GetDWORDRegKey(metroLastAHE, ahe)) {
     return (AHE_TYPE) ahe;
   }
   return AHE_DESKTOP;
 }
 
 bool
-SetLastAHE(AHE_TYPE ahe)
-{
-  return SetDWORDRegKey(metroLastAHE, (DWORD) ahe);
-}
-
-bool
 IsDX10Available()
 {
   DWORD isDX10Available;
   if (GetDWORDRegKey(metroDX10Available, isDX10Available)) {
     return isDX10Available;
   }
 
   HMODULE dxgiModule = LoadLibraryA("dxgi.dll");
--- a/browser/metro/shell/commandexecutehandler/CommandExecuteHandler.cpp
+++ b/browser/metro/shell/commandexecutehandler/CommandExecuteHandler.cpp
@@ -15,17 +15,16 @@
 #include <shlwapi.h>
 #include <propkey.h>
 #include <propvarutil.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <strsafe.h>
 #include <io.h>
 #include <shellapi.h>
-#include <wininet.h>
 
 #ifdef SHOW_CONSOLE
 #define DEBUG_DELAY_SHUTDOWN 1
 #endif
 
 // Heartbeat timer duration used while waiting for an incoming request.
 #define HEARTBEAT_MSEC 1000
 // Total number of heartbeats we wait before giving up and shutting down.
@@ -259,23 +258,24 @@ public:
   }
 
   // IExecuteCommandApplicationHostEnvironment
   IFACEMETHODIMP GetValue(AHE_TYPE *aLaunchType)
   {
     Log(L"IExecuteCommandApplicationHostEnvironment::GetValue()");
     *aLaunchType = GetLaunchType();
     mIsDesktopRequest = (*aLaunchType == AHE_DESKTOP);
-    SetLastAHE(*aLaunchType);
     return S_OK;
   }
 
   /**
    * Choose the appropriate launch type based on the user's previously chosen
    * host environment, along with system constraints.
+   * AHE_DESKTOP	= 0
+   * AHE_IMMERSIVE	= 1
    */
   AHE_TYPE GetLaunchType() {
     AHE_TYPE ahe = GetLastAHE();
     Log(L"Previous AHE: %d", ahe);
 
     if (!mIsRestartMetroRequest && IsProcessRunning(kFirefoxExe, false)) {
       Log(L"Returning AHE_DESKTOP because desktop is already running");
       return AHE_DESKTOP;
--- a/browser/metro/shell/testing/metrotestharness.cpp
+++ b/browser/metro/shell/testing/metrotestharness.cpp
@@ -194,16 +194,17 @@ static bool SetupTestOutputPipe()
 static void ReadPipe()
 {
   DWORD numBytesRead;
   while (ReadFile(gTestOutputPipe, buffer, PIPE_BUFFER_SIZE,
                   &numBytesRead, nullptr) &&
          numBytesRead) {
     buffer[numBytesRead] = '\0';
     printf("%s", buffer);
+    fflush(stdout);
   }
 }
 
 static int Launch()
 {
   Log(L"Launching browser...");
 
   DWORD processID;
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -1167,17 +1167,17 @@ nsScriptSecurityManager::CheckLoadURIWit
                              nsIProtocolHandler::URI_LOADABLE_BY_ANYONE,
                              &hasFlags);
     NS_ENSURE_SUCCESS(rv, rv);
     if (!hasFlags) {
         nsXPIDLString message;
         NS_ConvertASCIItoUTF16 ucsTargetScheme(targetScheme);
         const PRUnichar* formatStrings[] = { ucsTargetScheme.get() };
         rv = sStrBundle->
-            FormatStringFromName(NS_LITERAL_STRING("ProtocolFlagError").get(),
+            FormatStringFromName(MOZ_UTF16("ProtocolFlagError"),
                                  formatStrings,
                                  ArrayLength(formatStrings),
                                  getter_Copies(message));
         if (NS_SUCCEEDED(rv)) {
             nsCOMPtr<nsIConsoleService> console(
               do_GetService("@mozilla.org/consoleservice;1"));
             NS_ENSURE_TRUE(console, NS_ERROR_FAILURE);
 
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -26,16 +26,17 @@
 #ifdef XP_WIN
 #ifdef GetClassInfo
 #undef GetClassInfo
 #endif
 #endif
 
 class nsAttrAndChildArray;
 class nsChildContentList;
+class nsCSSSelectorList;
 class nsDOMAttributeMap;
 class nsIContent;
 class nsIDocument;
 class nsIDOMElement;
 class nsIDOMNodeList;
 class nsIDOMUserDataHandler;
 class nsIEditor;
 class nsIFrame;
@@ -1693,16 +1694,27 @@ protected:
    * @param aKid The child to insert.
    * @param aIndex The index to insert at.
    * @param aNotify Whether to notify.
    * @param aChildArray The child array to work with
    */
   nsresult doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
                            bool aNotify, nsAttrAndChildArray& aChildArray);
 
+  /**
+   * Parse the given selector string into an nsCSSSelectorList.
+   *
+   * A null return value with a non-failing aRv means the string only
+   * contained pseudo-element selectors.
+   *
+   * A failing aRv means the string was not a valid selector.
+   */
+  nsCSSSelectorList* ParseSelectorList(const nsAString& aSelectorString,
+                                       mozilla::ErrorResult& aRv);
+
 public:
   /* Event stuff that documents and elements share.  This needs to be
      NS_IMETHOD because some subclasses implement DOM methods with
      this exact name and signature and then the calling convention
      needs to match.
 
      Note that we include DOCUMENT_ONLY_EVENT events here so that we
      can forward all the document stuff to this implementation.
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -2402,68 +2402,24 @@ Element::PostHandleEventForLinks(nsEvent
 }
 
 void
 Element::GetLinkTarget(nsAString& aTarget)
 {
   aTarget.Truncate();
 }
 
-// NOTE: The aPresContext pointer is NOT addrefed.
-// *aSelectorList might be null even if NS_OK is returned; this
-// happens when all the selectors were pseudo-element selectors.
-static nsresult
-ParseSelectorList(nsINode* aNode,
-                  const nsAString& aSelectorString,
-                  nsCSSSelectorList** aSelectorList)
-{
-  NS_ENSURE_ARG(aNode);
-
-  nsIDocument* doc = aNode->OwnerDoc();
-  nsCSSParser parser(doc->CSSLoader());
-
-  nsCSSSelectorList* selectorList;
-  nsresult rv = parser.ParseSelectorString(aSelectorString,
-                                           doc->GetDocumentURI(),
-                                           0, // XXXbz get the line number!
-                                           &selectorList);
-  if (NS_FAILED(rv)) {
-    // We hit this for syntax errors, which are quite common, so don't
-    // use NS_ENSURE_SUCCESS.  (For example, jQuery has an extended set
-    // of selectors, but it sees if we can parse them first.)
-    return rv;
-  }
-
-  // Filter out pseudo-element selectors from selectorList
-  nsCSSSelectorList** slot = &selectorList;
-  do {
-    nsCSSSelectorList* cur = *slot;
-    if (cur->mSelectors->IsPseudoElement()) {
-      *slot = cur->mNext;
-      cur->mNext = nullptr;
-      delete cur;
-    } else {
-      slot = &cur->mNext;
-    }
-  } while (*slot);
-  *aSelectorList = selectorList;
-
-  return NS_OK;
-}
-
-
 bool
 Element::MozMatchesSelector(const nsAString& aSelector,
                             ErrorResult& aError)
 {
-  nsAutoPtr<nsCSSSelectorList> selectorList;
-
-  aError = ParseSelectorList(this, aSelector, getter_Transfers(selectorList));
-
-  if (aError.Failed()) {
+  nsCSSSelectorList* selectorList = ParseSelectorList(aSelector, aError);
+  if (!selectorList) {
+    // Either we failed (and aError already has the exception), or this
+    // is a pseudo-element-only selector that matches nothing.
     return false;
   }
 
   OwnerDoc()->FlushPendingLinkUpdates();
   TreeMatchContext matchingContext(false,
                                    nsRuleWalker::eRelevantLinkUnvisited,
                                    OwnerDoc(),
                                    TreeMatchContext::eNeverMatchVisited);
--- a/content/base/src/EventSource.cpp
+++ b/content/base/src/EventSource.cpp
@@ -982,21 +982,21 @@ EventSource::ConsoleError()
   nsresult rv = mSrc->GetSpec(targetSpec);
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ConvertUTF8toUTF16 specUTF16(targetSpec);
   const PRUnichar *formatStrings[] = { specUTF16.get() };
 
   if (mReadyState == CONNECTING && !mInterrupted) {
     rv = PrintErrorOnConsole("chrome://global/locale/appstrings.properties",
-                             NS_LITERAL_STRING("connectionFailure").get(),
+                             MOZ_UTF16("connectionFailure"),
                              formatStrings, ArrayLength(formatStrings));
   } else {
     rv = PrintErrorOnConsole("chrome://global/locale/appstrings.properties",
-                             NS_LITERAL_STRING("netInterrupt").get(),
+                             MOZ_UTF16("netInterrupt"),
                              formatStrings, ArrayLength(formatStrings));
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
--- a/content/base/src/WebSocket.cpp
+++ b/content/base/src/WebSocket.cpp
@@ -171,21 +171,21 @@ WebSocket::ConsoleError()
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to get targetSpec");
   } else {
     NS_ConvertUTF8toUTF16 specUTF16(targetSpec);
     const PRUnichar* formatStrings[] = { specUTF16.get() };
 
     if (mReadyState < WebSocket::OPEN) {
       PrintErrorOnConsole("chrome://global/locale/appstrings.properties",
-                          NS_LITERAL_STRING("connectionFailure").get(),
+                          MOZ_UTF16("connectionFailure"),
                           formatStrings, ArrayLength(formatStrings));
     } else {
       PrintErrorOnConsole("chrome://global/locale/appstrings.properties",
-                          NS_LITERAL_STRING("netInterrupt").get(),
+                          MOZ_UTF16("netInterrupt"),
                           formatStrings, ArrayLength(formatStrings));
     }
   }
   /// todo some specific errors - like for message too large
   return rv;
 }
 
 
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -526,22 +526,22 @@ nsContentUtils::InitializeModifierString
   nsXPIDLString shiftModifier;
   nsXPIDLString metaModifier;
   nsXPIDLString osModifier;
   nsXPIDLString altModifier;
   nsXPIDLString controlModifier;
   nsXPIDLString modifierSeparator;
   if (bundle) {
     //macs use symbols for each modifier key, so fetch each from the bundle, which also covers i18n
-    bundle->GetStringFromName(NS_LITERAL_STRING("VK_SHIFT").get(), getter_Copies(shiftModifier));
-    bundle->GetStringFromName(NS_LITERAL_STRING("VK_META").get(), getter_Copies(metaModifier));
-    bundle->GetStringFromName(NS_LITERAL_STRING("VK_WIN").get(), getter_Copies(osModifier));
-    bundle->GetStringFromName(NS_LITERAL_STRING("VK_ALT").get(), getter_Copies(altModifier));
-    bundle->GetStringFromName(NS_LITERAL_STRING("VK_CONTROL").get(), getter_Copies(controlModifier));
-    bundle->GetStringFromName(NS_LITERAL_STRING("MODIFIER_SEPARATOR").get(), getter_Copies(modifierSeparator));
+    bundle->GetStringFromName(MOZ_UTF16("VK_SHIFT"), getter_Copies(shiftModifier));
+    bundle->GetStringFromName(MOZ_UTF16("VK_META"), getter_Copies(metaModifier));
+    bundle->GetStringFromName(MOZ_UTF16("VK_WIN"), getter_Copies(osModifier));
+    bundle->GetStringFromName(MOZ_UTF16("VK_ALT"), getter_Copies(altModifier));
+    bundle->GetStringFromName(MOZ_UTF16("VK_CONTROL"), getter_Copies(controlModifier));
+    bundle->GetStringFromName(MOZ_UTF16("MODIFIER_SEPARATOR"), getter_Copies(modifierSeparator));
   }
   //if any of these don't exist, we get  an empty string
   sShiftText = new nsString(shiftModifier);
   sMetaText = new nsString(metaModifier);
   sOSText = new nsString(osModifier);
   sAltText = new nsString(altModifier);
   sControlText = new nsString(controlModifier);
   sModifierSeparator = new nsString(modifierSeparator);  
@@ -6001,22 +6001,22 @@ void nsContentUtils::RemoveNewlines(nsSt
   aString.StripChars(badChars);
 }
 
 void
 nsContentUtils::PlatformToDOMLineBreaks(nsString &aString)
 {
   if (aString.FindChar(PRUnichar('\r')) != -1) {
     // Windows linebreaks: Map CRLF to LF:
-    aString.ReplaceSubstring(NS_LITERAL_STRING("\r\n").get(),
-                             NS_LITERAL_STRING("\n").get());
+    aString.ReplaceSubstring(MOZ_UTF16("\r\n"),
+                             MOZ_UTF16("\n"));
 
     // Mac linebreaks: Map any remaining CR to LF:
-    aString.ReplaceSubstring(NS_LITERAL_STRING("\r").get(),
-                             NS_LITERAL_STRING("\n").get());
+    aString.ReplaceSubstring(MOZ_UTF16("\r"),
+                             MOZ_UTF16("\n"));
   }
 }
 
 void
 nsContentUtils::PopulateStringFromStringBuffer(nsStringBuffer* aBuf,
                                                nsAString& aResultString)
 {
   MOZ_ASSERT(aBuf, "Expecting a non-null string buffer");
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -2296,55 +2296,72 @@ nsINode::Length() const
     MOZ_ASSERT(IsNodeOfType(eCONTENT));
     return static_cast<const nsIContent*>(this)->TextLength();
 
   default:
     return GetChildCount();
   }
 }
 
-// NOTE: The aPresContext pointer is NOT addrefed.
-// *aSelectorList might be null even if NS_OK is returned; this
-// happens when all the selectors were pseudo-element selectors.
-static nsresult
-ParseSelectorList(nsINode* aNode,
-                  const nsAString& aSelectorString,
-                  nsCSSSelectorList** aSelectorList)
+nsCSSSelectorList*
+nsINode::ParseSelectorList(const nsAString& aSelectorString,
+                           ErrorResult& aRv)
 {
-  MOZ_ASSERT(aNode);
-  nsIDocument* doc = aNode->OwnerDoc();
+  nsIDocument* doc = OwnerDoc();
+  nsIDocument::SelectorCache& cache = doc->GetSelectorCache();
+  nsCSSSelectorList* selectorList = nullptr;
+  bool haveCachedList = cache.GetList(aSelectorString, &selectorList);
+  if (haveCachedList) {
+    if (!selectorList) {
+      // Invalid selector.
+      aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+    }
+    return selectorList;
+  }
+
   nsCSSParser parser(doc->CSSLoader());
 
-  nsCSSSelectorList* selectorList;
-  nsresult rv = parser.ParseSelectorString(aSelectorString,
-                                           doc->GetDocumentURI(),
-                                           0, // XXXbz get the line number!
-                                           &selectorList);
-  if (NS_FAILED(rv)) {
+  aRv = parser.ParseSelectorString(aSelectorString,
+                                   doc->GetDocumentURI(),
+                                   0, // XXXbz get the line number!
+                                   &selectorList);
+  if (aRv.Failed()) {
     // We hit this for syntax errors, which are quite common, so don't
     // use NS_ENSURE_SUCCESS.  (For example, jQuery has an extended set
     // of selectors, but it sees if we can parse them first.)
-    return rv;
+    MOZ_ASSERT(aRv.ErrorCode() == NS_ERROR_DOM_SYNTAX_ERR,
+               "Unexpected error, so cached version won't return it");
+    cache.CacheList(aSelectorString, nullptr);
+    return nullptr;
   }
 
   // Filter out pseudo-element selectors from selectorList
   nsCSSSelectorList** slot = &selectorList;
   do {
     nsCSSSelectorList* cur = *slot;
     if (cur->mSelectors->IsPseudoElement()) {
       *slot = cur->mNext;
       cur->mNext = nullptr;
       delete cur;
     } else {
       slot = &cur->mNext;
     }
   } while (*slot);
-  *aSelectorList = selectorList;
 
-  return NS_OK;
+  if (selectorList) {
+    NS_ASSERTION(selectorList->mSelectors,
+                 "How can we not have any selectors?");
+    cache.CacheList(aSelectorString, selectorList);
+  } else {
+    // This is the "only pseudo-element selectors" case, which is
+    // not common, so just don't worry about caching it.  That way a
+    // null cached value can always indicate an invalid selector.
+  }
+
+  return selectorList;
 }
 
 static void
 AddScopeElements(TreeMatchContext& aMatchContext,
                  nsINode* aMatchContextNode)
 {
   if (aMatchContextNode->IsElement()) {
     aMatchContext.SetHasSpecifiedScope();
@@ -2404,103 +2421,71 @@ FindMatchingElementsWithId(const nsAStri
     }
   }
 }
 
 // Actually find elements matching aSelectorList (which must not be
 // null) and which are descendants of aRoot and put them in aList.  If
 // onlyFirstMatch, then stop once the first one is found.
 template<bool onlyFirstMatch, class Collector, class T>
-MOZ_ALWAYS_INLINE static nsresult
-FindMatchingElements(nsINode* aRoot, const nsAString& aSelector, T &aList)
+MOZ_ALWAYS_INLINE static void
+FindMatchingElements(nsINode* aRoot, nsCSSSelectorList* aSelectorList, T &aList,
+                     ErrorResult& aRv)
 {
   nsIDocument* doc = aRoot->OwnerDoc();
-  nsIDocument::SelectorCache& cache = doc->GetSelectorCache();
-  nsCSSSelectorList* selectorList = nullptr;
-  bool haveCachedList = cache.GetList(aSelector, &selectorList);
-
-  if (!haveCachedList) {
-    nsresult rv = ParseSelectorList(aRoot, aSelector, &selectorList);
-    if (NS_FAILED(rv)) {
-      MOZ_ASSERT(!selectorList);
-      MOZ_ASSERT(rv == NS_ERROR_DOM_SYNTAX_ERR,
-                 "Unexpected error, so cached version won't return it");
-      // We hit this for syntax errors, which are quite common, so don't
-      // use NS_ENSURE_SUCCESS.  (For example, jQuery has an extended set
-      // of selectors, but it sees if we can parse them first.)
-    } else if (!selectorList) {
-      // This is the "only pseudo-element selectors" case, which is
-      // not common, so just don't worry about caching it.  That way a
-      // null cached value can always indicate an invalid selector.
-      // Also don't try to do any matching, of course.
-      return NS_OK;
-    }
-
-    cache.CacheList(aSelector, selectorList);
-  }
-
-  if (!selectorList) {
-    // Invalid selector, since we've already handled the pseudo-element case.
-    return NS_ERROR_DOM_SYNTAX_ERR;
-  }
-
-  NS_ASSERTION(selectorList->mSelectors,
-               "How can we not have any selectors?");
 
   TreeMatchContext matchingContext(false, nsRuleWalker::eRelevantLinkUnvisited,
                                    doc, TreeMatchContext::eNeverMatchVisited);
   doc->FlushPendingLinkUpdates();
   AddScopeElements(matchingContext, aRoot);
 
   // Fast-path selectors involving IDs.  We can only do this if aRoot
   // is in the document and the document is not in quirks mode, since
   // ID selectors are case-insensitive in quirks mode.  Also, only do
-  // this if selectorList only has one selector, because otherwise
+  // this if aSelectorList only has one selector, because otherwise
   // ordering the elements correctly is a pain.
   NS_ASSERTION(aRoot->IsElement() || aRoot->IsNodeOfType(nsINode::eDOCUMENT) ||
                !aRoot->IsInDoc(),
                "The optimization below to check ContentIsDescendantOf only for "
                "elements depends on aRoot being either an element or a "
                "document if it's in the document.");
   if (aRoot->IsInDoc() &&
       doc->GetCompatibilityMode() != eCompatibility_NavQuirks &&
-      !selectorList->mNext &&
-      selectorList->mSelectors->mIDList) {
-    nsIAtom* id = selectorList->mSelectors->mIDList->mAtom;
-    SelectorMatchInfo info = { selectorList, matchingContext };
+      !aSelectorList->mNext &&
+      aSelectorList->mSelectors->mIDList) {
+    nsIAtom* id = aSelectorList->mSelectors->mIDList->mAtom;
+    SelectorMatchInfo info = { aSelectorList, matchingContext };
     FindMatchingElementsWithId<onlyFirstMatch, T>(nsDependentAtomString(id),
                                                   aRoot, &info, aList);
-    return NS_OK;
+    return;
   }
 
   Collector results;
   for (nsIContent* cur = aRoot->GetFirstChild();
        cur;
        cur = cur->GetNextNode(aRoot)) {
     if (cur->IsElement() &&
         nsCSSRuleProcessor::SelectorListMatches(cur->AsElement(),
                                                 matchingContext,
-                                                selectorList)) {
+                                                aSelectorList)) {
       if (onlyFirstMatch) {
         aList.AppendElement(cur->AsElement());
-        return NS_OK;
+        return;
       }
       results.AppendElement(cur->AsElement());
     }
   }
 
   const uint32_t len = results.Length();
   if (len) {
     aList.SetCapacity(len);
     for (uint32_t i = 0; i < len; ++i) {
       aList.AppendElement(results.ElementAt(i));
     }
   }
-
-  return NS_OK;
 }
 
 struct ElementHolder {
   ElementHolder() : mElement(nullptr) {}
   void AppendElement(Element* aElement) {
     NS_ABORT_IF_FALSE(!mElement, "Should only get one element");
     mElement = aElement;
   }
@@ -2509,31 +2494,42 @@ struct ElementHolder {
   Element* ElementAt(uint32_t aIndex) { return nullptr; }
 
   Element* mElement;
 };
 
 Element*
 nsINode::QuerySelector(const nsAString& aSelector, ErrorResult& aResult)
 {
+  nsCSSSelectorList* selectorList = ParseSelectorList(aSelector, aResult);
+  if (!selectorList) {
+    // Either we failed (and aResult already has the exception), or this
+    // is a pseudo-element-only selector that matches nothing.
+    return nullptr;
+  }
   ElementHolder holder;
-  aResult = FindMatchingElements<true, ElementHolder>(this, aSelector, holder);
-
+  FindMatchingElements<true, ElementHolder>(this, selectorList, holder, aResult);
   return holder.mElement;
 }
 
 already_AddRefed<nsINodeList>
 nsINode::QuerySelectorAll(const nsAString& aSelector, ErrorResult& aResult)
 {
   nsRefPtr<nsSimpleContentList> contentList = new nsSimpleContentList(this);
 
-  aResult =
+  nsCSSSelectorList* selectorList = ParseSelectorList(aSelector, aResult);
+  if (selectorList) {
     FindMatchingElements<false, nsAutoTArray<Element*, 128>>(this,
-                                                             aSelector,
-                                                             *contentList);
+                                                             selectorList,
+                                                             *contentList,
+                                                             aResult);
+  } else {
+    // Either we failed (and aResult already has the exception), or this
+    // is a pseudo-element-only selector that matches nothing.
+  }
 
   return contentList.forget();
 }
 
 nsresult
 nsINode::QuerySelector(const nsAString& aSelector, nsIDOMElement **aReturn)
 {
   ErrorResult rv;
--- a/content/base/src/nsPlainTextSerializer.cpp
+++ b/content/base/src/nsPlainTextSerializer.cpp
@@ -565,17 +565,17 @@ nsPlainTextSerializer::DoOpenContainer(n
   else if (aTag == nsGkAtoms::td || aTag == nsGkAtoms::th) {
     // We must make sure that the content of two table cells get a
     // space between them.
 
     // To make the separation between cells most obvious and
     // importable, we use a TAB.
     if (GetLastBool(mHasWrittenCellsForRow)) {
       // Bypass |Write| so that the TAB isn't compressed away.
-      AddToLine(NS_LITERAL_STRING("\t").get(), 1);
+      AddToLine(MOZ_UTF16("\t"), 1);
       mInWhitespace = true;
     }
     else if (mHasWrittenCellsForRow.IsEmpty()) {
       // We don't always see a <tr> (nor a <table>) before the <td> if we're
       // copying part of a table
       PushBool(mHasWrittenCellsForRow, true); // will never be popped
     }
     else {
@@ -1168,17 +1168,17 @@ nsPlainTextSerializer::Output(nsString& 
   }
   mOutputString->Append(aString);
 }
 
 static bool
 IsSpaceStuffable(const PRUnichar *s)
 {
   if (s[0] == '>' || s[0] == ' ' || s[0] == kNBSP ||
-      nsCRT::strncmp(s, NS_LITERAL_STRING("From ").get(), 5) == 0)
+      nsCRT::strncmp(s, MOZ_UTF16("From "), 5) == 0)
     return true;
   else
     return false;
 }
 
 /**
  * This function adds a piece of text to the current stored line. If we are
  * wrapping text and the stored line will become too long, a suitable
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -78,17 +78,17 @@ WebGLMemoryPressureObserver::Observe(nsI
         return NS_OK;
 
     bool wantToLoseContext = true;
 
     if (!mContext->mCanLoseContextInForeground &&
         ProcessPriorityManager::CurrentProcessIsForeground())
         wantToLoseContext = false;
     else if (!nsCRT::strcmp(aSomeData,
-                            NS_LITERAL_STRING("heap-minimize").get()))
+                            MOZ_UTF16("heap-minimize")))
         wantToLoseContext = mContext->mLoseContextOnHeapMinimize;
 
     if (wantToLoseContext)
         mContext->ForceLoseContext();
 
     return NS_OK;
 }
 
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -7021,25 +7021,25 @@ HTMLInputElement::SetFilePickerFiltersFr
 
     int32_t filterMask = 0;
     nsString filterName;
     nsString extensionListStr;
 
     // First, check for image/audio/video filters...
     if (token.EqualsLiteral("image/*")) {
       filterMask = nsIFilePicker::filterImages;
-      filterBundle->GetStringFromName(NS_LITERAL_STRING("imageFilter").get(),
+      filterBundle->GetStringFromName(MOZ_UTF16("imageFilter"),
                                       getter_Copies(extensionListStr));
     } else if (token.EqualsLiteral("audio/*")) {
       filterMask = nsIFilePicker::filterAudio;
-      filterBundle->GetStringFromName(NS_LITERAL_STRING("audioFilter").get(),
+      filterBundle->GetStringFromName(MOZ_UTF16("audioFilter"),
                                       getter_Copies(extensionListStr));
     } else if (token.EqualsLiteral("video/*")) {
       filterMask = nsIFilePicker::filterVideo;
-      filterBundle->GetStringFromName(NS_LITERAL_STRING("videoFilter").get(),
+      filterBundle->GetStringFromName(MOZ_UTF16("videoFilter"),
                                       getter_Copies(extensionListStr));
     } else {
       //... if no image/audio/video filter is found, check mime types filters
       nsCOMPtr<nsIMIMEInfo> mimeInfo;
       if (NS_FAILED(mimeService->GetFromTypeAndExtension(
                       NS_ConvertUTF16toUTF8(token),
                       EmptyCString(), // No extension
                       getter_AddRefs(mimeInfo))) ||
--- a/content/html/content/src/HTMLPreElement.cpp
+++ b/content/html/content/src/HTMLPreElement.cpp
@@ -30,77 +30,63 @@ NS_IMPL_INT_ATTR(HTMLPreElement, Width, 
 
 bool
 HTMLPreElement::ParseAttribute(int32_t aNamespaceID,
                                nsIAtom* aAttribute,
                                const nsAString& aValue,
                                nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
-    if (aAttribute == nsGkAtoms::cols) {
-      return aResult.ParseIntWithBounds(aValue, 0);
-    }
     if (aAttribute == nsGkAtoms::width) {
       return aResult.ParseIntWithBounds(aValue, 0);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLPreElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                       nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
     nsCSSValue* width = aData->ValueForWidth();
     if (width->GetUnit() == eCSSUnit_Null) {
-      // width: int (html4 attribute == nav4 cols)
+      // width: int (html4 attribute)
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
-      if (!value || value->Type() != nsAttrValue::eInteger) {
-        // cols: int (nav4 attribute)
-        value = aAttributes->GetAttr(nsGkAtoms::cols);
-      }
-
       if (value && value->Type() == nsAttrValue::eInteger)
         width->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Char);
     }
   }
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Text)) {
     nsCSSValue* whiteSpace = aData->ValueForWhiteSpace();
     if (whiteSpace->GetUnit() == eCSSUnit_Null) {
       // wrap: empty
       if (aAttributes->GetAttr(nsGkAtoms::wrap))
         whiteSpace->SetIntValue(NS_STYLE_WHITESPACE_PRE_WRAP, eCSSUnit_Enumerated);
 
-      // width: int (html4 attribute == nav4 cols)
+      // width: int (html4 attribute)
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
-      if (!value || value->Type() != nsAttrValue::eInteger) {
-        // cols: int (nav4 attribute)
-        value = aAttributes->GetAttr(nsGkAtoms::cols);
-      }
-
       if (value && value->Type() == nsAttrValue::eInteger) {
         // Force wrap property on since we want to wrap at a width
         // boundary not just a newline.
         whiteSpace->SetIntValue(NS_STYLE_WHITESPACE_PRE_WRAP, eCSSUnit_Enumerated);
       }
     }
   }
 
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLPreElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::wrap },
-    { &nsGkAtoms::cols },
     { &nsGkAtoms::width },
     { nullptr },
   };
   
   static const MappedAttributeEntry* const map[] = {
     attributes,
     sCommonAttributeMap,
   };
--- a/content/html/document/src/ImageDocument.cpp
+++ b/content/html/document/src/ImageDocument.cpp
@@ -739,17 +739,17 @@ ImageDocument::UpdateTitleAndCharset()
   }
 
   nsXPIDLString status;
   if (mImageIsResized) {
     nsAutoString ratioStr;
     ratioStr.AppendInt(NSToCoordFloor(GetRatio() * 100));
 
     const PRUnichar* formatString[1] = { ratioStr.get() };
-    mStringBundle->FormatStringFromName(NS_LITERAL_STRING("ScaledImage").get(),
+    mStringBundle->FormatStringFromName(MOZ_UTF16("ScaledImage"),
                                         formatString, 1,
                                         getter_Copies(status));
   }
 
   static const char* const formatNames[4] = 
   {
     "ImageTitleWithNeitherDimensionsNorFile",
     "ImageTitleWithoutDimensions",
--- a/content/html/document/src/PluginDocument.cpp
+++ b/content/html/document/src/PluginDocument.cpp
@@ -160,17 +160,17 @@ PluginDocument::StartDocumentLoad(const 
                                   bool                aReset,
                                   nsIContentSink*     aSink)
 {
   // do not allow message panes to host full-page plugins
   // returning an error causes helper apps to take over
   nsCOMPtr<nsIDocShellTreeItem> dsti (do_QueryInterface(aContainer));
   if (dsti) {
     bool isMsgPane = false;
-    dsti->NameEquals(NS_LITERAL_STRING("messagepane").get(), &isMsgPane);
+    dsti->NameEquals(MOZ_UTF16("messagepane"), &isMsgPane);
     if (isMsgPane) {
       return NS_ERROR_FAILURE;
     }
   }
 
   nsresult rv =
     MediaDocument::StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer,
                                      aDocListener, aReset, aSink);
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -735,17 +735,17 @@ nsHTMLDocument::StartDocumentLoad(const 
     nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
     NS_ASSERTION(NS_SUCCEEDED(rv) && bundleService, "The bundle service could not be loaded");
     nsCOMPtr<nsIStringBundle> bundle;
     rv = bundleService->CreateBundle("chrome://global/locale/browser.properties",
                                      getter_AddRefs(bundle));
     NS_ASSERTION(NS_SUCCEEDED(rv) && bundle, "chrome://global/locale/browser.properties could not be loaded");
     nsXPIDLString title;
     if (bundle) {
-      bundle->GetStringFromName(NS_LITERAL_STRING("plainText.wordWrap").get(), getter_Copies(title));
+      bundle->GetStringFromName(MOZ_UTF16("plainText.wordWrap"), getter_Copies(title));
     }
     SetSelectedStyleSheetSet(title);
   }
 
   // parser the content of the URI
   mParser->Parse(uri, nullptr, (void *)this);
 
   return rv;
--- a/content/mathml/content/src/nsMathMLElement.cpp
+++ b/content/mathml/content/src/nsMathMLElement.cpp
@@ -1069,18 +1069,18 @@ nsMathMLElement::SetAttr(int32_t aNameSp
   // is important here!  The attribute is not set until SetAttr returns, and
   // we will need the updated attribute value because notifying the document
   // that content states have changed will call IntrinsicState, which will try
   // to get updated information about the visitedness from Link.
   if (aName == nsGkAtoms::href &&
       (aNameSpaceID == kNameSpaceID_None ||
        aNameSpaceID == kNameSpaceID_XLink)) {
     if (aNameSpaceID == kNameSpaceID_XLink) {
-      WarnDeprecated(NS_LITERAL_STRING("xlink:href").get(),
-                     NS_LITERAL_STRING("href").get(), OwnerDoc());
+      WarnDeprecated(MOZ_UTF16("xlink:href"),
+                     MOZ_UTF16("href"), OwnerDoc());
     }
     Link::ResetLinkState(!!aNotify, true);
   }
 
   return rv;
 }
 
 nsresult
--- a/content/media/AudioStream.cpp
+++ b/content/media/AudioStream.cpp
@@ -133,16 +133,17 @@ static cubeb_stream_type ConvertChannelT
 }
 #endif
 
 AudioStream::AudioStream()
   : mMonitor("AudioStream")
   , mInRate(0)
   , mOutRate(0)
   , mChannels(0)
+  , mOutChannels(0)
   , mWritten(0)
   , mAudioClock(MOZ_THIS_IN_INITIALIZER_LIST())
   , mLatencyRequest(HighLatency)
   , mReadPoint(0)
   , mLostFrames(0)
   , mDumpFile(nullptr)
   , mVolume(1.0)
   , mBytesPerFrame(0)
@@ -189,22 +190,22 @@ nsresult AudioStream::EnsureTimeStretche
   return EnsureTimeStretcherInitializedUnlocked();
 }
 
 nsresult AudioStream::EnsureTimeStretcherInitializedUnlocked()
 {
   mMonitor.AssertCurrentThreadOwns();
   if (!mTimeStretcher) {
     // SoundTouch does not support a number of channels > 2
-    if (mChannels > 2) {
+    if (mOutChannels > 2) {
       return NS_ERROR_FAILURE;
     }
     mTimeStretcher = new soundtouch::SoundTouch();
     mTimeStretcher->setSampleRate(mInRate);
-    mTimeStretcher->setChannels(mChannels);
+    mTimeStretcher->setChannels(mOutChannels);
     mTimeStretcher->setPitch(1.0);
   }
   return NS_OK;
 }
 
 nsresult AudioStream::SetPlaybackRate(double aPlaybackRate)
 {
   NS_ASSERTION(aPlaybackRate > 0.0,
@@ -326,17 +327,17 @@ OpenDumpFile(AudioStream* aStream)
 
 static void
 WriteDumpFile(FILE* aDumpFile, AudioStream* aStream, uint32_t aFrames,
               void* aBuffer)
 {
   if (!aDumpFile)
     return;
 
-  uint32_t samples = aStream->GetChannels()*aFrames;
+  uint32_t samples = aStream->GetOutChannels()*aFrames;
   if (AUDIO_OUTPUT_FORMAT == AUDIO_FORMAT_S16) {
     fwrite(aBuffer, 2, samples, aDumpFile);
     return;
   }
 
   NS_ASSERTION(AUDIO_OUTPUT_FORMAT == AUDIO_FORMAT_FLOAT32, "bad format");
   nsAutoTArray<uint8_t, 1024*2> buf;
   buf.SetLength(samples*2);
@@ -359,40 +360,41 @@ AudioStream::Init(int32_t aNumChannels, 
   if (!cubebContext || aNumChannels < 0 || aRate < 0) {
     return NS_ERROR_FAILURE;
   }
 
   PR_LOG(gAudioStreamLog, PR_LOG_DEBUG,
     ("%s  channels: %d, rate: %d", __FUNCTION__, aNumChannels, aRate));
   mInRate = mOutRate = aRate;
   mChannels = aNumChannels;
+  mOutChannels = (aNumChannels > 2) ? 2 : aNumChannels;
   mLatencyRequest = aLatencyRequest;
 
   mDumpFile = OpenDumpFile(this);
 
   cubeb_stream_params params;
   params.rate = aRate;
-  params.channels = aNumChannels;
+  params.channels = mOutChannels;
 #if defined(__ANDROID__)
 #if defined(MOZ_B2G)
   params.stream_type = ConvertChannelToCubebType(aAudioChannelType);
 #else
   params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
 #endif
 
   if (params.stream_type == CUBEB_STREAM_TYPE_MAX) {
     return NS_ERROR_INVALID_ARG;
   }
 #endif
   if (AUDIO_OUTPUT_FORMAT == AUDIO_FORMAT_S16) {
     params.format = CUBEB_SAMPLE_S16NE;
   } else {
     params.format = CUBEB_SAMPLE_FLOAT32NE;
   }
-  mBytesPerFrame = sizeof(AudioDataValue) * aNumChannels;
+  mBytesPerFrame = sizeof(AudioDataValue) * mOutChannels;
 
   mAudioClock.Init();
 
   // If the latency pref is set, use it. Otherwise, if this stream is intended
   // for low latency playback, try to get the lowest latency possible.
   // Otherwise, for normal streams, use 100ms.
   uint32_t latency;
   if (aLatencyRequest == LowLatency && !CubebLatencyPrefSet()) {
@@ -449,16 +451,24 @@ AudioStream::Write(const AudioDataValue*
 {
   MonitorAutoLock mon(mMonitor);
   if (!mCubebStream || mState == ERRORED) {
     return NS_ERROR_FAILURE;
   }
   NS_ASSERTION(mState == INITIALIZED || mState == STARTED,
     "Stream write in unexpected state.");
 
+  // Downmix to Stereo.
+  if (mChannels > 2 && mChannels <= 8) {
+    DownmixAudioToStereo(const_cast<AudioDataValue*> (aBuf), mChannels, aFrames);
+  }
+  else if (mChannels > 8) {
+    return NS_ERROR_FAILURE;
+  }
+
   const uint8_t* src = reinterpret_cast<const uint8_t*>(aBuf);
   uint32_t bytesToCopy = FramesToBytes(aFrames);
 
   // XXX this will need to change if we want to enable this on-the-fly!
   if (PR_LOG_TEST(GetLatencyLog(), PR_LOG_DEBUG)) {
     // Record the position and time this data was inserted
     int64_t timeMs;
     if (aTime && !aTime->IsNull()) {
@@ -796,17 +806,17 @@ AudioStream::DataCallback(void* aBuffer,
       } else {
         servicedFrames = GetUnprocessed(output, aFrames, insertTime);
       }
     } else {
       servicedFrames = GetTimeStretched(output, aFrames, insertTime);
     }
     float scaled_volume = float(GetVolumeScale() * mVolume);
 
-    ScaleAudioSamples(output, aFrames * mChannels, scaled_volume);
+    ScaleAudioSamples(output, aFrames * mOutChannels, scaled_volume);
 
     NS_ABORT_IF_FALSE(mBuffer.Length() % mBytesPerFrame == 0, "Must copy complete frames");
 
     // Notify any blocked Write() call that more space is available in mBuffer.
     mon.NotifyAll();
   } else {
     GetBufferInsertTime(insertTime);
   }
--- a/content/media/AudioStream.h
+++ b/content/media/AudioStream.h
@@ -247,16 +247,17 @@ public:
   // rate.
   int64_t GetPositionInFramesInternal();
 
   // Returns true when the audio stream is paused.
   bool IsPaused();
 
   int GetRate() { return mOutRate; }
   int GetChannels() { return mChannels; }
+  int GetOutChannels() { return mOutChannels; }
 
   // This should be called before attempting to use the time stretcher.
   nsresult EnsureTimeStretcherInitialized();
   // Set playback rate as a multiple of the intrinsic playback rate. This is to
   // be called only with aPlaybackRate > 0.0.
   nsresult SetPlaybackRate(double aPlaybackRate);
   // Switch between resampling (if false) and time stretching (if true, default).
   nsresult SetPreservesPitch(bool aPreservesPitch);
@@ -304,16 +305,17 @@ private:
   // StateCallback() notifies when mState is DRAINED.
   Monitor mMonitor;
 
   // Input rate in Hz (characteristic of the media being played)
   int mInRate;
   // Output rate in Hz (characteristic of the playback rate)
   int mOutRate;
   int mChannels;
+  int mOutChannels;
   // Number of frames written to the buffers.
   int64_t mWritten;
   AudioClock mAudioClock;
   nsAutoPtr<soundtouch::SoundTouch> mTimeStretcher;
   nsRefPtr<AsyncLatencyLogger> mLatencyLog;
 
   // copy of Latency logger's starting time for offset calculations
   TimeStamp mStartTime;
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -1273,16 +1273,18 @@ uint32_t MediaDecoderStateMachine::PlayF
   uint32_t frames = 0;
   if (!PR_GetEnv("MOZ_QUIET")) {
     DECODER_LOG(PR_LOG_DEBUG, ("%p Decoder playing %d frames of data to stream for AudioData at %lld",
                                mDecoder.get(), audio->mFrames, audio->mTime));
   }
   mAudioStream->Write(audio->mAudioData,
                       audio->mFrames);
 
+  aChannels = mAudioStream->GetOutChannels();
+
   StartAudioStreamPlaybackIfNeeded(mAudioStream);
 
   offset = audio->mOffset;
   frames = audio->mFrames;
 
   // Dispatch events to the DOM for the audio just written.
   mEventManager.QueueWrittenAudioData(audio->mAudioData.get(),
                                       audio->mFrames * aChannels,
--- a/content/media/VideoUtils.cpp
+++ b/content/media/VideoUtils.cpp
@@ -2,16 +2,17 @@
  * 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 "VideoUtils.h"
 #include "MediaResource.h"
 #include "mozilla/dom/TimeRanges.h"
 #include "nsMathUtils.h"
 #include "nsSize.h"
+#include "VorbisUtils.h"
 
 #include <stdint.h>
 
 namespace mozilla {
 
 // Converts from number of audio frames to microseconds, given the specified
 // audio rate.
 CheckedInt64 FramesToUsecs(int64_t aFrames, uint32_t aRate) {
@@ -86,16 +87,70 @@ void GetEstimatedBufferedTimeRanges(mozi
       aOutBuffered->Add(double(startUs) / USECS_PER_S,
                         double(endUs) / USECS_PER_S);
     }
     startOffset = aStream->GetNextCachedData(endOffset);
   }
   return;
 }
 
+int DownmixAudioToStereo(mozilla::AudioDataValue* buffer,
+                         int channels, uint32_t frames)
+{
+  int outChannels;
+  outChannels = 2;
+#ifdef MOZ_SAMPLE_TYPE_FLOAT32
+  // Downmix matrix. Per-row normalization 1 for rows 3,4 and 2 for rows 5-8.
+  static const float dmatrix[6][8][2]= {
+      /*3*/{{0.5858f,0},{0.4142f,0.4142f},{0,     0.5858f}},
+      /*4*/{{0.4226f,0},{0,      0.4226f},{0.366f,0.2114f},{0.2114f,0.366f}},
+      /*5*/{{0.6510f,0},{0.4600f,0.4600f},{0,     0.6510f},{0.5636f,0.3254f},{0.3254f,0.5636f}},
+      /*6*/{{0.5290f,0},{0.3741f,0.3741f},{0,     0.5290f},{0.4582f,0.2645f},{0.2645f,0.4582f},{0.3741f,0.3741f}},
+      /*7*/{{0.4553f,0},{0.3220f,0.3220f},{0,     0.4553f},{0.3943f,0.2277f},{0.2277f,0.3943f},{0.2788f,0.2788f},{0.3220f,0.3220f}},
+      /*8*/{{0.3886f,0},{0.2748f,0.2748f},{0,     0.3886f},{0.3366f,0.1943f},{0.1943f,0.3366f},{0.3366f,0.1943f},{0.1943f,0.3366f},{0.2748f,0.2748f}},
+  };
+  // Re-write the buffer with downmixed data
+  for (uint32_t i = 0; i < frames; i++) {
+    float sampL = 0.0;
+    float sampR = 0.0;
+    for (int j = 0; j < channels; j++) {
+      sampL+=buffer[i*channels+j]*dmatrix[channels-3][j][0];
+      sampR+=buffer[i*channels+j]*dmatrix[channels-3][j][1];
+    }
+    buffer[i*outChannels]=sampL;
+    buffer[i*outChannels+1]=sampR;
+  }
+#else
+  // Downmix matrix. Per-row normalization 1 for rows 3,4 and 2 for rows 5-8.
+  // Coefficients in Q14.
+  static const int16_t dmatrix[6][8][2]= {
+      /*3*/{{9598, 0},{6786,6786},{0,   9598}},
+      /*4*/{{6925, 0},{0,   6925},{5997,3462},{3462,5997}},
+      /*5*/{{10663,0},{7540,7540},{0,  10663},{9234,5331},{5331,9234}},
+      /*6*/{{8668, 0},{6129,6129},{0,   8668},{7507,4335},{4335,7507},{6129,6129}},
+      /*7*/{{7459, 0},{5275,5275},{0,   7459},{6460,3731},{3731,6460},{4568,4568},{5275,5275}},
+      /*8*/{{6368, 0},{4502,4502},{0,   6368},{5514,3184},{3184,5514},{5514,3184},{3184,5514},{4502,4502}}
+  };
+  // Re-write the buffer with downmixed data
+  for (uint32_t i = 0; i < frames; i++) {
+    int32_t sampL = 0;
+    int32_t sampR = 0;
+    for (int j = 0; j < channels; j++) {
+      sampL+=buffer[i*channels+j]*dmatrix[channels-3][j][0];
+      sampR+=buffer[i*channels+j]*dmatrix[channels-3][j][1];
+    }
+    sampL = (sampL + 8192)>>14;
+    buffer[i*outChannels] = static_cast<mozilla::AudioDataValue>(MOZ_CLIP_TO_15(sampL));
+    sampR = (sampR + 8192)>>14;
+    buffer[i*outChannels+1] = static_cast<mozilla::AudioDataValue>(MOZ_CLIP_TO_15(sampR));
+  }
+#endif
+  return outChannels;
+}
+
 bool
 IsVideoContentType(const nsCString& aContentType)
 {
   NS_NAMED_LITERAL_CSTRING(video, "video");
   if (FindInReadable(video, aContentType)) {
     return true;
   }
   return false;
--- a/content/media/VideoUtils.h
+++ b/content/media/VideoUtils.h
@@ -13,16 +13,17 @@
 
 #if !(defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)) || \
     defined(MOZ_ASAN)
 // For MEDIA_THREAD_STACK_SIZE
 #include "nsIThreadManager.h"
 #endif
 #include "nsThreadUtils.h"
 #include "prtime.h"
+#include "AudioSampleFormat.h"
 
 using mozilla::CheckedInt64;
 using mozilla::CheckedUint64;
 using mozilla::CheckedInt32;
 using mozilla::CheckedUint32;
 
 struct nsIntSize;
 
@@ -142,13 +143,20 @@ void ScaleDisplayByAspectRatio(nsIntSize
 #if (defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)) && \
     !defined(MOZ_ASAN)
 #define MEDIA_THREAD_STACK_SIZE (128 * 1024)
 #else
 // All other platforms use their system defaults.
 #define MEDIA_THREAD_STACK_SIZE nsIThreadManager::DEFAULT_STACK_SIZE
 #endif
 
+// Downmix multichannel Audio samples to Stereo.
+// Input are the buffer contains multichannel data,
+// the number of channels and the number of frames.
+int DownmixAudioToStereo(mozilla::AudioDataValue* buffer,
+                         int channels,
+                         uint32_t frames);
+
 bool IsVideoContentType(const nsCString& aContentType);
 
 } // end namespace mozilla
 
 #endif
--- a/content/media/directshow/SourceFilter.cpp
+++ b/content/media/directshow/SourceFilter.cpp
@@ -16,19 +16,19 @@ using namespace mozilla::media;
 
 namespace mozilla {
 
 // Define to trace what's on...
 //#define DEBUG_SOURCE_TRACE 1
 
 #if defined(PR_LOGGING) && defined (DEBUG_SOURCE_TRACE)
 PRLogModuleInfo* GetDirectShowLog();
-#define LOG(...) PR_LOG(GetDirectShowLog(), PR_LOG_DEBUG, (__VA_ARGS__))
+#define DIRECTSHOW_LOG(...) PR_LOG(GetDirectShowLog(), PR_LOG_DEBUG, (__VA_ARGS__))
 #else
-#define LOG(...)
+#define DIRECTSHOW_LOG(...)
 #endif
 
 static HRESULT
 DoGetInterface(IUnknown* aUnknown, void** aInterface)
 {
   if (!aInterface)
     return E_POINTER;
   *aInterface = aUnknown;
@@ -241,23 +241,23 @@ OutputPin::OutputPin(MediaResource* aRes
     mSignal(&mPinLock),
     mParentSource(aParent),
     mResource(aResource, aMP3DataStart),
     mFlushCount(0),
     mBytesConsumed(0),
     mQueriedForAsyncReader(false)
 {
   MOZ_COUNT_CTOR(OutputPin);
-  LOG("OutputPin::OutputPin()");
+  DIRECTSHOW_LOG("OutputPin::OutputPin()");
 }
 
 OutputPin::~OutputPin()
 {
   MOZ_COUNT_DTOR(OutputPin);
-  LOG("OutputPin::~OutputPin()");
+  DIRECTSHOW_LOG("OutputPin::~OutputPin()");
 }
 
 HRESULT
 OutputPin::BreakConnect()
 {
   mQueriedForAsyncReader = false;
   return BasePin::BreakConnect();
 }
@@ -291,31 +291,31 @@ HRESULT
 OutputPin::CheckMediaType(const MediaType* aMediaType)
 {
   const MediaType *myMediaType = mParentSource->GetMediaType();
 
   if (IsEqualGUID(aMediaType->majortype, myMediaType->majortype) &&
       IsEqualGUID(aMediaType->subtype, myMediaType->subtype) &&
       IsEqualGUID(aMediaType->formattype, myMediaType->formattype))
   {
-    LOG("OutputPin::CheckMediaType() Match: major=%s minor=%s TC=%d FSS=%d SS=%u",
-        GetDirectShowGuidName(aMediaType->majortype),
-        GetDirectShowGuidName(aMediaType->subtype),
-        aMediaType->TemporalCompression(),
-        aMediaType->bFixedSizeSamples,
-        aMediaType->SampleSize());
+    DIRECTSHOW_LOG("OutputPin::CheckMediaType() Match: major=%s minor=%s TC=%d FSS=%d SS=%u",
+                   GetDirectShowGuidName(aMediaType->majortype),
+                   GetDirectShowGuidName(aMediaType->subtype),
+                   aMediaType->TemporalCompression(),
+                   aMediaType->bFixedSizeSamples,
+                   aMediaType->SampleSize());
     return S_OK;
   }
 
-  LOG("OutputPin::CheckMediaType() Failed to match: major=%s minor=%s TC=%d FSS=%d SS=%u",
-      GetDirectShowGuidName(aMediaType->majortype),
-      GetDirectShowGuidName(aMediaType->subtype),
-      aMediaType->TemporalCompression(),
-      aMediaType->bFixedSizeSamples,
-      aMediaType->SampleSize());
+  DIRECTSHOW_LOG("OutputPin::CheckMediaType() Failed to match: major=%s minor=%s TC=%d FSS=%d SS=%u",
+                 GetDirectShowGuidName(aMediaType->majortype),
+                 GetDirectShowGuidName(aMediaType->subtype),
+                 aMediaType->TemporalCompression(),
+                 aMediaType->bFixedSizeSamples,
+                 aMediaType->SampleSize());
   return S_FALSE;
 }
 
 HRESULT
 OutputPin::GetMediaType(int aPosition, MediaType* aMediaType)
 {
   if (!aMediaType)
     return E_POINTER;
@@ -545,17 +545,17 @@ OutputPin::SyncRead(LONGLONG aPosition,
                     LONG aLength,
                     BYTE* aBuffer)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   NS_ENSURE_TRUE(aPosition >= 0, E_FAIL);
   NS_ENSURE_TRUE(aLength > 0, E_FAIL);
   NS_ENSURE_TRUE(aBuffer, E_POINTER);
 
-  LOG("OutputPin::SyncRead(%lld, %d)", aPosition, aLength);
+  DIRECTSHOW_LOG("OutputPin::SyncRead(%lld, %d)", aPosition, aLength);
   {
     // Ignore reads while flushing.
     CriticalSectionAutoEnter lock(*mLock);
     if (mFlushCount) {
       return S_FALSE;
     }
   }
 
@@ -595,17 +595,17 @@ OutputPin::Length(LONGLONG* aTotal, LONG
     *aTotal = INT32_MAX;
   } else {
     *aTotal = length;
   }
   if (aAvailable) {
     *aAvailable = mResource.GetCachedDataEnd();
   }
 
-  LOG("OutputPin::Length() len=%lld avail=%lld", *aTotal, *aAvailable);
+  DIRECTSHOW_LOG("OutputPin::Length() len=%lld avail=%lld", *aTotal, *aAvailable);
 
   return hr;
 }
 
 STDMETHODIMP
 OutputPin::BeginFlush()
 {
   CriticalSectionAutoEnter lock(*mLock);
@@ -634,25 +634,25 @@ OutputPin::GetAndResetBytesConsumedCount
 SourceFilter::SourceFilter(const GUID& aMajorType,
                                                const GUID& aSubType)
   : BaseFilter(L"MozillaDirectShowSource", __uuidof(SourceFilter))
 {
   MOZ_COUNT_CTOR(SourceFilter);
   mMediaType.majortype = aMajorType;
   mMediaType.subtype = aSubType;
 
-  LOG("SourceFilter Constructor(%s, %s)",
-      GetDirectShowGuidName(aMajorType),
-      GetDirectShowGuidName(aSubType));
+  DIRECTSHOW_LOG("SourceFilter Constructor(%s, %s)",
+                 GetDirectShowGuidName(aMajorType),
+                 GetDirectShowGuidName(aSubType));
 }
 
 SourceFilter::~SourceFilter()
 {
   MOZ_COUNT_DTOR(SourceFilter);
-  LOG("SourceFilter Destructor()");
+  DIRECTSHOW_LOG("SourceFilter Destructor()");
 }
 
 BasePin*
 SourceFilter::GetPin(int n)
 {
   if (n == 0) {
     NS_ASSERTION(mOutputPin != 0, "GetPin with no pin!");
     return static_cast<BasePin*>(mOutputPin);
@@ -666,17 +666,17 @@ const MediaType*
 SourceFilter::GetMediaType() const
 {
   return &mMediaType;
 }
 
 nsresult
 SourceFilter::Init(MediaResource* aResource, int64_t aMP3Offset)
 {
-  LOG("SourceFilter::Init()");
+  DIRECTSHOW_LOG("SourceFilter::Init()");
 
   mOutputPin = new OutputPin(aResource,
                              this,
                              mLock,
                              aMP3Offset);
   NS_ENSURE_TRUE(mOutputPin != nullptr, NS_ERROR_FAILURE);
 
   return NS_OK;
--- a/content/media/ogg/OggReader.cpp
+++ b/content/media/ogg/OggReader.cpp
@@ -305,30 +305,30 @@ nsresult OggReader::ReadMetadata(MediaIn
       memcpy(&mTheoraInfo, &mTheoraState->mInfo, sizeof(mTheoraInfo));
       mTheoraSerial = mTheoraState->mSerial;
     }
   }
 
   if (mVorbisState && ReadHeaders(mVorbisState)) {
     mInfo.mAudio.mHasAudio = true;
     mInfo.mAudio.mRate = mVorbisState->mInfo.rate;
-    mInfo.mAudio.mChannels = mVorbisState->mInfo.channels > 2 ? 2 : mVorbisState->mInfo.channels;
+    mInfo.mAudio.mChannels = mVorbisState->mInfo.channels;
     // Copy Vorbis info data for time computations on other threads.
     memcpy(&mVorbisInfo, &mVorbisState->mInfo, sizeof(mVorbisInfo));
     mVorbisInfo.codec_setup = nullptr;
     mVorbisSerial = mVorbisState->mSerial;
     *aTags = mVorbisState->GetTags();
   } else {
     memset(&mVorbisInfo, 0, sizeof(mVorbisInfo));
   }
 #ifdef MOZ_OPUS
   if (mOpusState && ReadHeaders(mOpusState)) {
     mInfo.mAudio.mHasAudio = true;
     mInfo.mAudio.mRate = mOpusState->mRate;
-    mInfo.mAudio.mChannels = mOpusState->mChannels > 2 ? 2 : mOpusState->mChannels;
+    mInfo.mAudio.mChannels = mOpusState->mChannels;
     mOpusSerial = mOpusState->mSerial;
     mOpusPreSkip = mOpusState->mPreSkip;
 
     *aTags = mOpusState->GetTags();
   }
 #endif
   if (mSkeletonState) {
     if (!HasAudio() && !HasVideo()) {
@@ -411,23 +411,19 @@ nsresult OggReader::DecodeVorbis(ogg_pac
     nsAutoArrayPtr<AudioDataValue> buffer(new AudioDataValue[frames * channels]);
     for (uint32_t j = 0; j < channels; ++j) {
       VorbisPCMValue* channel = pcm[j];
       for (uint32_t i = 0; i < uint32_t(frames); ++i) {
         buffer[i*channels + j] = MOZ_CONVERT_VORBIS_SAMPLE(channel[i]);
       }
     }
 
-    // More than 2 decoded channels must be downmixed to stereo.
-    if (channels > 2) {
-      if (channels > 8) {
-        // No channel mapping for more than 8 channels.
-        return NS_ERROR_FAILURE;
-      }
-      DownmixToStereo(buffer, channels, frames);
+    // No channel mapping for more than 8 channels.
+    if (channels > 8) {
+      return NS_ERROR_FAILURE;
     }
 
     int64_t duration = mVorbisState->Time((int64_t)frames);
     int64_t startTime = mVorbisState->Time(endFrame - frames);
     mAudioQueue.Push(new AudioData(mDecoder->GetResource()->Tell(),
                                    startTime,
                                    duration,
                                    frames,
@@ -530,23 +526,19 @@ nsresult OggReader::DecodeOpus(ogg_packe
     int samples = frames * channels;
     for (int i = 0; i < samples; i++) {
       int32_t val = static_cast<int32_t>((gain_Q16*buffer[i] + 32768)>>16);
       buffer[i] = static_cast<AudioDataValue>(MOZ_CLIP_TO_15(val));
     }
   }
 #endif
 
-  // More than 2 decoded channels must be downmixed to stereo.
-  if (channels > 2) {
-    // Opus doesn't provide a channel mapping for more than 8 channels,
-    // so we can't downmix more than that.
-    if (channels > 8)
-      return NS_ERROR_FAILURE;
-    DownmixToStereo(buffer, channels, frames);
+  // No channel mapping for more than 8 channels.
+  if (channels > 8) {
+    return NS_ERROR_FAILURE;
   }
 
   LOG(PR_LOG_DEBUG, ("Opus decoder pushing %d frames", frames));
   int64_t startTime = mOpusState->Time(startFrame);
   int64_t endTime = mOpusState->Time(endFrame);
   mAudioQueue.Push(new AudioData(mDecoder->GetResource()->Tell(),
                                  startTime,
                                  endTime - startTime,
@@ -555,71 +547,16 @@ nsresult OggReader::DecodeOpus(ogg_packe
                                  channels));
 
   mDecodedAudioFrames += frames;
 
   return NS_OK;
 }
 #endif /* MOZ_OPUS */
 
-void OggReader::DownmixToStereo(nsAutoArrayPtr<AudioDataValue>& buffer,
-                              uint32_t& channels, int32_t frames)
-{
-  uint32_t out_channels;
-  out_channels = 2;
-  // dBuffer stores the downmixed samples.
-  nsAutoArrayPtr<AudioDataValue> dBuffer(new AudioDataValue[frames * out_channels]);
-#ifdef MOZ_SAMPLE_TYPE_FLOAT32
-  // Downmix matrix. Per-row normalization 1 for rows 3,4 and 2 for rows 5-8.
-  static const float dmatrix[6][8][2]= {
-      /*3*/{{0.5858f,0},{0.4142f,0.4142f},{0,     0.5858f}},
-      /*4*/{{0.4226f,0},{0,      0.4226f},{0.366f,0.2114f},{0.2114f,0.366f}},
-      /*5*/{{0.6510f,0},{0.4600f,0.4600f},{0,     0.6510f},{0.5636f,0.3254f},{0.3254f,0.5636f}},
-      /*6*/{{0.5290f,0},{0.3741f,0.3741f},{0,     0.5290f},{0.4582f,0.2645f},{0.2645f,0.4582f},{0.3741f,0.3741f}},
-      /*7*/{{0.4553f,0},{0.3220f,0.3220f},{0,     0.4553f},{0.3943f,0.2277f},{0.2277f,0.3943f},{0.2788f,0.2788f},{0.3220f,0.3220f}},
-      /*8*/{{0.3886f,0},{0.2748f,0.2748f},{0,     0.3886f},{0.3366f,0.1943f},{0.1943f,0.3366f},{0.3366f,0.1943f},{0.1943f,0.3366f},{0.2748f,0.2748f}},
-  };
-  for (int32_t i = 0; i < frames; i++) {
-    float sampL = 0.0;
-    float sampR = 0.0;
-    for (uint32_t j = 0; j < channels; j++) {
-      sampL+=buffer[i*channels+j]*dmatrix[channels-3][j][0];
-      sampR+=buffer[i*channels+j]*dmatrix[channels-3][j][1];
-    }
-    dBuffer[i*out_channels]=sampL;
-    dBuffer[i*out_channels+1]=sampR;
-  }
-#else
-  // Downmix matrix. Per-row normalization 1 for rows 3,4 and 2 for rows 5-8.
-  // Coefficients in Q14.
-  static const int16_t dmatrix[6][8][2]= {
-      /*3*/{{9598, 0},{6786,6786},{0,   9598}},
-      /*4*/{{6925, 0},{0,   6925},{5997,3462},{3462,5997}},
-      /*5*/{{10663,0},{7540,7540},{0,  10663},{9234,5331},{5331,9234}},
-      /*6*/{{8668, 0},{6129,6129},{0,   8668},{7507,4335},{4335,7507},{6129,6129}},
-      /*7*/{{7459, 0},{5275,5275},{0,   7459},{6460,3731},{3731,6460},{4568,4568},{5275,5275}},
-      /*8*/{{6368, 0},{4502,4502},{0,   6368},{5514,3184},{3184,5514},{5514,3184},{3184,5514},{4502,4502}}
-  };
-  for (int32_t i = 0; i < frames; i++) {
-    int32_t sampL = 0;
-    int32_t sampR = 0;
-    for (uint32_t j = 0; j < channels; j++) {
-      sampL+=buffer[i*channels+j]*dmatrix[channels-3][j][0];
-      sampR+=buffer[i*channels+j]*dmatrix[channels-3][j][1];
-    }
-    sampL = (sampL + 8192)>>14;
-    dBuffer[i*out_channels]   = static_cast<AudioDataValue>(MOZ_CLIP_TO_15(sampL));
-    sampR = (sampR + 8192)>>14;
-    dBuffer[i*out_channels+1] = static_cast<AudioDataValue>(MOZ_CLIP_TO_15(sampR));
-  }
-#endif
-  channels = out_channels;
-  buffer = dBuffer;
-}
-
 bool OggReader::DecodeAudioData()
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
   DebugOnly<bool> haveCodecState = mVorbisState != nullptr
 #ifdef MOZ_OPUS
     || mOpusState != nullptr
 #endif /* MOZ_OPUS */
     ;
--- a/content/media/ogg/OggReader.h
+++ b/content/media/ogg/OggReader.h
@@ -73,22 +73,16 @@ public:
     return mTheoraState != 0 && mTheoraState->mActive;
   }
 
   virtual nsresult ReadMetadata(MediaInfo* aInfo,
                                 MetadataTags** aTags);
   virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
   virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime);
 
-  // Downmix multichannel Audio samples to Stereo.
-  // It is used from Vorbis and Opus decoders.
-  // Input are the buffer contains multichannel data,
-  // the number of channels and the number of frames.
-  static void DownmixToStereo(nsAutoArrayPtr<AudioDataValue>& buffer,
-                     uint32_t& channel, int32_t frames);
 private:
   // This monitor should be taken when reading or writing to mIsChained.
   ReentrantMonitor mMonitor;
 
   // Specialized Reset() method to signal if the seek is
   // to the start of the stream.
   nsresult ResetDecode(bool start);
 
@@ -224,17 +218,16 @@ private:
   // Decodes a packet of Vorbis data, and inserts its samples into the
   // audio queue.
   nsresult DecodeVorbis(ogg_packet* aPacket);
 
   // Decodes a packet of Opus data, and inserts its samples into the
   // audio queue.
   nsresult DecodeOpus(ogg_packet* aPacket);
 
-
   // Decodes a packet of Theora data, and inserts its frame into the
   // video queue. May return NS_ERROR_OUT_OF_MEMORY. Caller must have obtained
   // the reader's monitor. aTimeThreshold is the current playback position
   // in media time in microseconds. Frames with an end time before this will
   // not be enqueued.
   nsresult DecodeTheora(ogg_packet* aPacket, int64_t aTimeThreshold);
 
   // Read a page of data from the Ogg file. Returns true if a page has been
--- a/content/media/webaudio/ScriptProcessorNode.cpp
+++ b/content/media/webaudio/ScriptProcessorNode.cpp
@@ -106,25 +106,34 @@ public:
     if (mLastEventTime.IsNull()) {
       mLastEventTime = now;
     } else {
       // When the main thread is blocked, and all the event are processed in a
       // burst after the main thread unblocks, the |(now - mLastEventTime)|
       // interval will be very short. |latency - bufferDuration| will be
       // negative, effectively moving back mLatency to a smaller and smaller
       // value, until it crosses zero, at which point we stop dropping buffers
-      // and resume normal operation.
+      // and resume normal operation. This does not work if at the same time,
+      // the MSG thread was also slowed down, so if the latency on the MSG
+      // thread is normal, and we are still dropping buffers, and mLatency is
+      // still more than twice the duration of a buffer, we reset it and stop
+      // dropping buffers.
       float latency = (now - mLastEventTime).ToSeconds();
       float bufferDuration = aBufferSize / mSampleRate;
       mLatency += latency - bufferDuration;
       mLastEventTime = now;
-      if (mLatency > MAX_LATENCY_S || (mDroppingBuffers && mLatency > 0.0)) {
+      if (mLatency > MAX_LATENCY_S ||
+          (mDroppingBuffers && mLatency > 0.0 &&
+           fabs(latency - bufferDuration) < bufferDuration)) {
         mDroppingBuffers = true;
         return;
       } else {
+        if (mDroppingBuffers) {
+          mLatency = 0;
+        }
         mDroppingBuffers = false;
       }
     }
 
     MutexAutoLock lock(mOutputQueue.Lock());
     for (uint32_t offset = 0; offset < aBufferSize; offset += WEBAUDIO_BLOCK_SIZE) {
       AudioChunk& chunk = mOutputQueue.Produce();
       if (aBuffer) {
--- a/content/media/webm/WebMReader.cpp
+++ b/content/media/webm/WebMReader.cpp
@@ -704,23 +704,19 @@ bool WebMReader::DecodeAudioPacket(neste
         int samples = frames * channels;
         for (int i = 0; i < samples; i++) {
           int32_t val = static_cast<int32_t>((gain_Q16*buffer[i] + 32768)>>16);
           buffer[i] = static_cast<AudioDataValue>(MOZ_CLIP_TO_15(val));
         }
       }
 #endif
 
-      // More than 2 decoded channels must be downmixed to stereo.
-      if (channels > 2) {
-        // Opus doesn't provide a channel mapping for more than 8 channels,
-        // so we can't downmix more than that.
-        if (channels > 8)
-          return false;
-        OggReader::DownmixToStereo(buffer, channels, frames);
+      // No channel mapping for more than 8 channels.
+      if (channels > 8) {
+        return false;
       }
 
       CheckedInt64 duration = FramesToUsecs(frames, rate);
       if (!duration.isValid()) {
         NS_WARNING("Int overflow converting WebM audio duration");
         return false;
       }
       CheckedInt64 time = startTime - (mCodecDelay / NS_PER_USEC);
--- a/content/svg/content/src/SVGLength.cpp
+++ b/content/svg/content/src/SVGLength.cpp
@@ -19,17 +19,17 @@ namespace mozilla {
 static void GetUnitString(nsAString& unit, uint16_t unitType);
 static uint16_t GetUnitTypeForString(const nsAString& unitStr);
 
 void
 SVGLength::GetValueAsString(nsAString &aValue) const
 {
   PRUnichar buf[24];
   nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
-                            NS_LITERAL_STRING("%g").get(),
+                            MOZ_UTF16("%g"),
                             (double)mValue);
   aValue.Assign(buf);
 
   nsAutoString unitString;
   GetUnitString(unitString, mUnit);
   aValue.Append(unitString);
 }
 
--- a/content/svg/content/src/SVGNumberList.cpp
+++ b/content/svg/content/src/SVGNumberList.cpp
@@ -29,17 +29,17 @@ SVGNumberList::GetValueAsString(nsAStrin
 {
   aValue.Truncate();
   PRUnichar buf[24];
   uint32_t last = mNumbers.Length() - 1;
   for (uint32_t i = 0; i < mNumbers.Length(); ++i) {
     // Would like to use aValue.AppendPrintf("%f", mNumbers[i]), but it's not
     // possible to always avoid trailing zeros.
     nsTextFormatter::snprintf(buf, ArrayLength(buf),
-                              NS_LITERAL_STRING("%g").get(),
+                              MOZ_UTF16("%g"),
                               double(mNumbers[i]));
     // We ignore OOM, since it's not useful for us to return an error.
     aValue.Append(buf);
     if (i != last) {
       aValue.Append(' ');
     }
   }
 }
--- a/content/svg/content/src/SVGPathSegUtils.cpp
+++ b/content/svg/content/src/SVGPathSegUtils.cpp
@@ -31,51 +31,51 @@ SVGPathSegUtils::GetValueAsString(const 
   uint32_t type = DecodeType(aSeg[0]);
   PRUnichar typeAsChar = GetPathSegTypeAsLetter(type);
 
   // Special case arcs:
   if (IsArcType(type)) {
     bool largeArcFlag = aSeg[4] != 0.0f;
     bool sweepFlag = aSeg[5] != 0.0f;
     nsTextFormatter::ssprintf(aValue,
-                              NS_LITERAL_STRING("%c%g,%g %g %d,%d %g,%g").get(),
+                              MOZ_UTF16("%c%g,%g %g %d,%d %g,%g"),
                               typeAsChar, aSeg[1], aSeg[2], aSeg[3],
                               largeArcFlag, sweepFlag, aSeg[6], aSeg[7]);
   } else {
 
     switch (ArgCountForType(type)) {
     case 0:
       aValue = typeAsChar;
       break;
 
     case 1:
-      nsTextFormatter::ssprintf(aValue, NS_LITERAL_STRING("%c%g").get(),
+      nsTextFormatter::ssprintf(aValue, MOZ_UTF16("%c%g"),
                                 typeAsChar, aSeg[1]);
       break;
 
     case 2:
-      nsTextFormatter::ssprintf(aValue, NS_LITERAL_STRING("%c%g,%g").get(),
+      nsTextFormatter::ssprintf(aValue, MOZ_UTF16("%c%g,%g"),
                                 typeAsChar, aSeg[1], aSeg[2]);
       break;
 
     case 4:
-      nsTextFormatter::ssprintf(aValue, NS_LITERAL_STRING("%c%g,%g %g,%g").get(),
+      nsTextFormatter::ssprintf(aValue, MOZ_UTF16("%c%g,%g %g,%g"),
                                 typeAsChar, aSeg[1], aSeg[2], aSeg[3], aSeg[4]);
       break;
 
     case 6:
       nsTextFormatter::ssprintf(aValue,
-                                NS_LITERAL_STRING("%c%g,%g %g,%g %g,%g").get(),
+                                MOZ_UTF16("%c%g,%g %g,%g %g,%g"),
                                 typeAsChar, aSeg[1], aSeg[2], aSeg[3], aSeg[4],
                                 aSeg[5], aSeg[6]);
       break;
 
     default:
       NS_ABORT_IF_FALSE(false, "Unknown segment type");
-      aValue = NS_LITERAL_STRING("<unknown-segment-type>").get();
+      aValue = MOZ_UTF16("<unknown-segment-type>");
       return;
     }
   }
   
   // nsTextFormatter::ssprintf is one of the nsTextFormatter methods that
   // randomly appends '\0' to its output string, which means that the length
   // of the output string is one too long. We need to manually remove that '\0'
   // until nsTextFormatter is fixed.
--- a/content/svg/content/src/SVGPointList.cpp
+++ b/content/svg/content/src/SVGPointList.cpp
@@ -28,17 +28,17 @@ SVGPointList::GetValueAsString(nsAString
 {
   aValue.Truncate();
   PRUnichar buf[50];
   uint32_t last = mItems.Length() - 1;
   for (uint32_t i = 0; i < mItems.Length(); ++i) {
     // Would like to use aValue.AppendPrintf("%f,%f", item.mX, item.mY),
     // but it's not possible to always avoid trailing zeros.
     nsTextFormatter::snprintf(buf, ArrayLength(buf),
-                              NS_LITERAL_STRING("%g,%g").get(),
+                              MOZ_UTF16("%g,%g"),
                               double(mItems[i].mX), double(mItems[i].mY));
     // We ignore OOM, since it's not useful for us to return an error.
     aValue.Append(buf);
     if (i != last) {
       aValue.Append(' ');
     }
   }
 }
--- a/content/svg/content/src/nsSVGAngle.cpp
+++ b/content/svg/content/src/nsSVGAngle.cpp
@@ -79,17 +79,17 @@ GetUnitTypeForString(const nsAString& un
   return SVG_ANGLETYPE_UNKNOWN;
 }
 
 static void
 GetValueString(nsAString &aValueAsString, float aValue, uint16_t aUnitType)
 {
   PRUnichar buf[24];
   nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
-                            NS_LITERAL_STRING("%g").get(),
+                            MOZ_UTF16("%g"),
                             (double)aValue);
   aValueAsString.Assign(buf);
 
   nsAutoString unitString;
   GetUnitString(unitString, aUnitType);
   aValueAsString.Append(unitString);
 }
 
--- a/content/svg/content/src/nsSVGLength2.cpp
+++ b/content/svg/content/src/nsSVGLength2.cpp
@@ -107,17 +107,17 @@ GetUnitTypeForString(const nsAString& un
   return nsIDOMSVGLength::SVG_LENGTHTYPE_UNKNOWN;
 }
 
 static void
 GetValueString(nsAString &aValueAsString, float aValue, uint16_t aUnitType)
 {
   PRUnichar buf[24];
   nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
-                            NS_LITERAL_STRING("%g").get(),
+                            MOZ_UTF16("%g"),
                             (double)aValue);
   aValueAsString.Assign(buf);
 
   nsAutoString unitString;
   GetUnitString(unitString, aUnitType);
   aValueAsString.Append(unitString);
 }
 
--- a/content/svg/content/src/nsSVGTransform.cpp
+++ b/content/svg/content/src/nsSVGTransform.cpp
@@ -20,51 +20,51 @@ nsSVGTransform::GetValueAsString(nsAStri
 {
   PRUnichar buf[256];
 
   switch (mType) {
     case SVG_TRANSFORM_TRANSLATE:
       // The spec say that if Y is not provided, it is assumed to be zero.
       if (mMatrix.y0 != 0)
         nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
-            NS_LITERAL_STRING("translate(%g, %g)").get(),
+            MOZ_UTF16("translate(%g, %g)"),
             mMatrix.x0, mMatrix.y0);
       else
         nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
-            NS_LITERAL_STRING("translate(%g)").get(),
+            MOZ_UTF16("translate(%g)"),
             mMatrix.x0);
       break;
     case SVG_TRANSFORM_ROTATE:
       if (mOriginX != 0.0f || mOriginY != 0.0f)
         nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
-            NS_LITERAL_STRING("rotate(%g, %g, %g)").get(),
+            MOZ_UTF16("rotate(%g, %g, %g)"),
             mAngle, mOriginX, mOriginY);
       else
         nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
-            NS_LITERAL_STRING("rotate(%g)").get(), mAngle);
+            MOZ_UTF16("rotate(%g)"), mAngle);
       break;
     case SVG_TRANSFORM_SCALE:
       if (mMatrix.xx != mMatrix.yy)
         nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
-            NS_LITERAL_STRING("scale(%g, %g)").get(), mMatrix.xx, mMatrix.yy);
+            MOZ_UTF16("scale(%g, %g)"), mMatrix.xx, mMatrix.yy);
       else
         nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
-            NS_LITERAL_STRING("scale(%g)").get(), mMatrix.xx);
+            MOZ_UTF16("scale(%g)"), mMatrix.xx);
       break;
     case SVG_TRANSFORM_SKEWX:
       nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
-                                NS_LITERAL_STRING("skewX(%g)").get(), mAngle);
+                                MOZ_UTF16("skewX(%g)"), mAngle);
       break;
     case SVG_TRANSFORM_SKEWY:
       nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
-                                NS_LITERAL_STRING("skewY(%g)").get(), mAngle);
+                                MOZ_UTF16("skewY(%g)"), mAngle);
       break;
     case SVG_TRANSFORM_MATRIX:
       nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
-          NS_LITERAL_STRING("matrix(%g, %g, %g, %g, %g, %g)").get(),
+          MOZ_UTF16("matrix(%g, %g, %g, %g, %g, %g)"),
                             mMatrix.xx, mMatrix.yx,
                             mMatrix.xy, mMatrix.yy,
                             mMatrix.x0, mMatrix.y0);
       break;
     default:
       buf[0] = '\0';
       NS_ERROR("unknown transformation type");
       break;
--- a/content/svg/content/src/nsSVGViewBox.cpp
+++ b/content/svg/content/src/nsSVGViewBox.cpp
@@ -177,17 +177,17 @@ void
 nsSVGViewBox::GetBaseValueString(nsAString& aValue) const
 {
   if (mBaseVal.none) {
     aValue.AssignLiteral("none");
     return;
   }
   PRUnichar buf[200];
   nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
-                            NS_LITERAL_STRING("%g %g %g %g").get(),
+                            MOZ_UTF16("%g %g %g %g"),
                             (double)mBaseVal.x, (double)mBaseVal.y,
                             (double)mBaseVal.width, (double)mBaseVal.height);
   aValue.Assign(buf);
 }
 
 
 already_AddRefed<dom::SVGAnimatedRect>
 nsSVGViewBox::ToSVGAnimatedRect(nsSVGElement* aSVGElement)
--- a/content/xml/document/src/nsXMLContentSink.cpp
+++ b/content/xml/document/src/nsXMLContentSink.cpp
@@ -1384,18 +1384,18 @@ nsXMLContentSink::ReportError(const PRUn
     mXSLTProcessor->CancelLoads();
     mXSLTProcessor = nullptr;
   }
 
   // release the nodes on stack
   mContentStack.Clear();
   mNotifyLevel = 0;
 
-  rv = HandleProcessingInstruction(NS_LITERAL_STRING("xml-stylesheet").get(),
-                                   NS_LITERAL_STRING("href=\"chrome://global/locale/intl.css\" type=\"text/css\"").get());
+  rv = HandleProcessingInstruction(MOZ_UTF16("xml-stylesheet"),
+                                   MOZ_UTF16("href=\"chrome://global/locale/intl.css\" type=\"text/css\""));
   NS_ENSURE_SUCCESS(rv, rv);
 
   const PRUnichar* noAtts[] = { 0, 0 };
 
   NS_NAMED_LITERAL_STRING(errorNs,
                           "http://www.mozilla.org/newlayout/xml/parsererror.xml");
 
   nsAutoString parsererror(errorNs);
--- a/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp
+++ b/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp
@@ -1062,22 +1062,22 @@ txMozillaXSLTProcessor::reportError(nsre
 
             nsXPIDLString errorMessage;
             nsCOMPtr<nsIStringBundle> bundle;
             sbs->CreateBundle(XSLT_MSGS_URL, getter_AddRefs(bundle));
 
             if (bundle) {
                 const PRUnichar* error[] = { errorText.get() };
                 if (mStylesheet) {
-                    bundle->FormatStringFromName(NS_LITERAL_STRING("TransformError").get(),
+                    bundle->FormatStringFromName(MOZ_UTF16("TransformError"),
                                                  error, 1,
                                                  getter_Copies(errorMessage));
                 }
                 else {
-                    bundle->FormatStringFromName(NS_LITERAL_STRING("LoadingError").get(),
+                    bundle->FormatStringFromName(MOZ_UTF16("LoadingError"),
                                                  error, 1,
                                                  getter_Copies(errorMessage));
                 }
             }
             mErrorText.Assign(errorMessage);
         }
     }
 
--- a/docshell/base/nsDSURIContentListener.cpp
+++ b/docshell/base/nsDSURIContentListener.cpp
@@ -431,17 +431,17 @@ bool nsDSURIContentListener::CheckFrameO
     while (tokenizer.hasMoreTokens()) {
         const nsSubstring& tok = tokenizer.nextToken();
         if (!CheckOneFrameOptionsPolicy(httpChannel, tok)) {
             // cancel the load and display about:blank
             httpChannel->Cancel(NS_BINDING_ABORTED);
             if (mDocShell) {
                 nsCOMPtr<nsIWebNavigation> webNav(do_QueryObject(mDocShell));
                 if (webNav) {
-                    webNav->LoadURI(NS_LITERAL_STRING("about:blank").get(),
+                    webNav->LoadURI(MOZ_UTF16("about:blank"),
                                     0, nullptr, nullptr, nullptr);
                 }
             }
             return false;
         }
     }
 
     return true;
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -11698,35 +11698,35 @@ nsDocShell::ConfirmRepost(bool * aRepost
   nsCOMPtr<nsIStringBundle> brandBundle;
   rv = stringBundleService->CreateBundle(kBrandBundleURL, getter_AddRefs(brandBundle));
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ASSERTION(prompter && brandBundle && appBundle,
                "Unable to set up repost prompter.");
 
   nsXPIDLString brandName;
-  rv = brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
+  rv = brandBundle->GetStringFromName(MOZ_UTF16("brandShortName"),
                                       getter_Copies(brandName));
 
   nsXPIDLString msgString, button0Title;
   if (NS_FAILED(rv)) { // No brand, use the generic version.
-    rv = appBundle->GetStringFromName(NS_LITERAL_STRING("confirmRepostPrompt").get(),
+    rv = appBundle->GetStringFromName(MOZ_UTF16("confirmRepostPrompt"),
                                       getter_Copies(msgString));
   }
   else {
     // Brand available - if the app has an override file with formatting, the app name will
     // be included. Without an override, the prompt will look like the generic version.
     const PRUnichar *formatStrings[] = { brandName.get() };
-    rv = appBundle->FormatStringFromName(NS_LITERAL_STRING("confirmRepostPrompt").get(),
+    rv = appBundle->FormatStringFromName(MOZ_UTF16("confirmRepostPrompt"),
                                          formatStrings, ArrayLength(formatStrings),
                                          getter_Copies(msgString));
   }
   if (NS_FAILED(rv)) return rv;
 
-  rv = appBundle->GetStringFromName(NS_LITERAL_STRING("resendButton.label").get(),
+  rv = appBundle->GetStringFromName(MOZ_UTF16("resendButton.label"),
                                     getter_Copies(button0Title));
   if (NS_FAILED(rv)) return rv;
 
   int32_t buttonPressed;
   // The actual value here is irrelevant, but we can't pass an invalid
   // bool through XPConnect.
   bool checkState = false;
   rv = prompter->
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -132,27 +132,31 @@ AudioChannelService::RegisterType(AudioC
       mDeferTelChannelTimer = nullptr;
       UnregisterTypeInternal(aType, mTimerElementHidden, mTimerChildID, false);
     }
 
     if (aWithVideo) {
       mWithVideoChildIDs.AppendElement(aChildID);
     }
 
+    // No hidden content channel can be playable if there is a content channel
+    // in foreground (bug 855208), nor if there is a normal channel with video
+    // in foreground (bug 894249).
+    if (type == AUDIO_CHANNEL_INT_CONTENT ||
+        (type == AUDIO_CHANNEL_INT_NORMAL &&
+         mWithVideoChildIDs.Contains(aChildID))) {
+      mPlayableHiddenContentChildID = CONTENT_PROCESS_ID_UNKNOWN;
+    }
     // One hidden content channel can be playable only when there is no any
-    // content channel in the foreground.
-    if (type == AUDIO_CHANNEL_INT_CONTENT_HIDDEN &&
+    // content channel in the foreground, and no normal channel with video in
+    // foreground.
+    else if (type == AUDIO_CHANNEL_INT_CONTENT_HIDDEN &&
         mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].IsEmpty()) {
       mPlayableHiddenContentChildID = aChildID;
     }
-    // No hidden content channel can be playable if there is an content channel
-    // in foreground.
-    else if (type == AUDIO_CHANNEL_INT_CONTENT) {
-      mPlayableHiddenContentChildID = CONTENT_PROCESS_ID_UNKNOWN;
-    }
 
     // In order to avoid race conditions, it's safer to notify any existing
     // agent any time a new one is registered.
     SendAudioChannelChangedNotification(aChildID);
     Notify();
   }
 }
 
@@ -249,28 +253,32 @@ AudioChannelService::UpdateChannelType(A
   AudioChannelInternalType oldType = GetInternalType(aType, aElementWasHidden);
 
   if (newType != oldType) {
     mChannelCounters[newType].AppendElement(aChildID);
     MOZ_ASSERT(mChannelCounters[oldType].Contains(aChildID));
     mChannelCounters[oldType].RemoveElement(aChildID);
   }
 
-  // The last content channel which goes from foreground to background can also
-  // be playable.
-  if (oldType == AUDIO_CHANNEL_INT_CONTENT &&
+  // No hidden content channel can be playable if there is a content channel
+  // in foreground (bug 855208), nor if there is a normal channel with video
+  // in foreground (bug 894249).
+  if (newType == AUDIO_CHANNEL_INT_CONTENT ||
+      (newType == AUDIO_CHANNEL_INT_NORMAL &&
+       mWithVideoChildIDs.Contains(aChildID))) {
+    mPlayableHiddenContentChildID = CONTENT_PROCESS_ID_UNKNOWN;
+  }
+  // If there is no content channel in foreground and no normal channel with
+  // video in foreground, the last content channel which goes from foreground
+  // to background can be playable.
+  else if (oldType == AUDIO_CHANNEL_INT_CONTENT &&
       newType == AUDIO_CHANNEL_INT_CONTENT_HIDDEN &&
       mChannelCounters[AUDIO_CHANNEL_INT_CONTENT].IsEmpty()) {
     mPlayableHiddenContentChildID = aChildID;
   }
-  // No hidden content channel can be playable if there is an content channel
-  // in foreground.
-  else if (newType == AUDIO_CHANNEL_INT_CONTENT) {
-    mPlayableHiddenContentChildID = CONTENT_PROCESS_ID_UNKNOWN;
-  }
 }
 
 AudioChannelState
 AudioChannelService::GetState(AudioChannelAgent* aAgent, bool aElementHidden)
 {
   AudioChannelAgentData* data;
   if (!mAgents.Get(aAgent, &data)) {
     return AUDIO_CHANNEL_STATE_MUTED;
--- a/dom/audiochannel/tests/TestAudioChannelService.cpp
+++ b/dom/audiochannel/tests/TestAudioChannelService.cpp
@@ -42,19 +42,25 @@ public:
 
   virtual ~Agent()
   {
     if (mRegistered) {
       StopPlaying();
     }
   }
 
-  nsresult Init()
+  nsresult Init(bool video=false)
   {
-    nsresult rv = mAgent->InitWithWeakCallback(mType, this);
+    nsresult rv = NS_OK;
+    if (video) {
+      rv = mAgent->InitWithVideo(mType, this, true);
+    }
+    else {
+      rv = mAgent->InitWithWeakCallback(mType, this);
+    }
     NS_ENSURE_SUCCESS(rv, rv);
 
     return mAgent->SetVisibilityState(false);
   }
 
   nsresult StartPlaying(AudioChannelState *_ret)
   {
     if (mRegistered) {
@@ -525,16 +531,97 @@ TestPriorities()
   rv = pNotificationAgent->GetCanPlay(&playable);
   NS_ENSURE_SUCCESS(rv, rv);
   TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL,
     "Test5: A pNotification channel visible agent must be playable");
 
   return rv;
 }
 
+nsresult
+TestOneVideoNormalChannel()
+{
+  nsRefPtr<Agent> agent1 = new Agent(AUDIO_CHANNEL_NORMAL);
+  nsresult rv = agent1->Init(true);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsRefPtr<Agent> agent2 = new Agent(AUDIO_CHANNEL_CONTENT);
+  rv = agent2->Init(false);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  AudioChannelState playable;
+  rv = agent1->StartPlaying(&playable);
+  NS_ENSURE_SUCCESS(rv, rv);
+  TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED,
+    "Test6: A video normal channel invisible agent1 must be muted");
+
+  rv = agent2->StartPlaying(&playable);
+  NS_ENSURE_SUCCESS(rv, rv);
+  TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL,
+    "Test6: A content channel invisible agent2 must be playable");
+
+  // one video normal channel in foreground and one content channel in background
+  rv = agent1->SetVisibilityState(true);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = agent1->GetCanPlay(&playable);
+  NS_ENSURE_SUCCESS(rv, rv);
+  TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL,
+    "Test6: A video normal channel visible agent1 must be playable");
+
+  rv = agent2->GetCanPlay(&playable);
+  NS_ENSURE_SUCCESS(rv, rv);
+  TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED,
+    "Test6: A content channel invisible agent2 must be muted");
+
+  // both one video normal channel and one content channel in foreground
+  rv = agent2->SetVisibilityState(true);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = agent1->GetCanPlay(&playable);
+  NS_ENSURE_SUCCESS(rv, rv);
+  TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL,
+    "Test6: A video normal channel visible agent1 must be playable");
+
+  rv = agent2->GetCanPlay(&playable);
+  NS_ENSURE_SUCCESS(rv, rv);
+  TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL,
+    "Test6: A content channel visible agent2 must be playable");
+
+  // one video normal channel in background and one content channel in foreground
+  rv = agent1->SetVisibilityState(false);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = agent1->GetCanPlay(&playable);
+  NS_ENSURE_SUCCESS(rv, rv);
+  TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED,
+    "Test6: A video normal channel invisible agent1 must be muted");
+
+  rv = agent2->GetCanPlay(&playable);
+  NS_ENSURE_SUCCESS(rv, rv);
+  TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL,
+    "Test6: A content channel visible agent2 must be playable");
+
+  // both one video normal channel and one content channel in background
+  rv = agent2->SetVisibilityState(false);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = agent1->GetCanPlay(&playable);
+  NS_ENSURE_SUCCESS(rv, rv);
+  TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_MUTED,
+    "Test6: A video normal channel invisible agent1 must be muted");
+
+  rv = agent2->GetCanPlay(&playable);
+  NS_ENSURE_SUCCESS(rv, rv);
+  TEST_ENSURE_BASE(playable == AUDIO_CHANNEL_STATE_NORMAL,
+    "Test6: A content channel invisible agent2 must be playable");
+
+  return rv;
+}
+
 int main(int argc, char** argv)
 {
   ScopedXPCOM xpcom("AudioChannelService");
   if (xpcom.failed()) {
     return 1;
   }
 
   if (NS_FAILED(TestDoubleStartPlaying())) {
@@ -552,15 +639,24 @@ int main(int argc, char** argv)
   if (NS_FAILED(TestContentChannels())) {
     return 1;
   }
 
   if (NS_FAILED(TestFadedState())) {
     return 1;
   }
 
+  // Channel type with AUDIO_CHANNEL_TELEPHONY cannot be unregistered until the
+  // main thread has chances to process 1500 millisecond timer. In order to
+  // skip ambiguous return value of ChannelsActiveWithHigherPriorityThan(), new
+  // test cases are added before any test case that registers the channel type
+  // with AUDIO_CHANNEL_TELEPHONY channel.
+  if (NS_FAILED(TestOneVideoNormalChannel())) {
+    return 1;
+  }
+
   if (NS_FAILED(TestPriorities())) {
     return 1;
   }
 
   return 0;
 }
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -139,17 +139,16 @@
 // Drag and drop
 #include "nsIDOMDataTransfer.h"
 
 #include "nsIDOMFile.h"
 #include "nsDOMBlobBuilder.h" // nsDOMMultipartFile
 
 #include "nsIEventListenerService.h"
 #include "nsIMessageManager.h"
-#include "nsIDOMMediaQueryList.h"
 
 #include "nsDOMTouchEvent.h"
 
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/dom/HTMLCollectionBinding.h"
 
 #include "nsIDOMWakeLock.h"
 #include "nsIDOMMobileMessageManager.h"
@@ -497,19 +496,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframeRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframesRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(CSSPageRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(MediaQueryList, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-
 #ifdef MOZ_B2G_RIL
   NS_DEFINE_CLASSINFO_DATA(MozIccManager, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 
 #ifdef MOZ_B2G_BT
   NS_DEFINE_CLASSINFO_DATA(BluetoothDevice, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
@@ -1248,20 +1244,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(MozCSSKeyframesRule, nsIDOMMozCSSKeyframesRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframesRule)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(CSSPageRule, nsIDOMCSSPageRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSPageRule)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(MediaQueryList, nsIDOMMediaQueryList)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMMediaQueryList)
-  DOM_CLASSINFO_MAP_END
-
 #ifdef MOZ_B2G_RIL
   DOM_CLASSINFO_MAP_BEGIN(MozIccManager, nsIDOMMozIccManager)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozIccManager)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
 #endif
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -108,18 +108,16 @@ DOMCI_CLASS(ContentFrameMessageManager)
 DOMCI_CLASS(ChromeMessageBroadcaster)
 DOMCI_CLASS(ChromeMessageSender)
 
 DOMCI_CLASS(MozCSSKeyframeRule)
 DOMCI_CLASS(MozCSSKeyframesRule)
 
 DOMCI_CLASS(CSSPageRule)
 
-DOMCI_CLASS(MediaQueryList)
-
 #ifdef MOZ_B2G_RIL
 DOMCI_CLASS(MozIccManager)
 #endif
 
 #ifdef MOZ_B2G_BT
 DOMCI_CLASS(BluetoothDevice)
 #endif
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -205,16 +205,17 @@
 #include "nsSandboxFlags.h"
 #include "TimeChangeObserver.h"
 #include "mozilla/dom/AudioContext.h"
 #include "mozilla/dom/BrowserElementDictionariesBinding.h"
 #include "mozilla/dom/FunctionBinding.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "nsITabChild.h"
 #include "nsIDOMMediaQueryList.h"
+#include "mozilla/dom/MediaQueryList.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 #ifdef MOZ_WEBSPEECH
 #include "mozilla/dom/SpeechSynthesis.h"
 #endif
 
 #ifdef MOZ_JSDEBUGGER
 #include "jsdIDebuggerService.h"
@@ -5012,17 +5013,17 @@ NS_IMETHODIMP
 nsGlobalWindow::GetMozAnimationStartTime(int64_t *aTime)
 {
   ErrorResult rv;
   *aTime = GetMozAnimationStartTime(rv);
 
   return rv.ErrorCode();
 }
 
-already_AddRefed<nsIDOMMediaQueryList>
+already_AddRefed<MediaQueryList>
 nsGlobalWindow::MatchMedia(const nsAString& aMediaQueryList,
                            ErrorResult& aError)
 {
   // FIXME: This whole forward-to-outer and then get a pres
   // shell/context off the docshell dance is sort of silly; it'd make
   // more sense to forward to the inner, but it's what everyone else
   // (GetSelection, GetScrollXY, etc.) does around here.
   FORWARD_TO_OUTER_OR_THROW(MatchMedia, (aMediaQueryList, aError), aError,
@@ -8894,17 +8895,17 @@ nsGlobalWindow::Find(const nsAString& aS
   if (aString.IsEmpty() || aShowDialog) {
     // See if the find dialog is already up using nsIWindowMediator
     nsCOMPtr<nsIWindowMediator> windowMediator =
       do_GetService(NS_WINDOWMEDIATOR_CONTRACTID);
 
     nsCOMPtr<nsIDOMWindow> findDialog;
 
     if (windowMediator) {
-      windowMediator->GetMostRecentWindow(NS_LITERAL_STRING("findInPage").get(),
+      windowMediator->GetMostRecentWindow(MOZ_UTF16("findInPage"),
                                           getter_AddRefs(findDialog));
     }
 
     if (findDialog) {
       // The Find dialog is already open, bring it to the top.
       aError = findDialog->Focus();
     } else if (finder) {
       // Open a Find dialog
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -103,16 +103,17 @@ struct nsRect;
 
 class nsWindowSizes;
 
 namespace mozilla {
 namespace dom {
 class BarProp;
 class Function;
 class Gamepad;
+class MediaQueryList;
 class Navigator;
 class SpeechSynthesis;
 namespace indexedDB {
 class IDBFactory;
 } // namespace indexedDB
 } // namespace dom
 } // namespace mozilla
 
@@ -845,18 +846,18 @@ public:
             mozilla::ErrorResult& aError);
   nsIDOMStorage* GetSessionStorage(mozilla::ErrorResult& aError);
   nsIDOMStorage* GetLocalStorage(mozilla::ErrorResult& aError);
   nsISelection* GetSelection(mozilla::ErrorResult& aError);
   mozilla::dom::indexedDB::IDBFactory* GetIndexedDB(mozilla::ErrorResult& aError);
   already_AddRefed<nsICSSDeclaration>
     GetComputedStyle(mozilla::dom::Element& aElt, const nsAString& aPseudoElt,
                      mozilla::ErrorResult& aError);
-  already_AddRefed<nsIDOMMediaQueryList> MatchMedia(const nsAString& aQuery,
-                                                    mozilla::ErrorResult& aError);
+  already_AddRefed<mozilla::dom::MediaQueryList> MatchMedia(const nsAString& aQuery,
+                                                            mozilla::ErrorResult& aError);
   nsScreen* GetScreen(mozilla::ErrorResult& aError);
   void MoveTo(int32_t aXPos, int32_t aYPos, mozilla::ErrorResult& aError);
   void MoveBy(int32_t aXDif, int32_t aYDif, mozilla::ErrorResult& aError);
   void ResizeTo(int32_t aWidth, int32_t aHeight,
                 mozilla::ErrorResult& aError);
   void ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
                 mozilla::ErrorResult& aError);
   int32_t GetInnerWidth(mozilla::ErrorResult& aError);
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1858,17 +1858,16 @@ addExternalIface('mozIDOMApplication', n
 addExternalIface('CSSRuleList')
 addExternalIface('DOMStringList')
 addExternalIface('RTCDataChannel', nativeType='nsIDOMDataChannel')
 addExternalIface('File')
 addExternalIface('HitRegionOptions', nativeType='nsISupports')
 addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserver')
 addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True)
 addExternalIface('LockedFile')
-addExternalIface('MediaQueryList')
 addExternalIface('MenuBuilder', nativeType='nsIMenuBuilder', notflattened=True)
 addExternalIface('MozBoxObject', nativeType='nsIBoxObject')
 addExternalIface('MozConnection', headerFile='nsIDOMConnection.h')
 addExternalIface('MozControllers', nativeType='nsIControllers')
 addExternalIface('MozFrameLoader', nativeType='nsIFrameLoader', notflattened=True)
 addExternalIface('MozFrameRequestCallback', nativeType='nsIFrameRequestCallback',
                  notflattened=True)
 addExternalIface('MozIccInfo', headerFile='nsIDOMIccInfo.h')
--- a/dom/bindings/CallbackObject.h
+++ b/dom/bindings/CallbackObject.h
@@ -97,16 +97,25 @@ public:
   };
 
 protected:
   explicit CallbackObject(CallbackObject* aCallbackObject)
   {
     Init(aCallbackObject->mCallback, aCallbackObject->mIncumbentGlobal);
   }
 
+  bool operator==(const CallbackObject& aOther) const
+  {
+    JSObject* thisObj =
+      js::UncheckedUnwrap(CallbackPreserveColor());
+    JSObject* otherObj =
+      js::UncheckedUnwrap(aOther.CallbackPreserveColor());
+    return thisObj == otherObj;
+  }
+
 private:
   inline void Init(JSObject* aCallback, nsIGlobalObject* aIncumbentGlobal)
   {
     MOZ_ASSERT(aCallback && !mCallback);
     // Set mCallback before we hold, on the off chance that a GC could somehow
     // happen in there... (which would be pretty odd, granted).
     mCallback = aCallback;
     mozilla::HoldJSObjects(this);
@@ -299,21 +308,17 @@ public:
     }
 
     if (!HasWebIDLCallback() || !GetWebIDLCallback()) {
       // If other is non-null, then we can't be equal if we have a
       // non-WebIDL callback or a null callback.
       return false;
     }
 
-    JSObject* thisObj =
-      js::UncheckedUnwrap(GetWebIDLCallback()->CallbackPreserveColor());
-    JSObject* otherObj =
-      js::UncheckedUnwrap(aOtherCallback->CallbackPreserveColor());
-    return thisObj == otherObj;
+    return *GetWebIDLCallback() == *aOtherCallback;
   }
 
   bool operator==(XPCOMCallbackT* aOtherCallback) const
   {
     return (!aOtherCallback && !GetISupports()) ||
       (!HasWebIDLCallback() && GetXPCOMCallback() == aOtherCallback);
   }
 
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -4169,18 +4169,19 @@ class CGArgumentConverter(CGThing):
 
 def getMaybeWrapValueFuncForType(type):
     # Callbacks might actually be DOM objects; nothing prevents a page from
     # doing that.
     if type.isCallback() or type.isCallbackInterface() or type.isObject():
         if type.nullable():
             return "MaybeWrapObjectOrNullValue"
         return "MaybeWrapObjectValue"
-    # Spidermonkey interfaces are never DOM objects
-    if type.isSpiderMonkeyInterface():
+    # Spidermonkey interfaces are never DOM objects.  Neither are sequences or
+    # dictionaries, since those are always plain JS objects.
+    if type.isSpiderMonkeyInterface() or type.isDictionary() or type.isSequence():
         if type.nullable():
             return "MaybeWrapNonDOMObjectOrNullValue"
         return "MaybeWrapNonDOMObjectValue"
     if type.isAny():
         return "MaybeWrapValue"
 
     # For other types, just go ahead an fall back on MaybeWrapValue for now:
     # it's always safe to do, and shouldn't be particularly slow for any of
@@ -5113,64 +5114,81 @@ if (!${obj}) {
         returnsNewObject = memberReturnsNewObject(self.idlNode)
         if returnsNewObject:
             # We better be returning addrefed things!
             assert(isResultAlreadyAddRefed(self.extendedAttributes) or
                    # NewObject can return raw pointers to owned objects
                    (self.returnType.isGeckoInterface() and
                     self.descriptor.getDescriptor(self.returnType.unroll().inner.identifier.name).nativeOwnership == 'owned'))
 
-        if self.idlNode.isAttr() and self.idlNode.slotIndex is not None:
+        setSlot = self.idlNode.isAttr() and self.idlNode.slotIndex is not None
+        if setSlot:
             # For the case of Cached attributes, go ahead and preserve our
             # wrapper if needed.  We need to do this because otherwise the
             # wrapper could get garbage-collected and the cached value would
             # suddenly disappear, but the whole premise of cached values is that
             # they never change without explicit action on someone's part.  We
             # don't do this for StoreInSlot, since those get dealt with during
             # wrapper setup, and failure would involve us trying to clear an
             # already-preserved wrapper.
             if (self.idlNode.getExtendedAttribute("Cached") and
                 self.descriptor.wrapperCache):
-                preserveWrapper = "  PreserveWrapper(self);\n"
+                preserveWrapper = "PreserveWrapper(self);\n"
             else:
                 preserveWrapper = ""
+            if self.idlNode.getExtendedAttribute("Frozen"):
+                assert self.idlNode.type.isSequence()
+                freezeValue = CGGeneric(
+                    "if (!JS_FreezeObject(cx, &args.rval().toObject())) {\n"
+                    "  return false;\n"
+                    "}")
+                if self.idlNode.type.nullable():
+                    freezeValue = CGIfWrapper(freezeValue,
+                                              "args.rval().isObject()")
+                freezeValue = freezeValue.define() + "\n"
+            else:
+                freezeValue = ""
+
             successCode = (
-                "// Be careful here: Have to wrap the value into the\n"
-                "// compartment of reflector before storing, since we might\n"
-                "// be coming in via Xrays and the value is already in the\n"
-                "// caller compartment.\n"
-                "{ // Scope for tempVal\n"
-                "  JS::Rooted<JS::Value> tempVal(cx, args.rval());\n"
-                "  JSAutoCompartment ac(cx, reflector);\n"
-                "  if (!%s(cx, &tempVal)) {\n"
-                "    return false;\n"
-                "  }\n"
-                "  js::SetReservedSlot(reflector, %s, tempVal);\n"
+                "%s"
+                "js::SetReservedSlot(reflector, %s, args.rval());\n"
                 "%s"
-                "}\n"
-                "return true;" %
-                (getMaybeWrapValueFuncForType(self.idlNode.type),
-                 memberReservedSlot(self.idlNode), preserveWrapper))
+                "break;" %
+                (freezeValue, memberReservedSlot(self.idlNode), preserveWrapper))
         else:
             successCode = None
 
         resultTemplateValues = { 'jsvalRef': 'args.rval()',
                                  'jsvalHandle': 'args.rval()',
                                  'returnsNewObject': returnsNewObject,
                                  'successCode': successCode,
                                  }
         try:
-            return wrapForType(self.returnType, self.descriptor,
-                               resultTemplateValues)
+            wrapCode = CGGeneric(wrapForType(self.returnType, self.descriptor,
+                                             resultTemplateValues))
         except MethodNotNewObjectError, err:
             assert not returnsNewObject
             raise TypeError("%s being returned from non-NewObject method or property %s.%s" %
                             (err.typename,
                              self.descriptor.interface.identifier.name,
                              self.idlNode.identifier.name))
+        if setSlot:
+            # We need to make sure that our initial wrapping is done
+            # in the reflector compartment, but that we finally set
+            # args.rval() in the caller compartment.
+            wrapCode = CGWrapper(
+                CGIndenter(wrapCode),
+                pre=("do { // block we break out of when done wrapping\n"
+                     "  // Make sure we wrap and store in the slot in reflector's compartment\n"
+                     "  JSAutoCompartment ac(cx, reflector);\n"),
+                post=("\n} while (0);\n"
+                      "// And now make sure args.rval() is in the caller compartment\n"
+                      "return %s(cx, args.rval());" %
+                      getMaybeWrapValueFuncForType(self.idlNode.type)))
+        return wrapCode.define()
 
     def getErrorReport(self):
         jsImplemented = ""
         if self.descriptor.interface.isJSImplemented():
             jsImplemented = ", true"
         return CGGeneric('return ThrowMethodFailedWithDetails(cx, rv, "%s", "%s"%s);'
                          % (self.descriptor.interface.identifier.name,
                             self.idlNode.identifier.name,
@@ -5648,18 +5666,31 @@ class CGSetterCall(CGPerSignatureCall):
     A class to generate a native object setter call for a particular IDL
     setter.
     """
     def __init__(self, argType, nativeMethodName, descriptor, attr):
         CGPerSignatureCall.__init__(self, None, [FakeArgument(argType, attr)],
                                     nativeMethodName, attr.isStatic(),
                                     descriptor, attr, setter=True)
     def wrap_return_value(self):
+        attr = self.idlNode
+        if self.descriptor.wrapperCache and attr.slotIndex is not None:
+            if attr.getExtendedAttribute("StoreInSlot"):
+                args = "cx, self"
+            else:
+                args = "self"
+            clearSlot = ("ClearCached%sValue(%s);\n" %
+                         (MakeNativeName(self.idlNode.identifier.name), args))
+        else:
+            clearSlot = ""
+
         # We have no return value
-        return "\nreturn true;"
+        return ("\n"
+                "%s"
+                "return true;" % clearSlot)
 
 class CGAbstractBindingMethod(CGAbstractStaticMethod):
     """
     Common class to generate the JSNatives for all our methods, getters, and
     setters.  This will generate the function declaration and unwrap the
     |this| object.  Subclasses are expected to override the generate_code
     function to do the rest of the work.  This function should return a
     CGThing which is already properly indented.
@@ -8726,17 +8757,21 @@ class CGDescriptor(CGThing):
                 cgThings.append(CGWrapNonWrapperCacheMethod(descriptor,
                                                             properties))
 
         # If we're not wrappercached, we don't know how to clear our
         # cached values, since we can't get at the JSObject.
         if descriptor.wrapperCache:
             cgThings.extend(CGClearCachedValueMethod(descriptor, m) for
                             m in descriptor.interface.members if
-                            m.isAttr() and m.slotIndex is not None)
+                            m.isAttr() and
+                            # Constants should never need clearing!
+                            not m.getExtendedAttribute("Constant") and
+                            not m.getExtendedAttribute("SameObject") and
+                            m.slotIndex is not None)
 
         # CGCreateInterfaceObjectsMethod needs to come after our
         # CGDOMJSClass, if any.
         cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties))
 
         # CGGetProtoObjectMethod and CGGetConstructorObjectMethod need
         # to come after CGCreateInterfaceObjectsMethod.
         if descriptor.interface.hasInterfacePrototypeObject():
@@ -10686,16 +10721,22 @@ class CGCallback(CGClass):
         # with templates and most especially template arguments.  So just
         # cheat and have CallbackMember compute all those things for us.
         realMethods = []
         for method in methods:
             if not method.needThisHandling:
                 realMethods.append(method)
             else:
                 realMethods.extend(self.getMethodImpls(method))
+        realMethods.append(
+            ClassMethod("operator==", "bool",
+                        [Argument("const %s&" % name, "aOther")],
+                        inline=True, bodyInHeader=True,
+                        const=True,
+                        body=("return %s::operator==(aOther);" % baseName)))
         CGClass.__init__(self, name,
                          bases=[ClassBase(baseName)],
                          constructors=self.getConstructors(),
                          methods=realMethods+getters+setters)
 
     def getConstructors(self):
         return [ClassConstructor(
             [Argument("JS::Handle<JSObject*>", "aCallback"), Argument("nsIGlobalObject*", "aIncumbentGlobal")],
@@ -10902,23 +10943,23 @@ class CallbackMember(CGNativeMember):
             # is what we want.
             "obj": "nullptr"
             }
 
         if isJSImplementedDescriptor(self.descriptorProvider):
             isCallbackReturnValue = "JSImpl"
         else:
             isCallbackReturnValue = "Callback"
+        sourceDescription = "return value of %s" % self.getPrettyName()
         convertType = instantiateJSToNativeConversion(
             getJSToNativeConversionInfo(self.retvalType,
                                         self.descriptorProvider,
                                         exceptionCode=self.exceptionCode,
                                         isCallbackReturnValue=isCallbackReturnValue,
-                                        # XXXbz we should try to do better here
-                                        sourceDescription="return value"),
+                                        sourceDescription=sourceDescription),
             replacements)
         assignRetval = string.Template(
             self.getRetvalInfo(self.retvalType,
                                False)[2]).substitute(replacements)
         return convertType.define() + "\n" + assignRetval
 
     def getArgConversions(self):
         # Just reget the arglist from self.originalSig, because our superclasses
@@ -10955,30 +10996,36 @@ class CallbackMember(CGNativeMember):
             # let's give it a string it can mutate
             # XXXbz if we try to do a sequence of strings, this will kinda fail.
             result = "mutableStr"
             prepend = "nsString mutableStr(%s);\n" % argval
         else:
             result = argval
             prepend = ""
 
-        conversion = prepend + wrapForType(
-            arg.type, self.descriptorProvider,
-            {
-                'result' : result,
-                'successCode' : "continue;" if arg.variadic else "break;",
-                'jsvalRef' : "argv.handleAt(%s)" % jsvalIndex,
-                'jsvalHandle' : "argv.handleAt(%s)" % jsvalIndex,
-                # XXXbz we don't have anything better to use for 'obj',
-                # really...  It's OK to use CallbackPreserveColor because
-                # CallSetup already handled the unmark-gray bits for us.
-                'obj' : 'CallbackPreserveColor()',
-                'returnsNewObject': False,
-                'exceptionCode' : self.exceptionCode
-                })
+        try:
+            conversion = prepend + wrapForType(
+                arg.type, self.descriptorProvider,
+                {
+                    'result' : result,
+                    'successCode' : "continue;" if arg.variadic else "break;",
+                    'jsvalRef' : "argv.handleAt(%s)" % jsvalIndex,
+                    'jsvalHandle' : "argv.handleAt(%s)" % jsvalIndex,
+                    # XXXbz we don't have anything better to use for 'obj',
+                    # really...  It's OK to use CallbackPreserveColor because
+                    # CallSetup already handled the unmark-gray bits for us.
+                    'obj' : 'CallbackPreserveColor()',
+                    'returnsNewObject': False,
+                    'exceptionCode' : self.exceptionCode
+                    })
+        except MethodNotNewObjectError as err:
+            raise TypeError("%s being passed as an argument to %s but is not "
+                            "wrapper cached, so can't be reliably converted to "
+                            "a JS object." %
+                            (err.typename, self.getPrettyName()))
         if arg.variadic:
             conversion = string.Template(
                 "for (uint32_t idx = 0; idx < ${arg}.Length(); ++idx) {\n" +
                 CGIndenter(CGGeneric(conversion)).define() + "\n"
                 "}\n"
                 "break;").substitute({ "arg": arg.identifier.name })
         elif arg.optional and not arg.defaultValue:
             conversion = (
@@ -11078,25 +11125,29 @@ class CallbackMethod(CallbackMember):
                 "if (!JS_CallFunctionValue(cx, ${thisObj}, callable,\n"
                 "                          ${argc}, ${argv}, rval.address())) {\n"
                 "  aRv.Throw(NS_ERROR_UNEXPECTED);\n"
                 "  return${errorReturn};\n"
                 "}\n").substitute(replacements)
 
 class CallCallback(CallbackMethod):
     def __init__(self, callback, descriptorProvider):
+        self.callback = callback
         CallbackMethod.__init__(self, callback.signatures()[0], "Call",
                                 descriptorProvider, needThisHandling=True)
 
     def getThisObj(self):
         return "aThisObj"
 
     def getCallableDecl(self):
         return "JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));\n"
 
+    def getPrettyName(self):
+        return self.callback.identifier.name
+
 class CallbackOperationBase(CallbackMethod):
     """
     Common class for implementing various callback operations.
     """
     def __init__(self, signature, jsName, nativeName, descriptor, singleOperation, rethrowContentException=False):
         self.singleOperation = singleOperation
         self.methodName = jsName
         CallbackMethod.__init__(self, signature, nativeName, descriptor, singleOperation, rethrowContentException)
@@ -11131,58 +11182,70 @@ class CallbackOperationBase(CallbackMeth
             '}\n' % CGIndenter(CGGeneric(getCallableFromProp)).define())
 
 class CallbackOperation(CallbackOperationBase):
     """
     Codegen actual WebIDL operations on callback interfaces.
     """
     def __init__(self, method, signature, descriptor):
         self.ensureASCIIName(method)
+        self.method = method
         jsName = method.identifier.name
         CallbackOperationBase.__init__(self, signature,
                                        jsName, MakeNativeName(jsName),
                                        descriptor, descriptor.interface.isSingleOperationInterface(),
                                        rethrowContentException=descriptor.interface.isJSImplemented())
 
-class CallbackGetter(CallbackMember):
-    def __init__(self, attr, descriptor):
+    def getPrettyName(self):
+        return "%s.%s" % (self.descriptorProvider.interface.identifier.name,
+                          self.method.identifier.name)
+
+class CallbackAccessor(CallbackMember):
+    """
+    Shared superclass for CallbackGetter and CallbackSetter.
+    """
+    def __init__(self, attr, sig, name, descriptor):
         self.ensureASCIIName(attr)
         self.attrName = attr.identifier.name
-        CallbackMember.__init__(self,
-                                (attr.type, []),
-                                callbackGetterName(attr),
-                                descriptor,
+        CallbackMember.__init__(self, sig, name, descriptor,
                                 needThisHandling=False,
                                 rethrowContentException=descriptor.interface.isJSImplemented())
 
+    def getPrettyName(self):
+        return "%s.%s" % (self.descriptorProvider.interface.identifier.name,
+                          self.attrName)
+
+class CallbackGetter(CallbackAccessor):
+    def __init__(self, attr, descriptor):
+        CallbackAccessor.__init__(self, attr,
+                                  (attr.type, []),
+                                  callbackGetterName(attr),
+                                  descriptor)
+
     def getRvalDecl(self):
         return "JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());\n"
 
     def getCall(self):
         replacements = {
             "errorReturn" : self.getDefaultRetval(),
             "attrName": self.attrName
             }
         return string.Template(
             'if (!JS_GetProperty(cx, mCallback, "${attrName}", &rval)) {\n'
             '  aRv.Throw(NS_ERROR_UNEXPECTED);\n'
             '  return${errorReturn};\n'
             '}\n').substitute(replacements);
 
-class CallbackSetter(CallbackMember):
+class CallbackSetter(CallbackAccessor):
     def __init__(self, attr, descriptor):
-        self.ensureASCIIName(attr)
-        self.attrName = attr.identifier.name
-        CallbackMember.__init__(self,
-                                (BuiltinTypes[IDLBuiltinType.Types.void],
-                                 [FakeArgument(attr.type, attr)]),
-                                callbackSetterName(attr),
-                                descriptor,
-                                needThisHandling=False,
-                                rethrowContentException=descriptor.interface.isJSImplemented())
+        CallbackAccessor.__init__(self, attr,
+                                  (BuiltinTypes[IDLBuiltinType.Types.void],
+                                   [FakeArgument(attr.type, attr)]),
+                                  callbackSetterName(attr),
+                                  descriptor)
 
     def getRvalDecl(self):
         # We don't need an rval
         return ""
 
     def getCall(self):
         replacements = {
             "errorReturn" : self.getDefaultRetval(),
@@ -11203,16 +11266,19 @@ class CGJSImplInitOperation(CallbackOper
     """
     Codegen the __Init() method used to pass along constructor arguments for JS-implemented WebIDL.
     """
     def __init__(self, sig, descriptor):
         assert sig in descriptor.interface.ctor().signatures()
         CallbackOperationBase.__init__(self, (BuiltinTypes[IDLBuiltinType.Types.void], sig[1]),
                                        "__init", "__Init", descriptor, False, True)
 
+    def getPrettyName(self):
+        return "__init"
+
 class GlobalGenRoots():
     """
     Roots for global codegen.
 
     To generate code, call the method associated with the target, and then
     call the appropriate define/declare method.
     """
 
--- a/dom/bindings/Makefile.in
+++ b/dom/bindings/Makefile.in
@@ -55,17 +55,19 @@ CSS2Properties.webidl: $(css2properties_
 # performed.
 codegen_dependencies := \
   $(nonstatic_webidl_files) \
   $(GLOBAL_DEPS) \
   $(NULL)
 
 $(call include_deps,codegen.pp)
 
-codegen.pp: $(codegen_dependencies)
+codegen.pp: codegen.done
+
+codegen.done: $(codegen_dependencies)
 	$(call py_action,webidl,$(srcdir))
 	@$(TOUCH) $@
 
 .PHONY: compiletests
 compiletests:
 	$(call SUBMAKE,libs,test)
 
 GARBAGE += \
--- a/dom/bindings/mozwebidlcodegen/__init__.py
+++ b/dom/bindings/mozwebidlcodegen/__init__.py
@@ -541,17 +541,17 @@ def create_build_system_manager(topsrcdi
         os.path.join(src_dir, 'Bindings.conf'),
         inputs,
         os.path.join(dist_dir, 'include', 'mozilla', 'dom'),
         obj_dir,
         os.path.join(obj_dir, 'codegen.json'),
         cache_dir=cache_dir,
         # The make rules include a codegen.pp file containing dependencies.
         make_deps_path=os.path.join(obj_dir, 'codegen.pp'),
-        make_deps_target='codegen.pp',
+        make_deps_target='codegen.done',
     )
 
 
 class BuildSystemWebIDL(MozbuildObject):
     @property
     def manager(self):
         if not hasattr(self, '_webidl_manager'):
             self._webidl_manager = create_build_system_manager(
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -2790,16 +2790,20 @@ class IDLAttribute(IDLInterfaceMember):
             if self.isStatic():
                 raise WebIDLError("[%s] is only allowed on non-static "
                                   "attributes" % identifier,
                                   [attr.location, self.location])
             if self.getExtendedAttribute("LenientThis"):
                 raise WebIDLError("[LenientThis] is not allowed in combination "
                                   "with [%s]" % identifier,
                                   [attr.location, self.location])
+        elif identifier == "Frozen":
+            if not self.type.isSequence():
+                raise WebIDLError("[Frozen] is only allowed on sequence-valued "
+                                  "attributes", [attr.location, self.location])
         elif (identifier == "Pref" or
               identifier == "SetterThrows" or
               identifier == "Pure" or
               identifier == "Throws" or
               identifier == "GetterThrows" or
               identifier == "ChromeOnly" or
               identifier == "SameObject" or
               identifier == "Constant" or
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -164,16 +164,19 @@ public:
   void PassOptionalByte(const Optional<int8_t>&);
   void PassOptionalByteBeforeRequired(const Optional<int8_t>&, int8_t);
   void PassOptionalByteWithDefault(int8_t);
   void PassOptionalByteWithDefaultBeforeRequired(int8_t, int8_t);
   void PassNullableByte(const Nullable<int8_t>&);
   void PassOptionalNullableByte(const Optional< Nullable<int8_t> >&);
   void PassVariadicByte(const Sequence<int8_t>&);
   int8_t CachedByte();
+  int8_t CachedConstantByte();
+  int8_t CachedWritableByte();
+  void SetCachedWritableByte(int8_t);
 
   int16_t ReadonlyShort();
   int16_t WritableShort();
   void SetWritableShort(int16_t);
   void PassShort(int16_t);
   int16_t ReceiveShort();
   void PassOptionalShort(const Optional<int16_t>&);
   void PassOptionalShortWithDefault(int16_t);
@@ -337,16 +340,19 @@ public:
   void PassOptionalCallbackInterfaceWithDefault(TestCallbackInterface*);
 
   already_AddRefed<IndirectlyImplementedInterface> ReceiveConsequentialInterface();
   void PassConsequentialInterface(IndirectlyImplementedInterface&);
 
   // Sequence types
   void GetReadonlySequence(nsTArray<int32_t>&);
   void GetReadonlySequenceOfDictionaries(JSContext*, nsTArray<Dict>&);
+  void GetReadonlyNullableSequenceOfDictionaries(JSContext*, Nullable<nsTArray<Dict> >&);
+  void GetReadonlyFrozenSequence(JSContext*, nsTArray<Dict>&);
+  void GetReadonlyFrozenNullableSequence(JSContext*, Nullable<nsTArray<Dict>>&);
   void ReceiveSequence(nsTArray<int32_t>&);
   void ReceiveNullableSequence(Nullable< nsTArray<int32_t> >&);
   void ReceiveSequenceOfNullableInts(nsTArray< Nullable<int32_t> >&);
   void ReceiveNullableSequenceOfNullableInts(Nullable< nsTArray< Nullable<int32_t> > >&);
   void PassSequence(const Sequence<int32_t> &);
   void PassNullableSequence(const Nullable< Sequence<int32_t> >&);
   void PassSequenceOfNullableInts(const Sequence<Nullable<int32_t> >&);
   void PassOptionalSequenceOfNullableInts(const Optional<Sequence<Nullable<int32_t> > > &);
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -121,16 +121,20 @@ interface TestInterface {
   void passOptionalByteBeforeRequired(optional byte arg1, byte arg2);
   void passOptionalByteWithDefault(optional byte arg = 0);
   void passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2);
   void passNullableByte(byte? arg);
   void passOptionalNullableByte(optional byte? arg);
   void passVariadicByte(byte... arg);
   [StoreInSlot, Pure]
   readonly attribute byte cachedByte;
+  [StoreInSlot, Constant]
+  readonly attribute byte cachedConstantByte;
+  [StoreInSlot, Pure]
+  attribute byte cachedWritableByte;
 
   readonly attribute short readonlyShort;
   attribute short writableShort;
   void passShort(short arg);
   short receiveShort();
   void passOptionalShort(optional short arg);
   void passOptionalShortWithDefault(optional short arg = 5);
 
@@ -294,16 +298,22 @@ interface TestInterface {
   IndirectlyImplementedInterface receiveConsequentialInterface();
   void passConsequentialInterface(IndirectlyImplementedInterface arg);
 
   // Sequence types
   [Cached, Pure]
   readonly attribute sequence<long> readonlySequence;
   [Cached, Pure]
   readonly attribute sequence<Dict> readonlySequenceOfDictionaries;
+  [Cached, Pure]
+  readonly attribute sequence<Dict>? readonlyNullableSequenceOfDictionaries;
+  [Cached, Pure, Frozen]
+  readonly attribute sequence<Dict> readonlyFrozenSequence;
+  [Cached, Pure, Frozen]
+  readonly attribute sequence<Dict>? readonlyFrozenNullableSequence;
   sequence<long> receiveSequence();
   sequence<long>? receiveNullableSequence();
   sequence<long?> receiveSequenceOfNullableInts();
   sequence<long?>? receiveNullableSequenceOfNullableInts();
   void passSequence(sequence<long> arg);
   void passNullableSequence(sequence<long>? arg);
   void passSequenceOfNullableInts(sequence<long?> arg);
   void passOptionalSequenceOfNullableInts(optional sequence<long?> arg);
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -26,16 +26,20 @@ interface TestExampleInterface {
   void passOptionalByteBeforeRequired(optional byte arg1, byte arg2);
   void passOptionalByteWithDefault(optional byte arg = 0);
   void passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2);
   void passNullableByte(byte? arg);
   void passOptionalNullableByte(optional byte? arg);
   void passVariadicByte(byte... arg);
   [Cached, Pure]
   readonly attribute byte cachedByte;
+  [StoreInSlot, Constant]
+  readonly attribute byte cachedConstantByte;
+  [Cached, Pure]
+  attribute byte cachedWritableByte;
 
   readonly attribute short readonlyShort;
   attribute short writableShort;
   void passShort(short arg);
   short receiveShort();
   void passOptionalShort(optional short arg);
   void passOptionalShortWithDefault(optional short arg = 5);
 
@@ -190,16 +194,22 @@ interface TestExampleInterface {
   IndirectlyImplementedInterface receiveConsequentialInterface();
   void passConsequentialInterface(IndirectlyImplementedInterface arg);
 
   // Sequence types
   [Cached, Pure]
   readonly attribute sequence<long> readonlySequence;
   [Cached, Pure]
   readonly attribute sequence<Dict> readonlySequenceOfDictionaries;
+  [Cached, Pure]
+  readonly attribute sequence<Dict>? readonlyNullableSequenceOfDictionaries;
+  [Cached, Pure, Frozen]
+  readonly attribute sequence<long> readonlyFrozenSequence;
+  [Cached, Pure, Frozen]
+  readonly attribute sequence<long>? readonlyFrozenNullableSequence;
   sequence<long> receiveSequence();
   sequence<long>? receiveNullableSequence();
   sequence<long?> receiveSequenceOfNullableInts();
   sequence<long?>? receiveNullableSequenceOfNullableInts();
   void passSequence(sequence<long> arg);
   void passNullableSequence(sequence<long>? arg);
   void passSequenceOfNullableInts(sequence<long?> arg);
   void passOptionalSequenceOfNullableInts(optional sequence<long?> arg);
--- a/dom/bindings/test/TestJSImplGen.webidl
+++ b/dom/bindings/test/TestJSImplGen.webidl
@@ -38,16 +38,20 @@ interface TestJSImplInterface {
   void passOptionalByteBeforeRequired(optional byte arg1, byte arg2);
   void passOptionalByteWithDefault(optional byte arg = 0);
   void passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2);
   void passNullableByte(byte? arg);
   void passOptionalNullableByte(optional byte? arg);
   void passVariadicByte(byte... arg);
   [Cached, Pure]
   readonly attribute byte cachedByte;
+  [Cached, Constant]
+  readonly attribute byte cachedConstantByte;
+  [Cached, Pure]
+  attribute byte cachedWritableByte;
 
   readonly attribute short readonlyShort;
   attribute short writableShort;
   void passShort(short arg);
   short receiveShort();
   void passOptionalShort(optional short arg);
   void passOptionalShortWithDefault(optional short arg = 5);
 
@@ -211,16 +215,22 @@ interface TestJSImplInterface {
   IndirectlyImplementedInterface receiveConsequentialInterface();
   void passConsequentialInterface(IndirectlyImplementedInterface arg);
 
   // Sequence types
   [Cached, Pure]
   readonly attribute sequence<long> readonlySequence;
   [Cached, Pure]
   readonly attribute sequence<Dict> readonlySequenceOfDictionaries;
+  [Cached, Pure]
+  readonly attribute sequence<Dict>? readonlyNullableSequenceOfDictionaries;
+  [Cached, Pure, Frozen]
+  readonly attribute sequence<long> readonlyFrozenSequence;
+  [Cached, Pure, Frozen]
+  readonly attribute sequence<long>? readonlyFrozenNullableSequence;
   sequence<long> receiveSequence();
   sequence<long>? receiveNullableSequence();
   sequence<long?> receiveSequenceOfNullableInts();
   sequence<long?>? receiveNullableSequenceOfNullableInts();
   void passSequence(sequence<long> arg);
   void passNullableSequence(sequence<long>? arg);
   void passSequenceOfNullableInts(sequence<long?> arg);
   void passOptionalSequenceOfNullableInts(optional sequence<long?> arg);
--- a/dom/browser-element/mochitest/browserElementTestHelpers.js
+++ b/dom/browser-element/mochitest/browserElementTestHelpers.js
@@ -165,17 +165,17 @@ function expectPriorityChange(childID, e
   var observed = false;
   browserElementTestHelpers.addProcessPriorityObserver(
     'process-priority-set',
     function(subject, topic, data) {
       if (observed) {
         return;
       }
 
-      [id, priority, cpuPriority] = data.split(":");
+      var [id, priority, cpuPriority] = data.split(":");
       if (id != childID) {
         return;
       }
 
       // Make sure we run the is() calls in this observer only once, otherwise
       // we'll expect /every/ priority change to match expectedPriority.
       observed = true;
 
@@ -207,17 +207,17 @@ function expectPriorityChange(childID, e
 
 function expectPriorityWithBackgroundLRUSet(childID, expectedBackgroundLRU) {
   var deferred = Promise.defer();
 
   browserElementTestHelpers.addProcessPriorityObserver(
     'process-priority-with-background-LRU-set',
     function(subject, topic, data) {
 
-      [id, priority, cpuPriority, backgroundLRU] = data.split(":");
+      var [id, priority, cpuPriority, backgroundLRU] = data.split(":");
       if (id != childID) {
         return;
       }
 
       is(backgroundLRU, expectedBackgroundLRU,
          'Expected backgroundLRU ' + backgroundLRU + ' of childID ' + childID +
          ' to change to ' + expectedBackgroundLRU);
 
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -1153,17 +1153,17 @@ public:
 
   ~RecordingComplete() { }
 
   NS_IMETHOD Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
-    obs->NotifyObservers(mFile, "file-watcher-notify", NS_LITERAL_STRING("modified").get());
+    obs->NotifyObservers(mFile, "file-watcher-notify", MOZ_UTF16("modified"));
     return NS_OK;
   }
 
 private:
   nsRefPtr<DeviceStorageFile> mFile;
 };
 
 nsresult
--- a/dom/gamepad/Gamepad.cpp
+++ b/dom/gamepad/Gamepad.cpp
@@ -14,17 +14,17 @@ namespace dom {
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Gamepad)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Gamepad)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Gamepad)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(Gamepad, mParent, mButtonsVariant)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(Gamepad, mParent, mButtons)
 
 Gamepad::Gamepad(nsISupports* aParent,
                  const nsAString& aID, uint32_t aIndex,
                  GamepadMappingType aMapping,
                  uint32_t aNumButtons, uint32_t aNumAxes)
   : mParent(aParent),
     mID(aID),
     mIndex(aIndex),
@@ -59,103 +59,43 @@ Gamepad::SetButton(uint32_t aButton, boo
   mButtons[aButton]->SetPressed(aPressed);
   mButtons[aButton]->SetValue(aValue);
 }
 
 void
 Gamepad::SetAxis(uint32_t aAxis, double aValue)
 {
   MOZ_ASSERT(aAxis < mAxes.Length());
-  mAxes[aAxis] = aValue;
-}
-
-nsresult
-Gamepad::GetButtons(nsIVariant** aButtons)
-{
-  if (mButtonsVariant) {
-    NS_ADDREF(*aButtons = mButtonsVariant);
-    return NS_OK;
-  }
-
-  nsRefPtr<nsVariant> out = new nsVariant();
-  NS_ENSURE_STATE(out);
-
-  if (mButtons.Length() == 0) {
-    nsresult rv = out->SetAsEmptyArray();
-    NS_ENSURE_SUCCESS(rv, rv);
-  } else {
-    // Note: The resulting nsIVariant dupes both the array and its elements.
-    GamepadButton** array = reinterpret_cast<GamepadButton**>
-                      (NS_Alloc(mButtons.Length() * sizeof(GamepadButton*)));
-    NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
-
-    for (uint32_t i = 0; i < mButtons.Length(); ++i) {
-      array[i] = mButtons[i].get();
-    }
-
-    nsresult rv = out->SetAsArray(nsIDataType::VTYPE_INTERFACE,
-                                  nullptr,
-                                  mButtons.Length(),
-                                  reinterpret_cast<void*>(array));
-    NS_Free(array);
-    NS_ENSURE_SUCCESS(rv, rv);
+  if (mAxes[aAxis] != aValue) {
+    mAxes[aAxis] = aValue;
+    GamepadBinding::ClearCachedAxesValue(this);
   }
-
-  mButtonsVariant = out;
-  *aButtons = out.forget().get();
-  return NS_OK;
-}
-
-nsresult
-Gamepad::GetAxes(nsIVariant** aAxes)
-{
-  nsRefPtr<nsVariant> out = new nsVariant();
-  NS_ENSURE_STATE(out);
-
-  if (mAxes.Length() == 0) {
-    nsresult rv = out->SetAsEmptyArray();
-    NS_ENSURE_SUCCESS(rv, rv);
-  } else {
-    // Note: The resulting nsIVariant dupes both the array and its elements.
-    double* array = reinterpret_cast<double*>
-                              (NS_Alloc(mAxes.Length() * sizeof(double)));
-    NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
-
-    for (uint32_t i = 0; i < mAxes.Length(); ++i) {
-      array[i] = mAxes[i];
-    }
-
-    nsresult rv = out->SetAsArray(nsIDataType::VTYPE_DOUBLE,
-                                  nullptr,
-                                  mAxes.Length(),
-                                  reinterpret_cast<void*>(array));
-    NS_Free(array);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  *aAxes = out.forget().get();
-  return NS_OK;
 }
 
 void
 Gamepad::SyncState(Gamepad* aOther)
 {
   if (mButtons.Length() != aOther->mButtons.Length() ||
       mAxes.Length() != aOther->mAxes.Length()) {
     return;
   }
 
   mConnected = aOther->mConnected;
   for (uint32_t i = 0; i < mButtons.Length(); ++i) {
     mButtons[i]->SetPressed(aOther->mButtons[i]->Pressed());
     mButtons[i]->SetValue(aOther->mButtons[i]->Value());
   }
+  bool changed = false;
   for (uint32_t i = 0; i < mAxes.Length(); ++i) {
+    changed = changed || (mAxes[i] != aOther->mAxes[i]);
     mAxes[i] = aOther->mAxes[i];
   }
+  if (changed) {
+    GamepadBinding::ClearCachedAxesValue(this);
+  }
 }
 
 already_AddRefed<Gamepad>
 Gamepad::Clone(nsISupports* aParent)
 {
   nsRefPtr<Gamepad> out =
     new Gamepad(aParent, mID, mIndex, mMapping,
                 mButtons.Length(), mAxes.Length());
--- a/dom/gamepad/Gamepad.h
+++ b/dom/gamepad/Gamepad.h
@@ -4,17 +4,16 @@
 
 #ifndef mozilla_dom_gamepad_Gamepad_h
 #define mozilla_dom_gamepad_Gamepad_h
 
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/GamepadButton.h"
 #include <stdint.h>
 #include "nsCOMPtr.h"
-#include "nsIVariant.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsWrapperCache.h"
 
 namespace mozilla {
 namespace dom {
 
 enum GamepadMappingType
@@ -73,51 +72,41 @@ public:
     return mConnected;
   }
 
   uint32_t Index() const
   {
     return mIndex;
   }
 
-  already_AddRefed<nsIVariant> GetButtons(mozilla::ErrorResult& aRv)
+  void GetButtons(nsTArray<nsRefPtr<GamepadButton>>& aButtons) const
   {
-    nsCOMPtr<nsIVariant> buttons;
-    aRv = GetButtons(getter_AddRefs(buttons));
-    return buttons.forget();
+    aButtons = mButtons;
   }
 
-  already_AddRefed<nsIVariant> GetAxes(mozilla::ErrorResult& aRv)
+  void GetAxes(nsTArray<double>& aAxes) const
   {
-    nsCOMPtr<nsIVariant> axes;
-    aRv = GetAxes(getter_AddRefs(axes));
-    return axes.forget();
+    aAxes = mAxes;
   }
 
 private:
   virtual ~Gamepad() {}
 
-  nsresult GetButtons(nsIVariant** aButtons);
-  nsresult GetAxes(nsIVariant** aAxes);
-
 protected:
   nsCOMPtr<nsISupports> mParent;
   nsString mID;
   uint32_t mIndex;
 
   // The mapping in use.
   GamepadMappingType mMapping;
 
   // true if this gamepad is currently connected.
   bool mConnected;
 
   // Current state of buttons, axes.
   nsTArray<nsRefPtr<GamepadButton>> mButtons;
   nsTArray<double> mAxes;
-
-  // Cached variant array.
-  nsCOMPtr<nsIVariant> mButtonsVariant;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_gamepad_Gamepad_h
--- a/dom/plugins/ipc/PluginHangUIParent.cpp
+++ b/dom/plugins/ipc/PluginHangUIParent.cpp
@@ -377,17 +377,17 @@ PluginHangUIParent::GetHangUIOwnerWindow
   windowHandle = nullptr;
 
   nsresult rv;
   nsCOMPtr<nsIWindowMediator> winMediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID,
                                                         &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDOMWindow> navWin;
-  rv = winMediator->GetMostRecentWindow(NS_LITERAL_STRING("navigator:browser").get(),
+  rv = winMediator->GetMostRecentWindow(MOZ_UTF16("navigator:browser"),
                                         getter_AddRefs(navWin));
   NS_ENSURE_SUCCESS(rv, rv);
   if (!navWin) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(navWin);
   if (!widget) {
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -866,17 +866,17 @@ nsGeolocationService::StartDevice(nsIPri
       NS_FAILED(rv = mProvider->Watch(this))) {
 
     NotifyError(nsIDOMGeoPositionError::POSITION_UNAVAILABLE);
     return rv;
   }
 
   obs->NotifyObservers(mProvider,
                        "geolocation-device-events",
-                       NS_LITERAL_STRING("starting").get());
+                       MOZ_UTF16("starting"));
 
   return NS_OK;
 }
 
 void
 nsGeolocationService::SetDisconnectTimer()
 {
   if (!mDisconnectTimer) {
@@ -946,17 +946,17 @@ nsGeolocationService::StopDevice()
     return;
   }
 
   mHigherAccuracy = false;
 
   mProvider->Shutdown();
   obs->NotifyObservers(mProvider,
                        "geolocation-device-events",
-                       NS_LITERAL_STRING("shutdown").get());
+                       MOZ_UTF16("shutdown"));
 }
 
 StaticRefPtr<nsGeolocationService> nsGeolocationService::sService;
 
 already_AddRefed<nsGeolocationService>
 nsGeolocationService::GetGeolocationService()
 {
   nsRefPtr<nsGeolocationService> result;
--- a/dom/system/gonk/AudioManager.cpp
+++ b/dom/system/gonk/AudioManager.cpp
@@ -43,20 +43,20 @@
 using namespace mozilla::dom::gonk;
 using namespace android;
 using namespace mozilla::hal;
 using namespace mozilla;
 using namespace mozilla::dom::bluetooth;
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "AudioManager" , ## args)
 
-#define HEADPHONES_STATUS_HEADSET   NS_LITERAL_STRING("headset").get()
-#define HEADPHONES_STATUS_HEADPHONE NS_LITERAL_STRING("headphone").get()
-#define HEADPHONES_STATUS_OFF       NS_LITERAL_STRING("off").get()
-#define HEADPHONES_STATUS_UNKNOWN   NS_LITERAL_STRING("unknown").get()
+#define HEADPHONES_STATUS_HEADSET   MOZ_UTF16("headset")
+#define HEADPHONES_STATUS_HEADPHONE MOZ_UTF16("headphone")
+#define HEADPHONES_STATUS_OFF       MOZ_UTF16("off")
+#define HEADPHONES_STATUS_UNKNOWN   MOZ_UTF16("unknown")
 #define HEADPHONES_STATUS_CHANGED   "headphones-status-changed"
 #define MOZ_SETTINGS_CHANGE_ID      "mozsettings-changed"
 
 static void BinderDeadCallback(status_t aErr);
 static void InternalSetAudioRoutes(SwitchState aState);
 // Refer AudioService.java from Android
 static int sMaxStreamVolumeTbl[AUDIO_STREAM_CNT] = {
   5,   // voice call
--- a/dom/webidl/Gamepad.webidl
+++ b/dom/webidl/Gamepad.webidl
@@ -1,15 +1,13 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-interface nsIVariant;
-
 [Pref="dom.gamepad.enabled"]
 interface GamepadButton {
   readonly    attribute boolean pressed;
   readonly    attribute double  value;
 };
 
 [Pref="dom.gamepad.enabled"]
 interface Gamepad {
@@ -34,18 +32,18 @@ interface Gamepad {
    * true if this gamepad is currently connected to the system.
    */
   readonly attribute boolean connected;
 
   /**
    * The current state of all buttons on the device, an
    * array of GamepadButton.
    */
-  [Throws]
-  readonly attribute nsIVariant buttons;
+  [Pure, Cached, Frozen]
+  readonly attribute sequence<GamepadButton> buttons;
 
   /**
    * The current position of all axes on the device, an
    * array of doubles.
    */
-  [Throws]
-  readonly attribute nsIVariant axes;
+  [Pure, Cached, Frozen]
+  readonly attribute sequence<double> axes;
 };
new file mode 100644
--- /dev/null
+++ b/dom/webidl/MediaQueryList.webidl
@@ -0,0 +1,20 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * http://dev.w3.org/csswg/cssom-view/#the-mediaquerylist-interface
+ *
+ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+interface MediaQueryList {
+  readonly attribute DOMString media;
+  readonly attribute boolean matches;
+  void addListener(MediaQueryListListener listener);
+  void removeListener(MediaQueryListListener listener);
+};
+
+callback MediaQueryListListener = void (MediaQueryList list);
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -11,17 +11,16 @@
  * http://dev.w3.org/csswg/cssom-view/
  * https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/RequestAnimationFrame/Overview.html
  * https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html
  * https://dvcs.w3.org/hg/webcrypto-api/raw-file/tip/spec/Overview.html
  * http://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html
  */
 
 interface ApplicationCache;
-interface MediaQueryList;
 interface MozFrameRequestCallback;
 interface nsIDOMCrypto;
 interface Pkcs11;
 typedef any Transferable;
 
 // http://www.whatwg.org/specs/web-apps/current-work/
 [Global]
 /*sealed*/ interface Window : EventTarget {
@@ -142,18 +141,18 @@ partial interface Window {
 // http://dev.w3.org/csswg/cssom-view/
 enum ScrollBehavior { "auto", "instant", "smooth" };
 
 dictionary ScrollOptions {
   ScrollBehavior behavior = "auto";
 };
 
 partial interface Window {
-  //[Throws] MediaQueryList matchMedia(DOMString query);
-  [Throws] MediaQueryList? matchMedia(DOMString query);
+  //[Throws,NewObject] MediaQueryList matchMedia(DOMString query);
+  [Throws,NewObject] MediaQueryList? matchMedia(DOMString query);
   //[SameObject]
   [Throws] readonly attribute Screen screen;
 
   // browsing context
   //[Throws] void moveTo(double x, double y);
   //[Throws] void moveBy(double x, double y);
   //[Throws] void resizeTo(double x, double y);
   //[Throws] void resizeBy(double x, double y);
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -206,16 +206,17 @@ WEBIDL_FILES = [
     'KeyEvent.webidl',
     'LegacyQueryInterface.webidl',
     'LinkStyle.webidl',
     'LocalMediaStream.webidl',
     'Location.webidl',
     'MediaElementAudioSourceNode.webidl',
     'MediaError.webidl',
     'MediaList.webidl',
+    'MediaQueryList.webidl',
     'MediaRecorder.webidl',
     'MediaSource.webidl',
     'MediaStream.webidl',
     'MediaStreamAudioDestinationNode.webidl',
     'MediaStreamAudioSourceNode.webidl',
     'MediaStreamTrack.webidl',
     'MessageChannel.webidl',
     'MessageEvent.webidl',
--- a/editor/composer/src/nsEditingSession.cpp
+++ b/editor/composer/src/nsEditingSession.cpp
@@ -1017,17 +1017,17 @@ nsEditingSession::EndDocumentLoad(nsIWeb
 void
 nsEditingSession::TimerCallback(nsITimer* aTimer, void* aClosure)
 {
   nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(static_cast<nsIWeakReference*> (aClosure));
   if (docShell)
   {
     nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
     if (webNav)
-      webNav->LoadURI(NS_LITERAL_STRING("about:blank").get(),
+      webNav->LoadURI(MOZ_UTF16("about:blank"),
                       0, nullptr, nullptr, nullptr);
   }
 }
 
 /*---------------------------------------------------------------------------
 
   StartPageLoad
 
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -1207,22 +1207,22 @@ nsHTMLEditor::ReplaceHeadContentsWithHTM
   NS_ENSURE_TRUE(headNode, NS_ERROR_NULL_POINTER);
 
   // First, make sure there are no return chars in the source.
   // Bad things happen if you insert returns (instead of dom newlines, \n)
   // into an editor document.
   nsAutoString inputString (aSourceToInsert);  // hope this does copy-on-write
  
   // Windows linebreaks: Map CRLF to LF:
-  inputString.ReplaceSubstring(NS_LITERAL_STRING("\r\n").get(),
-                               NS_LITERAL_STRING("\n").get());
+  inputString.ReplaceSubstring(MOZ_UTF16("\r\n"),
+                               MOZ_UTF16("\n"));
  
   // Mac linebreaks: Map any remaining CR to LF:
-  inputString.ReplaceSubstring(NS_LITERAL_STRING("\r").get(),
-                               NS_LITERAL_STRING("\n").get());
+  inputString.ReplaceSubstring(MOZ_UTF16("\r"),
+                               MOZ_UTF16("\n"));
 
   nsAutoEditBatch beginBatching(this);
 
   res = GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(res, res);
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
 
   // Get the first range in the selection, for context:
--- a/embedding/components/commandhandler/src/nsCommandManager.cpp
+++ b/embedding/components/commandhandler/src/nsCommandManager.cpp
@@ -98,17 +98,17 @@ nsCommandManager::CommandStatusChanged(c
     // XXX Should we worry about observers removing themselves from Observe()?
     int32_t i, numItems = commandObservers->Length();
     for (i = 0; i < numItems;  ++i)
     {
       nsCOMPtr<nsIObserver> observer = commandObservers->ElementAt(i);
       // should we get the command state to pass here? This might be expensive.
       observer->Observe(NS_ISUPPORTS_CAST(nsICommandManager*, this),
                         aCommandName,
-                        NS_LITERAL_STRING("command_status_changed").get());
+                        MOZ_UTF16("command_status_changed"));
     }
   }
 
   return NS_OK;
 }
 
 #if 0
 #pragma mark -
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -762,17 +762,17 @@ nsPermissionManager::AddInternal(nsIPrin
       if (aNotifyOperation == eNotify) {
         NotifyObserversWithPermission(host,
                                       entry->GetKey()->mAppId,
                                       entry->GetKey()->mIsInBrowserElement,
                                       mTypeArray[typeIndex],
                                       aPermission,
                                       aExpireType,
                                       aExpireTime,
-                                      NS_LITERAL_STRING("added").get());
+                                      MOZ_UTF16("added"));
       }
 
       break;
     }
 
   case eOperationRemoving:
     {
       PermissionEntry oldPermissionEntry = entry->GetPermissions()[index];
@@ -788,17 +788,17 @@ nsPermissionManager::AddInternal(nsIPrin
       if (aNotifyOperation == eNotify) {
         NotifyObserversWithPermission(host,
                                       entry->GetKey()->mAppId,
                                       entry->GetKey()->mIsInBrowserElement,
                                       mTypeArray[typeIndex],
                                       oldPermissionEntry.mPermission,
                                       oldPermissionEntry.mExpireType,
                                       oldPermissionEntry.mExpireTime,
-                                      NS_LITERAL_STRING("deleted").get());
+                                      MOZ_UTF16("deleted"));
       }
 
       // If there are no more permissions stored for that entry, clear it.
       if (entry->GetPermissions().IsEmpty()) {
         mPermissionTable.RawRemoveEntry(entry);
       }
 
       break;
@@ -835,17 +835,17 @@ nsPermissionManager::AddInternal(nsIPrin
       if (aNotifyOperation == eNotify) {
         NotifyObserversWithPermission(host,
                                       entry->GetKey()->mAppId,
                                       entry->GetKey()->mIsInBrowserElement,
                                       mTypeArray[typeIndex],
                                       aPermission,
                                       aExpireType,
                                       aExpireTime,
-                                      NS_LITERAL_STRING("changed").get());
+                                      MOZ_UTF16("changed"));
       }
 
       break;
     }
   }
 
   return NS_OK;
 }
@@ -911,17 +911,17 @@ nsPermissionManager::CloseDB(bool aRebui
 nsresult
 nsPermissionManager::RemoveAllInternal(bool aNotifyObservers)
 {
   // Remove from memory and notify immediately. Since the in-memory
   // database is authoritative, we do not need confirmation from the
   // on-disk database to notify observers.
   RemoveAllFromMemory();
   if (aNotifyObservers) {
-    NotifyObservers(nullptr, NS_LITERAL_STRING("cleared").get());
+    NotifyObservers(nullptr, MOZ_UTF16("cleared"));
   }
 
   // clear the db
   if (mDBConn) {
     nsCOMPtr<mozIStorageAsyncStatement> removeStmt;
     nsresult rv = mDBConn->
       CreateAsyncStatement(NS_LITERAL_CSTRING(
          "DELETE FROM moz_hosts"
@@ -1251,17 +1251,17 @@ NS_IMETHODIMP nsPermissionManager::GetEn
 NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
 {
   ENSURE_NOT_CHILD_PROCESS;
 
   if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
     // The profile is about to change,
     // or is going away because the application is shutting down.
     mIsShuttingDown = true;
-    if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
+    if (!nsCRT::strcmp(someData, MOZ_UTF16("shutdown-cleanse"))) {
       // Clear the permissions file and close the db asynchronously
       RemoveAllInternal(false);
     } else {
       RemoveAllFromMemory();
       CloseDB(false);
     }
   }
   else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
@@ -1382,33 +1382,33 @@ nsPermissionManager::RemoveExpiredPermis
 
       gPermissionManager->NotifyObserversWithPermission(entry->GetKey()->mHost,
                                                         entry->GetKey()->mAppId,
                                                         entry->GetKey()->mIsInBrowserElement,
                                                         gPermissionManager->mTypeArray.ElementAt(oldPermissionEntry.mType),
                                                         oldPermissionEntry.mPermission,
                                                         oldPermissionEntry.mExpireType,
                                                         oldPermissionEntry.mExpireTime,
-                                                        NS_LITERAL_STRING("deleted").get());
+                                                        MOZ_UTF16("deleted"));
       --i;
       continue;
     }
 
     permEntry.mPermission = permEntry.mNonSessionPermission;
     permEntry.mExpireType = permEntry.mNonSessionExpireType;
     permEntry.mExpireTime = permEntry.mNonSessionExpireTime;
 
     gPermissionManager->NotifyObserversWithPermission(entry->GetKey()->mHost,
                                                       entry->GetKey()->mAppId,
                                                       entry->GetKey()->mIsInBrowserElement,
                                                       gPermissionManager->mTypeArray.ElementAt(permEntry.mType),
                                                       permEntry.mPermission,
                                                       permEntry.mExpireType,
                                                       permEntry.mExpireTime,
-                                                      NS_LITERAL_STRING("changed").get());
+                                                      MOZ_UTF16("changed"));
   }
 
   return PL_DHASH_NEXT;
 }
 
 nsresult
 nsPermissionManager::RemoveExpiredPermissionsForApp(uint32_t aAppId)
 {
--- a/extensions/gio/nsGIOProtocolHandler.cpp
+++ b/extensions/gio/nsGIOProtocolHandler.cpp
@@ -822,27 +822,27 @@ mount_operation_ask_password (GMountOper
     return;
   }
   nsAutoString nsmessage;
 
   if (flags & G_ASK_PASSWORD_NEED_PASSWORD) {
     if (flags & G_ASK_PASSWORD_NEED_USERNAME) {
       if (!realm.IsEmpty()) {
         const PRUnichar *strings[] = { realm.get(), dispHost.get() };
-        bundle->FormatStringFromName(NS_LITERAL_STRING("EnterLoginForRealm").get(),
+        bundle->FormatStringFromName(MOZ_UTF16("EnterLoginForRealm"),
                                      strings, 2, getter_Copies(nsmessage));
       } else {
         const PRUnichar *strings[] = { dispHost.get() };
-        bundle->FormatStringFromName(NS_LITERAL_STRING("EnterUserPasswordFor").get(),
+        bundle->FormatStringFromName(MOZ_UTF16("EnterUserPasswordFor"),
                                      strings, 1, getter_Copies(nsmessage));
       }
     } else {
       NS_ConvertUTF8toUTF16 userName(default_user);
       const PRUnichar *strings[] = { userName.get(), dispHost.get() };
-      bundle->FormatStringFromName(NS_LITERAL_STRING("EnterPasswordFor").get(),
+      bundle->FormatStringFromName(MOZ_UTF16("EnterPasswordFor"),
                                    strings, 2, getter_Copies(nsmessage));
     }
   } else {
     g_warning("Unknown mount operation request (flags: %x)", flags);
   }
 
   if (nsmessage.IsEmpty()) {
     g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED);
--- a/extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp
+++ b/extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp
@@ -217,23 +217,23 @@ ProxiedAuthCallback(gconstpointer in,
                           getter_AddRefs(bundle));
   if (!bundle)
     return;
 
   nsString message;
   if (!realm.IsEmpty())
   {
     const PRUnichar *strings[] = { realm.get(), dispHost.get() };
-    bundle->FormatStringFromName(NS_LITERAL_STRING("EnterUserPasswordForRealm").get(),
+    bundle->FormatStringFromName(MOZ_UTF16("EnterUserPasswordForRealm"),
                                  strings, 2, getter_Copies(message));
   }
   else
   {
     const PRUnichar *strings[] = { dispHost.get() };
-    bundle->FormatStringFromName(NS_LITERAL_STRING("EnterUserPasswordFor").get(),
+    bundle->FormatStringFromName(MOZ_UTF16("EnterUserPasswordFor"),
                                  strings, 1, getter_Copies(message));
   }
   if (message.IsEmpty())
     return;
 
   // Prompt the user...
   nsresult rv;
   bool retval = false;
--- a/extensions/pref/autoconfig/src/nsAutoConfig.cpp
+++ b/extensions/pref/autoconfig/src/nsAutoConfig.cpp
@@ -497,21 +497,21 @@ nsresult nsAutoConfig::PromptForEMailAdd
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIStringBundle> bundle;
     rv = bundleService->CreateBundle("chrome://autoconfig/locale/autoconfig.properties",
                                 getter_AddRefs(bundle));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsXPIDLString title;
-    rv = bundle->GetStringFromName(NS_LITERAL_STRING("emailPromptTitle").get(), getter_Copies(title));
+    rv = bundle->GetStringFromName(MOZ_UTF16("emailPromptTitle"), getter_Copies(title));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsXPIDLString err;
-    rv = bundle->GetStringFromName(NS_LITERAL_STRING("emailPromptMsg").get(), getter_Copies(err));
+    rv = bundle->GetStringFromName(MOZ_UTF16("emailPromptMsg"), getter_Copies(err));
     NS_ENSURE_SUCCESS(rv, rv);
     bool check = false;
     nsXPIDLString emailResult;
     bool success;
     rv = promptService->Prompt(nullptr, title.get(), err.get(), getter_Copies(emailResult), nullptr, &check, &success);
     if (!success)
       return NS_ERROR_FAILURE;
     NS_ENSURE_SUCCESS(rv, rv);
--- a/extensions/pref/autoconfig/src/nsReadConfig.cpp
+++ b/extensions/pref/autoconfig/src/nsReadConfig.cpp
@@ -54,22 +54,22 @@ static void DisplayError(void)
 
     nsCOMPtr<nsIStringBundle> bundle;
     bundleService->CreateBundle("chrome://autoconfig/locale/autoconfig.properties",
                                 getter_AddRefs(bundle));
     if (!bundle)
         return;
 
     nsXPIDLString title;
-    rv = bundle->GetStringFromName(NS_LITERAL_STRING("readConfigTitle").get(), getter_Copies(title));
+    rv = bundle->GetStringFromName(MOZ_UTF16("readConfigTitle"), getter_Copies(title));
     if (NS_FAILED(rv))
         return;
 
     nsXPIDLString err;
-    rv = bundle->GetStringFromName(NS_LITERAL_STRING("readConfigMsg").get(), getter_Copies(err));
+    rv = bundle->GetStringFromName(MOZ_UTF16("readConfigMsg"), getter_Copies(err));
     if (NS_FAILED(rv))
         return;
 
     promptService->Alert(nullptr, title.get(), err.get());
 }
 
 // nsISupports Implementation
 
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -138,17 +138,17 @@ public:
 NS_IMPL_ISUPPORTS2(SRGBOverrideObserver, nsIObserver, nsISupportsWeakReference)
 
 NS_IMETHODIMP
 SRGBOverrideObserver::Observe(nsISupports *aSubject,
                               const char *aTopic,
                               const PRUnichar *someData)
 {
     NS_ASSERTION(NS_strcmp(someData,
-                   NS_LITERAL_STRING("gfx.color_mangement.force_srgb").get()),
+                   MOZ_UTF16("gfx.color_mangement.force_srgb")),
                  "Restarting CMS on wrong pref!");
     ShutdownCMS();
     return NS_OK;
 }
 
 #define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
 
 #define GFX_PREF_HARFBUZZ_SCRIPTS "gfx.font_rendering.harfbuzz.scripts"
--- a/image/decoders/icon/gtk/nsIconChannel.cpp
+++ b/image/decoders/icon/gtk/nsIconChannel.cpp
@@ -315,17 +315,17 @@ nsIconChannel::InitWithGnome(nsIMozIconU
     NS_ASSERTION(bundleService, "String bundle service must be present!");
 
     nsCOMPtr<nsIStringBundle> bundle;
     bundleService->CreateBundle("chrome://branding/locale/brand.properties",
                                 getter_AddRefs(bundle));
     nsAutoString appName;
 
     if (bundle) {
-      bundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
+      bundle->GetStringFromName(MOZ_UTF16("brandShortName"),
                                 getter_Copies(appName));
     } else {
       NS_WARNING("brand.properties not present, using default application name");
       appName.Assign(NS_LITERAL_STRING("Gecko"));
     }
 
     char* empty[] = { "" };
     _gnome_init(NS_ConvertUTF16toUTF8(appName).get(),
--- a/intl/uconv/src/nsCharsetConverterManager.cpp
+++ b/intl/uconv/src/nsCharsetConverterManager.cpp
@@ -106,17 +106,17 @@ nsresult GetCharsetDataImpl(const char *
 }
 
 //static
 bool nsCharsetConverterManager::IsInternal(const nsACString& aCharset)
 {
   nsAutoString str;
   // fully qualify to possibly avoid vtable call
   nsresult rv = GetCharsetDataImpl(PromiseFlatCString(aCharset).get(),
-                                   NS_LITERAL_STRING(".isInternal").get(),
+                                   MOZ_UTF16(".isInternal"),
                                    str);
 
   return NS_SUCCEEDED(rv);
 }
 
 
 //----------------------------------------------------------------------------//----------------------------------------------------------------------------
 // Interface nsICharsetConverterManager [implementation]
@@ -340,17 +340,17 @@ NS_IMETHODIMP
 nsCharsetConverterManager::GetCharsetLangGroupRaw(const char * aCharset, 
                                                   nsIAtom** aResult)
 {
 
   *aResult = nullptr;
   nsAutoString langGroup;
   // fully qualify to possibly avoid vtable call
   nsresult rv = nsCharsetConverterManager::GetCharsetData(
-      aCharset, NS_LITERAL_STRING(".LangGroup").get(), langGroup);
+      aCharset, MOZ_UTF16(".LangGroup"), langGroup);
 
   if (NS_SUCCEEDED(rv)) {
     ToLowerCase(langGroup); // use lowercase for all language atoms
     *aResult = NS_NewAtom(langGroup).get();
   }
 
   return rv;
 }
--- a/intl/unicharutil/src/nsEntityConverter.cpp
+++ b/intl/unicharutil/src/nsEntityConverter.cpp
@@ -38,17 +38,17 @@ nsEntityConverter::LoadVersionPropertyFi
     nsCOMPtr<nsIStringBundle> entities;
     nsresult rv = bundleService->CreateBundle(url.get(), getter_AddRefs(entities));
     if (NS_FAILED(rv)) return rv;
     
     nsresult result;
 
     nsAutoString key;
     nsXPIDLString value;
-    rv = entities->GetStringFromName(NS_LITERAL_STRING("length").get(),
+    rv = entities->GetStringFromName(MOZ_UTF16("length"),
                                      getter_Copies(value));
     NS_ASSERTION(NS_SUCCEEDED(rv),"nsEntityConverter: malformed entity table\n");
     if (NS_FAILED(rv)) return rv;
       
     mVersionListLength = nsAutoString(value).ToInteger(&result);
     NS_ASSERTION(32 >= mVersionListLength,"nsEntityConverter: malformed entity table\n");
     if (32 < mVersionListLength) return NS_ERROR_FAILURE;
     
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -65,16 +65,18 @@ js::CreateRegExpMatchResult(JSContext *c
     /* Get the templateObject that defines the shape and type of the output object */
     JSObject *templateObject = cx->compartment()->regExps.getOrCreateMatchResultTemplateObject(cx);
     if (!templateObject)
         return false;
 
     /* Copy the rooted vector into the array object. */
     RootedObject arr(cx, NewDenseCopiedArrayWithTemplate(cx, elements.length(), elements.begin(),
                                                          templateObject));
+    if (!arr)
+        return false;
 
     /* Set the |index| property. (TemplateObject positions it in slot 0) */
     RootedValue index(cx, Int32Value(matches[0].start));
     arr->nativeSetSlot(0, index);
 
     /* Set the |input| property. (TemplateObject positions it in slot 1) */
     RootedValue inputVal(cx, StringValue(input));
     arr->nativeSetSlot(1, inputVal);
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -2066,32 +2066,16 @@ EmitNameOp(ExclusiveContext *cx, Bytecod
         }
         if (Emit1(cx, bce, JSOP_NOTEARG) < 0)
             return false;
     }
 
     return true;
 }
 
-static inline bool
-EmitElemOpBase(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op)
-{
-    if (Emit1(cx, bce, op) < 0)
-        return false;
-    CheckTypeSet(cx, bce, op);
-
-    if (op == JSOP_CALLELEM) {
-        if (Emit1(cx, bce, JSOP_SWAP) < 0)
-            return false;
-        if (Emit1(cx, bce, JSOP_NOTEARG) < 0)
-            return false;
-    }
-    return true;
-}
-
 static bool
 EmitPropLHS(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
 {
     JS_ASSERT(pn->isKind(PNK_DOT));
     ParseNode *pn2 = pn->maybeExpr();
 
     /*
      * If the object operand is also a dotted property reference, reverse the
@@ -2229,55 +2213,49 @@ EmitNameIncDec(ExclusiveContext *cx, Par
     if (!EmitAtomOp(cx, pn->pn_kid, global ? JSOP_SETGNAME : JSOP_SETNAME, bce)) // N? N+1
         return false;
     if (post && Emit1(cx, bce, JSOP_POP) < 0)       // RESULT
         return false;
 
     return true;
 }
 
+/*
+ * Emit bytecode to put operands for a JSOP_GETELEM/CALLELEM/SETELEM/DELELEM
+ * opcode onto the stack in the right order. In the case of SETELEM, the
+ * value to be assigned must already be pushed.
+ */
 static bool
 EmitElemOperands(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
 {
-    ParseNode *left, *right;
-
-    if (pn->isArity(PN_NAME)) {
-        /*
-         * Set left and right so pn appears to be a PNK_ELEM node, instead of
-         * a PNK_DOT node. See the PNK_FOR/IN case in EmitTree, and
-         * EmitDestructuringOps nearer below. In the destructuring case, the
-         * base expression (pn_expr) of the name may be null, which means we
-         * have to emit a JSOP_BINDNAME.
-         */
-        left = pn->maybeExpr();
-        if (!left) {
-            left = bce->parser->handler.new_<NullaryNode>(
-                PNK_STRING, JSOP_BINDNAME, pn->pn_pos, pn->pn_atom);
-            if (!left)
-                return false;
-        }
-        right = bce->parser->handler.new_<NullaryNode>(
-            PNK_STRING, JSOP_STRING, pn->pn_pos, pn->pn_atom);
-        if (!right)
-            return false;
-    } else {
-        JS_ASSERT(pn->isArity(PN_BINARY));
-        left = pn->pn_left;
-        right = pn->pn_right;
-    }
-
-    if (!EmitTree(cx, bce, left))
-        return false;
-
+    JS_ASSERT(pn->isArity(PN_BINARY));
+    if (!EmitTree(cx, bce, pn->pn_left))
+        return false;
     if (op == JSOP_CALLELEM && Emit1(cx, bce, JSOP_DUP) < 0)
         return false;
-
-    if (!EmitTree(cx, bce, right))
-        return false;
-
+    if (!EmitTree(cx, bce, pn->pn_right))
+        return false;
+    if (op == JSOP_SETELEM && Emit2(cx, bce, JSOP_PICK, (jsbytecode)2) < 0)
+        return false;
+    return true;
+}
+
+static inline bool
+EmitElemOpBase(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op)
+{
+    if (Emit1(cx, bce, op) < 0)
+        return false;
+    CheckTypeSet(cx, bce, op);
+
+    if (op == JSOP_CALLELEM) {
+        if (Emit1(cx, bce, JSOP_SWAP) < 0)
+            return false;
+        if (Emit1(cx, bce, JSOP_NOTEARG) < 0)
+            return false;
+    }
     return true;
 }
 
 static bool
 EmitElemOp(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
 {
     return EmitElemOperands(cx, pn, op, bce) && EmitElemOpBase(cx, bce, op);
 }
@@ -2937,126 +2915,132 @@ EmitDestructuringOpsHelper(ExclusiveCont
  * with the initial values of the N (where 0 <= N) variables assigned in the
  * lhs expression. (Same post-condition as EmitDestructuringOpsHelper)
  */
 static bool
 EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmitOption emitOption)
 {
     JS_ASSERT(emitOption != DefineVars);
 
-    /*
-     * Now emit the lvalue opcode sequence.  If the lvalue is a nested
-     * destructuring initialiser-form, call ourselves to handle it, then
-     * pop the matched value.  Otherwise emit an lvalue bytecode sequence
-     * ending with a JSOP_ENUMELEM or equivalent op.
-     */
+    // Now emit the lvalue opcode sequence. If the lvalue is a nested
+    // destructuring initialiser-form, call ourselves to handle it, then pop
+    // the matched value. Otherwise emit an lvalue bytecode sequence followed
+    // by an assignment op.
     if (pn->isKind(PNK_ARRAY) || pn->isKind(PNK_OBJECT)) {
         if (!EmitDestructuringOpsHelper(cx, bce, pn, emitOption))
             return false;
         if (emitOption == InitializeVars) {
-            /*
-             * Per its post-condition, EmitDestructuringOpsHelper has left the
-             * to-be-destructured value on top of the stack.
-             */
+            // Per its post-condition, EmitDestructuringOpsHelper has left the
+            // to-be-destructured value on top of the stack.
             if (Emit1(cx, bce, JSOP_POP) < 0)
                 return false;
         }
     } else if (emitOption == PushInitialValues) {
         // The lhs is a simple name so the to-be-destructured value is
         // its initial value and there is nothing to do.
         JS_ASSERT(pn->getOp() == JSOP_GETLOCAL);
         JS_ASSERT(pn->pn_dflags & PND_BOUND);
     } else {
-        // All paths below must pop after assigning to the lhs.
-
         switch (pn->getKind()) {
           case PNK_NAME:
             if (!BindNameToSlot(cx, bce, pn))
                 return false;
 
             // Allow 'const [x,y] = o', make 'const x,y; [x,y] = o' a nop.
             if (pn->isConst() && !pn->isDefn())
                 return Emit1(cx, bce, JSOP_POP) >= 0;
 
             switch (pn->getOp()) {
               case JSOP_SETNAME:
               case JSOP_SETGNAME:
+              case JSOP_SETCONST: {
                 // This is like ordinary assignment, but with one difference.
                 //
                 // In `a = b`, we first determine a binding for `a` (using
                 // JSOP_BINDNAME or JSOP_BINDGNAME), then we evaluate `b`, then
                 // a JSOP_SETNAME instruction.
                 //
                 // In `[a] = [b]`, per spec, `b` is evaluated first, then we
                 // determine a binding for `a`. Then we need to do assignment--
                 // but the operands are on the stack in the wrong order for
-                // JSOP_SETPROP, so we use JSOP_ENUMELEM instead.
-                //
-                // EmitElemOp ordinarily works with PNK_ELEM nodes, naturally,
-                // but it has special code to handle PNK_NAME nodes in this one
-                // case.
-                if (!EmitElemOp(cx, pn, JSOP_ENUMELEM, bce))
+                // JSOP_SETPROP, so we have to add a JSOP_SWAP.
+                jsatomid atomIndex;
+                if (!bce->makeAtomIndex(pn->pn_atom, &atomIndex))
+                    return false;
+
+                if (!pn->isOp(JSOP_SETCONST)) {
+                    JSOp bindOp = pn->isOp(JSOP_SETNAME) ? JSOP_BINDNAME : JSOP_BINDGNAME;
+                    if (!EmitIndex32(cx, bindOp, atomIndex, bce))
+                        return false;
+                    if (Emit1(cx, bce, JSOP_SWAP) < 0)
+                        return false;
+                }
+
+                if (!EmitIndexOp(cx, pn->getOp(), atomIndex, bce))
                     return false;
                 break;
-
-              case JSOP_SETCONST:
-                // As above.
-                if (!EmitElemOp(cx, pn, JSOP_ENUMCONSTELEM, bce))
-                    return false;
-                break;
+              }
 
               case JSOP_SETLOCAL:
               case JSOP_SETARG:
                 if (!EmitVarOp(cx, pn, pn->getOp(), bce))
                     return false;
-                if (Emit1(cx, bce, JSOP_POP) < 0)
-                    return false;
                 break;
 
               default:
                 MOZ_ASSUME_UNREACHABLE("EmitDestructuringLHS: bad name op");
             }
             break;
 
           case PNK_DOT:
-          case PNK_ELEM:
             // See the (PNK_NAME, JSOP_SETNAME) case above.
             //
             // In `a.x = b`, `a` is evaluated first, then `b`, then a
             // JSOP_SETPROP instruction.
             //
             // In `[a.x] = [b]`, per spec, `b` is evaluated before `a`. Then we
             // need a property set -- but the operands are on the stack in the
-            // wrong order for JSOP_SETPROP, so we use JSOP_ENUMELEM instead.
-            //
-            // EmitElemOp has special code to handle PNK_DOT nodes in this one
-            // case.
-            if (!EmitElemOp(cx, pn, JSOP_ENUMELEM, bce))
+            // wrong order for JSOP_SETPROP, so we have to add a JSOP_SWAP.
+            if (!EmitTree(cx, bce, pn->pn_expr))
+                return false;
+            if (Emit1(cx, bce, JSOP_SWAP) < 0)
+                return false;
+            if (!EmitAtomOp(cx, pn, JSOP_SETPROP, bce))
+                return false;
+            break;
+
+          case PNK_ELEM:
+            // See the comment at `case PNK_DOT:` above. This case,
+            // `[a[x]] = [b]`, is handled much the same way. The JSOP_SWAP
+            // is emitted by EmitElemOperands.
+            if (!EmitElemOp(cx, pn, JSOP_SETELEM, bce))
                 return false;
             break;
 
           case PNK_CALL:
             JS_ASSERT(pn->pn_xflags & PNX_SETCALL);
             if (!EmitTree(cx, bce, pn))
                 return false;
 
-            // Pop the call return value and the RHS, presumably for the
-            // benefit of bytecode analysis. (The interpreter will never reach
-            // these instructions since we just emitted JSOP_SETCALL, which
-            // always throws. It's possible no analyses actually depend on this
-            // either.)
-            if (Emit1(cx, bce, JSOP_POP) < 0)
-                return false;
+            // Pop the call return value. Below, we pop the RHS too, balancing
+            // the stack --- presumably for the benefit of bytecode
+            // analysis. (The interpreter will never reach these instructions
+            // since we just emitted JSOP_SETCALL, which always throws. It's
+            // possible no analyses actually depend on this either.)
             if (Emit1(cx, bce, JSOP_POP) < 0)
                 return false;
             break;
 
           default:
             MOZ_ASSUME_UNREACHABLE("EmitDestructuringLHS: bad lhs kind");
         }
+
+        // Pop the assigned value.
+        if (Emit1(cx, bce, JSOP_POP) < 0)
+            return false;
     }
 
     return true;
 }
 
 /*
  * Recursive helper for EmitDestructuringOps.
  * EmitDestructuringOpsHelper assumes the to-be-destructured value has been
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -545,65 +545,92 @@ Fold(ExclusiveContext *cx, ParseNode **p
          */
         goto do_binary_op;
 
       case PNK_ADDASSIGN:
         JS_ASSERT(pn->isOp(JSOP_ADD));
         /* FALL THROUGH */
       case PNK_ADD:
         if (pn->isArity(PN_LIST)) {
-            /*
-             * Any string literal term with all others number or string means
-             * this is a concatenation.  If any term is not a string or number
-             * literal, we can't fold.
-             */
-            JS_ASSERT(pn->pn_count > 2);
-            if (pn->pn_xflags & PNX_CANTFOLD)
-                return true;
-            if (pn->pn_xflags != PNX_STRCAT)
-                goto do_binary_op;
+            bool folded = false;
 
-            /* Ok, we're concatenating: convert non-string constant operands. */
-            size_t length = 0;
-            for (pn2 = pn1; pn2; pn2 = pn2->pn_next) {
-                if (!FoldType(cx, pn2, PNK_STRING))
-                    return false;
-                /* XXX fold only if all operands convert to string */
-                if (!pn2->isKind(PNK_STRING))
-                    return true;
-                length += pn2->pn_atom->length();
+            pn2 = pn1->pn_next;
+            if (pn1->isKind(PNK_NUMBER)) {
+                // Fold addition of numeric literals: (1 + 2 + x === 3 + x).
+                // Note that we can only do this the front of the list:
+                // (x + 1 + 2 !== x + 3) when x is a string.
+                while (pn2 && pn2->isKind(PNK_NUMBER)) {
+                    pn1->pn_dval += pn2->pn_dval;
+                    pn1->pn_next = pn2->pn_next;
+                    handler.freeTree(pn2);
+                    pn2 = pn1->pn_next;
+                    pn->pn_count--;
+                    folded = true;
+                }
             }
 
-            /* Allocate a new buffer and string descriptor for the result. */
-            jschar *chars = cx->pod_malloc<jschar>(length + 1);
-            if (!chars)
-                return false;
-            chars[length] = 0;
-            JSString *str = js_NewString<CanGC>(cx, chars, length);
-            if (!str) {
-                js_free(chars);
-                return false;
+            // Now search for adjacent pairs of literals to fold for string
+            // concatenation.
+            //
+            // isStringConcat is true if we know the operation we're looking at
+            // will be string concatenation at runtime.  As soon as we see a
+            // string, we know that every addition to the right of it will be
+            // string concatenation, even if both operands are numbers:
+            // ("s" + x + 1 + 2 === "s" + x + "12").
+            //
+            bool isStringConcat = false;
+
+            // (number + string) is definitely concatenation, but only at the
+            // front of the list: (x + 1 + "2" !== x + "12") when x is a
+            // number.
+            if (pn1->isKind(PNK_NUMBER) && pn2 && pn2->isKind(PNK_STRING))
+                isStringConcat = true;
+
+            while (pn2) {
+                isStringConcat = isStringConcat || pn1->isKind(PNK_STRING);
+
+                if (isStringConcat &&
+                    (pn1->isKind(PNK_STRING) || pn1->isKind(PNK_NUMBER)) &&
+                    (pn2->isKind(PNK_STRING) || pn2->isKind(PNK_NUMBER)))
+                {
+                    // Fold string concatenation of literals.
+                    if (pn1->isKind(PNK_NUMBER) && !FoldType(cx, pn1, PNK_STRING))
+                        return false;
+                    if (pn2->isKind(PNK_NUMBER) && !FoldType(cx, pn2, PNK_STRING))
+                        return false;
+                    RootedString left(cx, pn1->pn_atom);
+                    RootedString right(cx, pn2->pn_atom);
+                    RootedString str(cx, ConcatStrings<CanGC>(cx, left, right));
+                    if (!str)
+                        return false;
+                    pn1->pn_atom = AtomizeString(cx, str);
+                    if (!pn1->pn_atom)
+                        return false;
+                    pn1->pn_next = pn2->pn_next;
+                    handler.freeTree(pn2);
+                    pn2 = pn1->pn_next;
+                    pn->pn_count--;
+                    folded = true;
+                } else {
+                    pn1 = pn2;
+                    pn2 = pn2->pn_next;
+                }
             }
 
-            /* Fill the buffer, advancing chars and recycling kids as we go. */
-            for (pn2 = pn1; pn2; pn2 = handler.freeTree(pn2)) {
-                JSAtom *atom = pn2->pn_atom;
-                size_t length2 = atom->length();
-                js_strncpy(chars, atom->chars(), length2);
-                chars += length2;
+            if (folded) {
+                if (pn->pn_count == 1) {
+                    // We reduced the list to one constant. There is no
+                    // addition anymore. Replace the PNK_ADD node with the
+                    // single PNK_STRING or PNK_NUMBER node.
+                    ReplaceNode(pnp, pn1);
+                    pn = pn1;
+                } else if (!pn2) {
+                    pn->pn_tail = &pn1->pn_next;
+                }
             }
-            JS_ASSERT(*chars == 0);
-
-            /* Atomize the result string and mutate pn to refer to it. */
-            pn->pn_atom = AtomizeString(cx, str);
-            if (!pn->pn_atom)
-                return false;
-            pn->setKind(PNK_STRING);
-            pn->setOp(JSOP_STRING);
-            pn->setArity(PN_NULLARY);
             break;
         }
 
         /* Handle a binary string concatenation. */
         JS_ASSERT(pn->isArity(PN_BINARY));
         if (pn1->isKind(PNK_STRING) || pn2->isKind(PNK_STRING)) {
             if (!FoldType(cx, !pn1->isKind(PNK_STRING) ? pn1 : pn2, PNK_STRING))
                 return false;
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -274,36 +274,20 @@ ParseNode::append(ParseNodeKind kind, JS
     if (left->pn_arity == PN_LIST) {
         list = &left->as<ListNode>();
     } else {
         ParseNode *pn1 = left->pn_left, *pn2 = left->pn_right;
         list = handler->new_<ListNode>(kind, op, pn1);
         if (!list)
             return nullptr;
         list->append(pn2);
-        if (kind == PNK_ADD) {
-            if (pn1->isKind(PNK_STRING))
-                list->pn_xflags |= PNX_STRCAT;
-            else if (!pn1->isKind(PNK_NUMBER))
-                list->pn_xflags |= PNX_CANTFOLD;
-            if (pn2->isKind(PNK_STRING))
-                list->pn_xflags |= PNX_STRCAT;
-            else if (!pn2->isKind(PNK_NUMBER))
-                list->pn_xflags |= PNX_CANTFOLD;
-        }
     }
 
     list->append(right);
     list->pn_pos.end = right->pn_pos.end;
-    if (kind == PNK_ADD) {
-        if (right->isKind(PNK_STRING))
-            list->pn_xflags |= PNX_STRCAT;
-        else if (!right->isKind(PNK_NUMBER))
-            list->pn_xflags |= PNX_CANTFOLD;
-    }
 
     return list;
 }
 
 ParseNode *
 ParseNode::newBinaryOrAppend(ParseNodeKind kind, JSOp op, ParseNode *left, ParseNode *right,
                              FullParseHandler *handler, ParseContext<FullParseHandler> *pc,
                              bool foldConstants)
@@ -320,34 +304,16 @@ ParseNode::newBinaryOrAppend(ParseNodeKi
 
     /*
      * Flatten a left-associative (left-heavy) tree of a given operator into
      * a list to reduce js::FoldConstants and js::frontend::EmitTree recursion.
      */
     if (left->isKind(kind) && left->isOp(op) && (js_CodeSpec[op].format & JOF_LEFTASSOC))
         return append(kind, op, left, right, handler);
 
-    /*
-     * Fold constant addition immediately, to conserve node space and, what's
-     * more, so js::FoldConstants never sees mixed addition and concatenation
-     * operations with more than one leading non-string operand in a PN_LIST
-     * generated for expressions such as 1 + 2 + "pt" (which should evaluate
-     * to "3pt", not "12pt").
-     */
-    if (kind == PNK_ADD &&
-        left->isKind(PNK_NUMBER) &&
-        right->isKind(PNK_NUMBER) &&
-        foldConstants)
-    {
-        left->pn_dval += right->pn_dval;
-        left->pn_pos.end = right->pn_pos.end;
-        handler->freeTree(right);
-        return left;
-    }
-
     return handler->new_<BinaryNode>(kind, op, left, right);
 }
 
 const char *
 Definition::kindString(Kind kind)
 {
     static const char * const table[] = {
         "", js_var_str, js_const_str, js_let_str, js_function_str, "argument", "unknown"
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -654,18 +654,16 @@ class ParseNode
                                            into a definition after the function
                                            body has been parsed. */
 #define PND_EMITTEDFUNCTION    0x400    /* hoisted function that was emitted */
 
 /* Flags to propagate from uses to definition. */
 #define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_CLOSED)
 
 /* PN_LIST pn_xflags bits. */
-#define PNX_STRCAT      0x01            /* PNK_ADD list has string term */
-#define PNX_CANTFOLD    0x02            /* PNK_ADD list has unfoldable term */
 #define PNX_POPVAR      0x04            /* PNK_VAR or PNK_CONST last result
                                            needs popping */
 #define PNX_GROUPINIT   0x08            /* var [a, b] = [c, d]; unit list */
 #define PNX_FUNCDEFS    0x10            /* contains top-level function statements */
 #define PNX_SETCALL     0x20            /* call expression in lvalue context */
 #define PNX_DESTRUCT    0x40            /* destructuring special cases:
                                            1. shorthand syntax used, at present
                                               object destructuring ({x,y}) only;
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -574,28 +574,18 @@ CompileError::throwError(JSContext *cx)
     //
     // If an exception is thrown but not caught, the JSREPORT_EXCEPTION
     // flag will be set in report.flags.  Proper behavior for an error
     // reporter is to ignore a report with this flag for all but top-level
     // compilation errors.  The exception will remain pending, and so long
     // as the non-top-level "load", "eval", or "compile" native function
     // returns false, the top-level reporter will eventually receive the
     // uncaught exception report.
-    if (!js_ErrorToException(cx, message, &report, nullptr, nullptr)) {
-        // If debugErrorHook is present then we give it a chance to veto
-        // sending the error on to the regular error reporter.
-        bool reportError = true;
-        if (JSDebugErrorHook hook = cx->runtime()->debugHooks.debugErrorHook) {
-            reportError = hook(cx, message, &report, cx->runtime()->debugHooks.debugErrorHookData);
-        }
-
-        // Report the error.
-        if (reportError && cx->errorReporter)
-            cx->errorReporter(cx, message, &report);
-    }
+    if (!js_ErrorToException(cx, message, &report, nullptr, nullptr))
+        CallErrorReporter(cx, message, &report);
 }
 
 CompileError::~CompileError()
 {
     js_free((void*)report.uclinebuf);
     js_free((void*)report.linebuf);
     js_free((void*)report.ucmessage);
     js_free(message);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/constant-folding-1.js
@@ -0,0 +1,43 @@
+function bytecode(f) {
+    if (typeof disassemble !== "function")
+        return "unavailable";
+    var d = disassemble(f);
+    return d.slice(d.indexOf("main:"), d.indexOf("\n\n"));
+}
+assertEq(bytecode(() => "hello" + "world"),
+         bytecode(() => "helloworld"));
+assertEq(bytecode(() => 2 + "2" + "2"),
+         bytecode(() => "222"));
+assertEq(bytecode(() => "x" + "3"),
+         bytecode(() => "x3"));
+
+var s = "hoge";
+assertEq(bytecode(() => "fo" + "o" + s + "ba" + "r"),
+         bytecode(() => "foo" + s + "bar"));
+assertEq(bytecode(() => "fo" + "o" + 1 + s + 1 + "ba" + "r"),
+         bytecode(() => "foo1" + s + "1bar"));
+assertEq(bytecode(() => 1 + (2 * 2) + "x"),
+         bytecode(() => 5 + "x"));
+assertEq(s + 1 + 2, "hoge12");
+assertEq((() => s + 1 + 2)(), "hoge12");
+
+// SpiderMonkey knows that 1 + 1 == "11".
+assertEq(bytecode(() => "x" + s + 1 + 1),
+         bytecode(() => "x" + s + "11"));
+
+var n = 5;
+assertEq(1 + n + 1 + "ba" + "r", "7bar");
+assertEq(1 + 2 + {valueOf: () => 3, toString: () => 'x'} + 4 + 5,15);
+assertEq(1+2+n,8);
+assertEq(bytecode(() => 1 + 2 + n + 1 + 2),
+         bytecode(() => 3 + n + 1 + 2));
+assertEq(1 + 2 + n + 1 + 2, 11);
+assertEq(bytecode(() => 1 + 2 + s + 1 + 2),
+         bytecode(() => 3 + s + 1 + 2));
+assertEq(1 + 2 + s + 1 + 2, "3hoge12");
+
+assertEq(bytecode(() => ["a" + "b" + n]),
+         bytecode(() => ["ab" + n]));
+var a = ["a" + "b" + n];
+assertEq(a[0], "ab5");
+
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -1722,35 +1722,16 @@ BaselineCompiler::emit_JSOP_SETELEM()
     // Call IC.
     ICSetElem_Fallback::Compiler stubCompiler(cx);
     if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
         return false;
 
     return true;
 }
 
-bool
-BaselineCompiler::emit_JSOP_ENUMELEM()
-{
-    // ENUMELEM is a SETELEM with a different stack arrangement.
-    // Instead of:   OBJ ID RHS
-    // The stack is: RHS OBJ ID
-
-    // Keep object and index in R0 and R1, and keep RHS on the stack.
-    frame.popRegsAndSync(2);
-
-    // Call IC.
-    ICSetElem_Fallback::Compiler stubCompiler(cx);
-    if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
-        return false;
-
-    frame.pop();
-    return true;
-}
-
 typedef bool (*DeleteElementFn)(JSContext *, HandleValue, HandleValue, bool *);
 static const VMFunction DeleteElementStrictInfo = FunctionInfo<DeleteElementFn>(DeleteElement<true>);
 static const VMFunction DeleteElementNonStrictInfo = FunctionInfo<DeleteElementFn>(DeleteElement<false>);
 
 bool
 BaselineCompiler::emit_JSOP_DELELEM()
 {
     // Keep values on the stack for the decompiler.
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -93,17 +93,16 @@ namespace jit {
     _(JSOP_INITELEM_SETTER)    \
     _(JSOP_INITPROP)           \
     _(JSOP_INITPROP_GETTER)    \
     _(JSOP_INITPROP_SETTER)    \
     _(JSOP_ENDINIT)            \
     _(JSOP_GETELEM)            \
     _(JSOP_SETELEM)            \
     _(JSOP_CALLELEM)           \
-    _(JSOP_ENUMELEM)           \
     _(JSOP_DELELEM)            \
     _(JSOP_IN)                 \
     _(JSOP_GETGNAME)           \
     _(JSOP_CALLGNAME)          \
     _(JSOP_BINDGNAME)          \
     _(JSOP_SETGNAME)           \
     _(JSOP_SETNAME)            \
     _(JSOP_GETPROP)            \
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -4927,17 +4927,16 @@ DoSetElemFallback(JSContext *cx, Baselin
                   HandleValue objv, HandleValue index, HandleValue rhs)
 {
     RootedScript script(cx, frame->script());
     jsbytecode *pc = stub->icEntry()->pc(script);
     JSOp op = JSOp(*pc);
     FallbackICSpew(cx, stub, "SetElem(%s)", js_CodeName[JSOp(*pc)]);
 
     JS_ASSERT(op == JSOP_SETELEM ||
-              op == JSOP_ENUMELEM ||
               op == JSOP_INITELEM ||
               op == JSOP_INITELEM_ARRAY);
 
     RootedObject obj(cx, ToObjectFromStack(cx, objv));
     if (!obj)
         return false;
 
     RootedShape oldShape(cx, obj->lastProperty());
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5909,25 +5909,16 @@ JS_ErrorFromException(JSContext *cx, Han
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, value);
     return js_ErrorFromException(value);
 }
 
 JS_PUBLIC_API(bool)
-JS_ThrowReportedError(JSContext *cx, const char *message,
-                      JSErrorReport *reportp)
-{
-    AssertHeapIsIdle(cx);
-    return JS_IsRunning(cx) &&
-           js_ErrorToException(cx, message, reportp, nullptr, nullptr);
-}
-
-JS_PUBLIC_API(bool)
 JS_ThrowStopIteration(JSContext *cx)
 {
     AssertHeapIsIdle(cx);
     return js_ThrowStopIteration(cx);
 }
 
 JS_PUBLIC_API(bool)
 JS_IsStopIteration(jsval v)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4460,24 +4460,16 @@ JS_DropExceptionState(JSContext *cx, JSE
  * the address of that struct.  Otherwise, it returns nullptr.  The lifetime
  * of the error report struct that might be returned is the same as the
  * lifetime of the exception object.
  */
 extern JS_PUBLIC_API(JSErrorReport *)
 JS_ErrorFromException(JSContext *cx, JS::HandleValue v);
 
 /*
- * Given a reported error's message and JSErrorReport struct pointer, throw
- * the corresponding exception on cx.
- */
-extern JS_PUBLIC_API(bool)
-JS_ThrowReportedError(JSContext *cx, const char *message,
-                      JSErrorReport *reportp);
-
-/*
  * Throws a StopIteration exception on cx.
  */
 extern JS_PUBLIC_API(bool)
 JS_ThrowStopIteration(JSContext *cx);
 
 extern JS_PUBLIC_API(bool)
 JS_IsStopIteration(jsval v);
 
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -285,29 +285,31 @@ ReportError(JSContext *cx, const char *m
      * Check the error report, and set a JavaScript-catchable exception
      * if the error is defined to have an associated exception.  If an
      * exception is thrown, then the JSREPORT_EXCEPTION flag will be set
      * on the error report, and exception-aware hosts should ignore it.
      */
     JS_ASSERT(reportp);
     if ((!callback || callback == js_GetErrorMessage) &&
         reportp->errorNumber == JSMSG_UNCAUGHT_EXCEPTION)
+    {
         reportp->flags |= JSREPORT_EXCEPTION;
+    }
 
     /*
      * Call the error reporter only if an exception wasn't raised.
      *
      * If an exception was raised, then we call the debugErrorHook
      * (if present) to give it a chance to see the error before it
      * propagates out of scope.  This is needed for compatibility
      * with the old scheme.
      */
-    if (!JS_IsRunning(cx) ||
-        !js_ErrorToException(cx, message, reportp, callback, userRef)) {
-        js_ReportErrorAgain(cx, message, reportp);
+    if (!JS_IsRunning(cx) || !js_ErrorToException(cx, message, reportp, callback, userRef)) {
+        if (message)
+            CallErrorReporter(cx, message, reportp);
     } else if (JSDebugErrorHook hook = cx->runtime()->debugHooks.debugErrorHook) {
         /*
          * If we've already chewed up all the C stack, don't call into the
          * error reporter since this may trigger an infinite recursion where
          * the reporter triggers an over-recursion.
          */
         int stackDummy;
         if (!JS_CHECK_STACK_SIZE(GetNativeStackLimit(cx), &stackDummy))
@@ -870,36 +872,31 @@ js_ReportErrorNumberUCArray(JSContext *c
     ReportError(cx, message, &report, callback, userRef);
 
     js_free(message);
     js_free((void *)report.ucmessage);
 
     return warning;
 }
 
-JS_FRIEND_API(void)
-js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
+void
+js::CallErrorReporter(JSContext *cx, const char *message, JSErrorReport *reportp)
 {
-    JSErrorReporter onError;
-
-    if (!message)
-        return;
+    JS_ASSERT(message);
+    JS_ASSERT(reportp);
 
-    onError = cx->errorReporter;
-
-    /*
-     * If debugErrorHook is present then we give it a chance to veto
-     * sending the error on to the regular ErrorReporter.
-     */
-    if (onError) {
+    // If debugErrorHook is present, give it a chance to veto sending the error
+    // on to the regular ErrorReporter.
+    if (cx->errorReporter) {
         JSDebugErrorHook hook = cx->runtime()->debugHooks.debugErrorHook;
         if (hook && !hook(cx, message, reportp, cx->runtime()->debugHooks.debugErrorHookData))
-            onError = nullptr;
+            return;
     }
-    if (onError)
+
+    if (JSErrorReporter onError = cx->errorReporter)
         onError(cx, message, reportp);
 }
 
 void
 js_ReportIsNotDefined(JSContext *cx, const char *name)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_DEFINED, name);
 }
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -779,24 +779,24 @@ ReportUsageError(JSContext *cx, HandleOb
  * Prints a full report and returns true if the given report is non-nullptr
  * and the report doesn't have the JSREPORT_WARNING flag set or reportWarnings
  * is true.
  * Returns false otherwise, printing just the message if the report is nullptr.
  */
 extern bool
 PrintError(JSContext *cx, FILE *file, const char *message, JSErrorReport *report,
            bool reportWarnings);
-} /* namespace js */
 
 /*
- * Report an exception using a previously composed JSErrorReport.
- * XXXbe remove from "friend" API
+ * Send a JSErrorReport to the errorReporter callback.
  */
-extern JS_FRIEND_API(void)
-js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *report);
+void
+CallErrorReporter(JSContext *cx, const char *message, JSErrorReport *report);
+
+} /* namespace js */
 
 extern void
 js_ReportIsNotDefined(JSContext *cx, const char *name);
 
 /*
  * Report an attempt to access the property of a null or undefined value (v).
  */
 extern bool
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -637,75 +637,72 @@ js::GetErrorTypeName(JSRuntime* rt, int1
     JSProtoKey key = GetExceptionProtoKey(JSExnType(exnType));
     return ClassName(key, rt)->chars();
 }
 
 bool
 js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
                     JSErrorCallback callback, void *userRef)
 {
-    /*
-     * Tell our caller to report immediately if this report is just a warning.
-     */
+    // Tell our caller to report immediately if this report is just a warning.
     JS_ASSERT(reportp);
     if (JSREPORT_IS_WARNING(reportp->flags))
         return false;
 
-    /* Find the exception index associated with this error. */
+    // Find the exception index associated with this error.
     JSErrNum errorNumber = static_cast<JSErrNum>(reportp->errorNumber);
     const JSErrorFormatString *errorString;
     if (!callback || callback == js_GetErrorMessage)
         errorString = js_GetLocalizedErrorMessage(cx, nullptr, nullptr, errorNumber);
     else
         errorString = callback(userRef, nullptr, errorNumber);
     JSExnType exnType = errorString ? static_cast<JSExnType>(errorString->exnType) : JSEXN_NONE;
     MOZ_ASSERT(exnType < JSEXN_LIMIT);
 
-    /*
-     * Return false (no exception raised) if no exception is associated
-     * with the given error number.
-     */
+    // Return false (no exception raised) if no exception is associated
+    // with the given error number.
     if (exnType == JSEXN_NONE)
         return false;
 
-    /* Prevent infinite recursion. */
+    // Prevent infinite recursion.
     if (cx->generatingError)
         return false;
     AutoScopedAssign<bool> asa(&cx->generatingError, true);
 
+    // Create an exception object.
     RootedString messageStr(cx, reportp->ucmessage ? JS_NewUCStringCopyZ(cx, reportp->ucmessage)
                                                    : JS_NewStringCopyZ(cx, message));
     if (!messageStr)
-        return false;
+        return cx->isExceptionPending();
 
     RootedString fileName(cx, JS_NewStringCopyZ(cx, reportp->filename));
     if (!fileName)
-        return false;
+        return cx->isExceptionPending();
 
     uint32_t lineNumber = reportp->lineno;
     uint32_t columnNumber = reportp->column;
 
     RootedString stack(cx, ComputeStackString(cx));
     if (!stack)
-        return false;
+        return cx->isExceptionPending();
 
     js::ScopedJSFreePtr<JSErrorReport> report(CopyErrorReport(cx, reportp));
     if (!report)
-        return false;
+        return cx->isExceptionPending();
 
     RootedObject errObject(cx, ErrorObject::create(cx, exnType, stack, fileName,
-                                                   lineNumber, columnNumber, &report,
-                                                   messageStr));
+                                                   lineNumber, columnNumber, &report, messageStr));
     if (!errObject)
-        return false;
+        return cx->isExceptionPending();
 
+    // Throw it.
     RootedValue errValue(cx, ObjectValue(*errObject));
     JS_SetPendingException(cx, errValue);
 
-    /* Flag the error report passed in to indicate an exception was raised. */
+    // Flag the error report passed in to indicate an exception was raised.
     reportp->flags |= JSREPORT_EXCEPTION;
     return true;
 }
 
 static bool
 IsDuckTypedErrorObject(JSContext *cx, HandleObject exnObject, const char **filename_strp)
 {
     bool found;
@@ -833,17 +830,17 @@ js_ReportUncaughtException(JSContext *cx
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                              JSMSG_UNCAUGHT_EXCEPTION, bytes);
     } else {
         /* Flag the error as an exception. */
         reportp->flags |= JSREPORT_EXCEPTION;
 
         /* Pass the exception object. */
         JS_SetPendingException(cx, exn);
-        js_ReportErrorAgain(cx, bytes, reportp);
+        CallErrorReporter(cx, bytes, reportp);
     }
 
     JS_ClearPendingException(cx);
     return true;
 }
 
 JSObject *
 js_CopyErrorObject(JSContext *cx, Handle<ErrorObject*> err, HandleObject scope)
--- a/js/src/jsexn.h
+++ b/js/src/jsexn.h
@@ -18,18 +18,36 @@ namespace js {
 class ErrorObject;
 }
 
 /*
  * Given a JSErrorReport, check to see if there is an exception associated with
  * the error number.  If there is, then create an appropriate exception object,
  * set it as the pending exception, and set the JSREPORT_EXCEPTION flag on the
  * error report.  Exception-aware host error reporters should probably ignore
- * error reports so flagged.  Returns true if an associated exception is
- * found and set, false otherwise.
+ * error reports so flagged.
+ *
+ * Return true if cx->throwing and cx->exception were set.
+ *
+ * This means that:
+ *
+ *   - If the error is successfully converted to an exception and stored in
+ *     cx->exception, the return value is true. This is the "normal", happiest
+ *     case for the caller.
+ *
+ *   - If we try to convert, but fail with OOM or some other error that ends up
+ *     setting cx->throwing to true and setting cx->exception, then we also
+ *     return true (because callers want to treat that case the same way).
+ *     The original error described by *reportp typically won't be reported
+ *     anywhere; instead OOM is reported.
+ *
+ *   - If *reportp is just a warning, or the error code is unrecognized, or if
+ *     we decided to do nothing in order to avoid recursion, then return
+ *     false. In those cases, this error is just being swept under the rug
+ *     unless the caller decides to call CallErrorReporter explicitly.
  */
 extern bool
 js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
                     JSErrorCallback callback, void *userRef);
 
 /*
  * Called if a JS API call to js_Execute or js_InternalCall fails; calls the
  * error reporter with the error report associated with any uncaught exception
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3207,41 +3207,16 @@ PurgeScopeChainHelper(ExclusiveContext *
 static inline bool
 PurgeScopeChain(ExclusiveContext *cx, JS::HandleObject obj, JS::HandleId id)
 {
     if (obj->isDelegate())
         return PurgeScopeChainHelper(cx, obj, id);
     return true;
 }
 
-Shape *
-js_AddNativeProperty(JSContext *cx, HandleObject obj, HandleId id,
-                     PropertyOp getter, StrictPropertyOp setter, uint32_t slot,
-                     unsigned attrs, unsigned flags, int shortid)
-{
-    /*
-     * Purge the property cache of now-shadowed id in obj's scope chain. Do
-     * this optimistically (assuming no failure below) before locking obj, so
-     * we can lock the shadowed scope.
-     */
-    if (!PurgeScopeChain(cx, obj, id))
-        return nullptr;
-
-    Shape *shape =
-        JSObject::putProperty<SequentialExecution>(cx, obj, id, getter, setter, slot,
-                                                   attrs, flags, shortid);
-    if (!shape)
-        return shape;
-
-    if (JSID_IS_INT(id))
-        JSObject::removeDenseElementForSparseIndex(cx, obj, JSID_TO_INT(id));
-
-    return shape;
-}
-
 bool
 baseops::DefineGeneric(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value,
                        PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     return DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, 0, 0);
 }
 
 /* static */ bool
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1321,25 +1321,16 @@ js_IdentifyClassPrototype(JSObject *obj)
 /*
  * If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is
  * JSProto_Null, clasp must non-null.
  */
 bool
 js_FindClassObject(js::ExclusiveContext *cx, JSProtoKey protoKey, js::MutableHandleValue vp,
                    const js::Class *clasp = nullptr);
 
-/*
- * Find or create a property named by id in obj's scope, with the given getter
- * and setter, slot, attributes, and other members.
- */
-extern js::Shape *
-js_AddNativeProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
-                     JSPropertyOp getter, JSStrictPropertyOp setter, uint32_t slot,
-                     unsigned attrs, unsigned flags, int shortid);
-
 namespace js {
 
 extern bool
 DefineOwnProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
                   JS::HandleValue descriptor, bool *bp);
 
 extern bool
 DefineOwnProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
--- a/js/src/jsopcode.tbl
+++ b/js/src/jsopcode.tbl
@@ -268,21 +268,17 @@ OPDEF(JSOP_CONDSWITCH,120,"condswitch", 
 OPDEF(JSOP_CASE,      121,"case",       NULL,         5,  2,  1,  JOF_JUMP)
 OPDEF(JSOP_DEFAULT,   122,"default",    NULL,         5,  1,  0,  JOF_JUMP)
 
 /*
  * ECMA-compliant call to eval op
  */
 OPDEF(JSOP_EVAL,      123,"eval",       NULL,         3, -1,  1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET)
 
-/*
- * ECMA-compliant helper for 'for (x[i] in o)' loops.
- */
-OPDEF(JSOP_ENUMELEM,  124,"enumelem",   NULL,         1,  3,  0,  JOF_BYTE |JOF_SET|JOF_TMPSLOT)
-
+OPDEF(JSOP_UNUSED124,  124, "unused124", NULL,      1,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED125,  125, "unused125", NULL,      1,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED126,  126, "unused126", NULL,      1,  0,  0,  JOF_BYTE)
 
 /*
  * Prolog bytecodes for defining function, var, and const names.
  */
 OPDEF(JSOP_DEFFUN,    127,"deffun",     NULL,         5,  0,  0,  JOF_OBJECT)
 OPDEF(JSOP_DEFCONST,  128,"defconst",   NULL,         5,  0,  0,  JOF_ATOM)
@@ -440,25 +436,18 @@ OPDEF(JSOP_UNUSED201,     201,"unused201
 
 /*
  * Generator and array comprehension support.
  */
 OPDEF(JSOP_GENERATOR,     202,"generator",   NULL,    1,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_YIELD,         203,"yield",       NULL,    1,  1,  1,  JOF_BYTE)
 OPDEF(JSOP_ARRAYPUSH,     204,"arraypush",   NULL,    3,  1,  0,  JOF_LOCAL)
 
-/*
- * Get the built-in function::foo namespace and push it.
- */
-OPDEF(JSOP_GETFUNNS,      205,"getfunns",   NULL,     1,  0,  1,  JOF_BYTE)
-
-/*
- * Variant of JSOP_ENUMELEM for destructuring const (const [a, b] = ...).
- */
-OPDEF(JSOP_ENUMCONSTELEM, 206,"enumconstelem",NULL,   1,  3,  0,  JOF_BYTE|JOF_SET)
+OPDEF(JSOP_UNUSED205,     205, "unused205",    NULL,  1,  0,  0,  JOF_BYTE)
+OPDEF(JSOP_UNUSED206,     206, "unused206",    NULL,  1,  0,  0,  JOF_BYTE)
 
 OPDEF(JSOP_UNUSED207,     207, "unused207",    NULL,  1,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED208,     208, "unused208",    NULL,  1,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED209,     209, "unused209",    NULL,  1,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED210,     210, "unused210",    NULL,  1,  0,  0,  JOF_BYTE)
 
 OPDEF(JSOP_CALLGNAME,     211, "callgname",    NULL,  5,  0,  1,  JOF_ATOM|JOF_NAME|JOF_TYPESET|JOF_GNAME)
 OPDEF(JSOP_CALLLOCAL,     212, "calllocal",    NULL,  3,  0,  1,  JOF_LOCAL|JOF_NAME)
--- a/js/src/vm/ErrorObject.h
+++ b/js/src/vm/ErrorObject.h
@@ -72,18 +72,20 @@ class ErrorObject : public JSObject
            uint32_t lineNumber, uint32_t columnNumber, ScopedJSFreePtr<JSErrorReport> *report,
            HandleString message);
 
     JSExnType type() const {
         return JSExnType(getReservedSlot(EXNTYPE_SLOT).toInt32());
     }
 
     JSErrorReport * getErrorReport() const {
-        void *priv = getReservedSlot(ERROR_REPORT_SLOT).toPrivate();
-        return static_cast<JSErrorReport*>(priv);
+        const Value &slot = getReservedSlot(ERROR_REPORT_SLOT);
+        if (slot.isUndefined())
+            return nullptr;
+        return static_cast<JSErrorReport*>(slot.toPrivate());
     }
 
     JSString * fileName() const {
         return getReservedSlot(FILENAME_SLOT).toString();
     }
 
     uint32_t lineNumber() const {
         return getReservedSlot(LINENUMBER_SLOT).toInt32();
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1598,16 +1598,17 @@ CASE(JSOP_UNUSED50)
 CASE(JSOP_UNUSED51)
 CASE(JSOP_UNUSED52)
 CASE(JSOP_UNUSED101)
 CASE(JSOP_UNUSED102)
 CASE(JSOP_UNUSED103)
 CASE(JSOP_UNUSED104)
 CASE(JSOP_UNUSED105)
 CASE(JSOP_UNUSED107)
+CASE(JSOP_UNUSED124)
 CASE(JSOP_UNUSED125)
 CASE(JSOP_UNUSED126)
 CASE(JSOP_UNUSED132)
 CASE(JSOP_UNUSED139)
 CASE(JSOP_UNUSED140)
 CASE(JSOP_UNUSED141)
 CASE(JSOP_UNUSED142)
 CASE(JSOP_UNUSED147)
@@ -1646,17 +1647,18 @@ CASE(JSOP_UNUSED186)
 CASE(JSOP_UNUSED187)
 CASE(JSOP_UNUSED189)
 CASE(JSOP_UNUSED190)
 CASE(JSOP_UNUSED191)
 CASE(JSOP_UNUSED192)
 CASE(JSOP_UNUSED194)
 CASE(JSOP_UNUSED196)
 CASE(JSOP_UNUSED201)
-CASE(JSOP_GETFUNNS)
+CASE(JSOP_UNUSED205)
+CASE(JSOP_UNUSED206)
 CASE(JSOP_UNUSED207)
 CASE(JSOP_UNUSED208)
 CASE(JSOP_UNUSED209)
 CASE(JSOP_UNUSED210)
 CASE(JSOP_UNUSED219)
 CASE(JSOP_UNUSED220)
 CASE(JSOP_UNUSED221)
 CASE(JSOP_UNUSED222)
@@ -2007,36 +2009,16 @@ CASE(JSOP_SETCONST)
     RootedObject &obj = rootObject0;
     obj = &REGS.fp()->varObj();
 
     if (!SetConstOperation(cx, obj, name, rval))
         goto error;
 }
 END_CASE(JSOP_SETCONST);
 
-#if JS_HAS_DESTRUCTURING
-CASE(JSOP_ENUMCONSTELEM)
-{
-    RootedValue &rval = rootValue0;
-    rval = REGS.sp[-3];
-
-    RootedObject &obj = rootObject0;
-    FETCH_OBJECT(cx, -2, obj);
-    RootedId &id = rootId0;
-    FETCH_ELEMENT_ID(-1, id);
-    if (!JSObject::defineGeneric(cx, obj, id, rval,
-                                 JS_PropertyStub, JS_StrictPropertyStub,
-                                 JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) {
-        goto error;
-    }
-    REGS.sp -= 3;
-}
-END_CASE(JSOP_ENUMCONSTELEM)
-#endif
-
 CASE(JSOP_BINDGNAME)
     PUSH_OBJECT(REGS.fp()->global());
 END_CASE(JSOP_BINDGNAME)
 
 CASE(JSOP_BINDINTRINSIC)
     PUSH_OBJECT(*cx->global()->intrinsicsHolder());
 END_CASE(JSOP_BINDINTRINSIC)
 
@@ -2491,32 +2473,16 @@ CASE(JSOP_SETELEM)
     Value &value = REGS.sp[-1];
     if (!SetObjectElementOperation(cx, obj, id, value, script->strict()))
         goto error;
     REGS.sp[-3] = value;
     REGS.sp -= 2;
 }
 END_CASE(JSOP_SETELEM)
 
-CASE(JSOP_ENUMELEM)
-{
-    RootedObject &obj = rootObject0;
-    RootedValue &rval = rootValue0;
-
-    /* Funky: the value to set is under the [obj, id] pair. */
-    FETCH_OBJECT(cx, -2, obj);
-    RootedId &id = rootId0;
-    FETCH_ELEMENT_ID(-1, id);
-    rval = REGS.sp[-3];
-    if (!JSObject::setGeneric(cx, obj, obj, id, &rval, script->strict()))
-        goto error;
-    REGS.sp -= 3;
-}
-END_CASE(JSOP_ENUMELEM)
-
 CASE(JSOP_EVAL)
 {
     CallArgs args = CallArgsFromSp(GET_ARGC(REGS.pc), REGS.sp);
     if (REGS.fp()->scopeChain()->global().valueIsEval(args.calleev())) {
         if (!DirectEval(cx, args))
             goto error;
     } else {
         if (!Invoke(cx, args))
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -644,16 +644,18 @@ RegExpCompartment::~RegExpCompartment()
 HeapPtrObject &
 RegExpCompartment::getOrCreateMatchResultTemplateObject(JSContext *cx)
 {
     if (matchResultTemplateObject_)
         return matchResultTemplateObject_;
 
     /* Create template array object */
     RootedObject templateObject(cx, NewDenseUnallocatedArray(cx, 0, nullptr, TenuredObject));
+    if (!templateObject)
+        return matchResultTemplateObject_; // = nullptr
 
     /* Set dummy index property */
     RootedValue index(cx, Int32Value(0));
     if (!baseops::DefineProperty(cx, templateObject, cx->names().index, index,
                                  JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE))
         return matchResultTemplateObject_; // = nullptr
 
     /* Set dummy input property */
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -17,17 +17,17 @@ namespace js {
  * Bytecode version number. Increment the subtrahend whenever JS bytecode
  * changes incompatibly.
  *
  * This version number is XDR'd near the front of xdr bytecode and
  * aborts deserialization if there is a mismatch between the current
  * and saved versions. If deserialization fails, the data should be
  * invalidated if possible.
  */
-static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 157);
+static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 158);
 
 class XDRBuffer {
   public:
     XDRBuffer(JSContext *cx)
       : context(cx), base(nullptr), cursor(nullptr), limit(nullptr) { }
 
     JSContext *cx() const {
         return context;
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -40,17 +40,17 @@
 #include "nsEventListenerManager.h"
 #include "prenv.h"
 #include "nsObjectFrame.h"
 #include "nsTransitionManager.h"
 #include "nsAnimationManager.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/Element.h"
 #include "nsIMessageManager.h"
-#include "nsDOMMediaQueryList.h"
+#include "mozilla/dom/MediaQueryList.h"
 #include "nsSMILAnimationController.h"
 #include "mozilla/css/ImageLoader.h"
 #include "mozilla/dom/TabChild.h"
 #include "nsRefreshDriver.h"
 #include "Layers.h"
 #include "nsIDOMEvent.h"
 
 #include "nsContentUtils.h"
@@ -340,17 +340,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventManager);
   // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLanguage); // an atom
 
   // We own only the items in mDOMMediaQueryLists that have listeners;
   // this reference is managed by their AddListener and RemoveListener
   // methods.
   for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists);
        l != &tmp->mDOMMediaQueryLists; l = PR_NEXT_LINK(l)) {
-    nsDOMMediaQueryList *mql = static_cast<nsDOMMediaQueryList*>(l);
+    MediaQueryList *mql = static_cast<MediaQueryList*>(l);
     if (mql->HasListeners()) {
       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDOMMediaQueryLists item");
       cb.NoteXPCOMChild(mql);
     }
   }
 
   // NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTheme); // a service
   // NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLangService); // a service
@@ -369,17 +369,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   }
 
   // We own only the items in mDOMMediaQueryLists that have listeners;
   // this reference is managed by their AddListener and RemoveListener
   // methods.
   for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists);
        l != &tmp->mDOMMediaQueryLists; ) {
     PRCList *next = PR_NEXT_LINK(l);
-    nsDOMMediaQueryList *mql = static_cast<nsDOMMediaQueryList*>(l);
+    MediaQueryList *mql = static_cast<MediaQueryList*>(l);
     mql->RemoveAllListeners();
     l = next;
   }
 
   // NS_RELEASE(tmp->mLanguage); // an atom
 
   // NS_IMPL_CYCLE_COLLECTION_UNLINK(mTheme); // a service
   // NS_IMPL_CYCLE_COLLECTION_UNLINK(mLangService); // a service
@@ -1837,33 +1837,40 @@ nsPresContext::MediaFeatureValuesChanged
     // we hold strong pointers to everything we're going to make
     // notification calls to, since each notification involves calling
     // arbitrary script that might otherwise destroy these objects, or,
     // for that matter, |this|.
     //
     // Note that we intentionally send the notifications to media query
     // list in the order they were created and, for each list, to the
     // listeners in the order added.
-    nsDOMMediaQueryList::NotifyList notifyList;
+    MediaQueryList::NotifyList notifyList;
     for (PRCList *l = PR_LIST_HEAD(&mDOMMediaQueryLists);
          l != &mDOMMediaQueryLists; l = PR_NEXT_LINK(l)) {
-      nsDOMMediaQueryList *mql = static_cast<nsDOMMediaQueryList*>(l);
+      MediaQueryList *mql = static_cast<MediaQueryList*>(l);
       mql->MediumFeaturesChanged(notifyList);
     }
 
     if (!notifyList.IsEmpty()) {
       nsPIDOMWindow *win = mDocument->GetInnerWindow();
       nsCOMPtr<EventTarget> et = do_QueryInterface(win);
       nsCxPusher pusher;
 
       for (uint32_t i = 0, i_end = notifyList.Length(); i != i_end; ++i) {
         if (pusher.RePush(et)) {
           nsAutoMicroTask mt;
-          nsDOMMediaQueryList::HandleChangeData &d = notifyList[i];
-          d.listener->HandleChange(d.mql);
+          MediaQueryList::HandleChangeData &d = notifyList[i];
+          if (d.listener) {
+            d.listener->HandleChange(d.mql);
+          } else if (d.callback) {
+            ErrorResult result;
+            d.callback->Call(*d.mql, result);
+          } else {
+            MOZ_ASSERT(false, "How come we have no listener or callback?");
+          }
         }
       }
     }
 
     // NOTE:  When |notifyList| goes out of scope, our destructor could run.
   }
 }
 
@@ -1888,21 +1895,20 @@ nsPresContext::HandleMediaFeatureValuesC
 {
   // Null-check mShell in case the shell has been destroyed (and the
   // event is the only thing holding the pres context alive).
   if (mPendingMediaFeatureValuesChanged && mShell) {
     MediaFeatureValuesChanged(eRebuildStyleIfNeeded);
   }
 }
 
-already_AddRefed<nsIDOMMediaQueryList>
+already_AddRefed<MediaQueryList>
 nsPresContext::MatchMedia(const nsAString& aMediaQueryList)
 {
-  nsRefPtr<nsDOMMediaQueryList> result =
-    new nsDOMMediaQueryList(this, aMediaQueryList);
+  nsRefPtr<MediaQueryList> result = new MediaQueryList(this, aMediaQueryList);
 
   // Insert the new item at the end of the linked list.
   PR_INSERT_BEFORE(result, &mDOMMediaQueryLists);
 
   return result.forget();
 }
 
 nsCompatibility
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -67,16 +67,19 @@ class nsTransitionManager;
 class nsAnimationManager;
 class nsIDOMMediaQueryList;
 class nsRefreshDriver;
 class nsIWidget;
 class nsDeviceContext;
 
 namespace mozilla {
 class RestyleManager;
+namespace dom {
+class MediaQueryList;
+}
 namespace layers {
 class ContainerLayer;
 }
 }
 
 // supported values for cached bool types
 enum nsPresContext_CachedBoolPrefType {
   kPresContext_UseDocumentColors = 1,
@@ -264,17 +267,17 @@ public:
   void FlushPendingMediaFeatureValuesChanged() {
     if (mPendingMediaFeatureValuesChanged)
       MediaFeatureValuesChanged(eRebuildStyleIfNeeded);
   }
 
   /**
    * Support for window.matchMedia()
    */
-  already_AddRefed<nsIDOMMediaQueryList>
+  already_AddRefed<mozilla::dom::MediaQueryList>
     MatchMedia(const nsAString& aMediaQueryList);
 
   /**
    * Access compatibility mode for this context.  This is the same as
    * our document's compatibility mode.
    */
   nsCompatibility CompatibilityMode() const;
 
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -2746,18 +2746,18 @@ static int32_t FindChar(const nsTextFrag
 
 static bool IsChineseOrJapanese(nsIFrame* aFrame)
 {
   nsIAtom* language = aFrame->StyleFont()->mLanguage;
   if (!language) {
     return false;
   }
   const PRUnichar *lang = language->GetUTF16String();
-  return (!nsCRT::strncmp(lang, NS_LITERAL_STRING("ja").get(), 2) ||
-          !nsCRT::strncmp(lang, NS_LITERAL_STRING("zh").get(), 2)) &&
+  return (!nsCRT::strncmp(lang, MOZ_UTF16("ja"), 2) ||
+          !nsCRT::strncmp(lang, MOZ_UTF16("zh"), 2)) &&
          (language->GetLength() == 2 || lang[2] == '-');
 }
 
 #ifdef DEBUG
 static bool IsInBounds(const gfxSkipCharsIterator& aStart, int32_t aContentLength,
                          uint32_t aOffset, uint32_t aLength) {
   if (aStart.GetSkippedOffset() > aOffset)
     return false;
--- a/layout/printing/nsPrintData.cpp
+++ b/layout/printing/nsPrintData.cpp
@@ -51,17 +51,17 @@ nsPrintData::nsPrintData(ePrintDataType 
 {
   MOZ_COUNT_CTOR(nsPrintData);
   nsCOMPtr<nsIStringBundle> brandBundle;
   nsCOMPtr<nsIStringBundleService> svc =
     mozilla::services::GetStringBundleService();
   if (svc) {
     svc->CreateBundle( "chrome://branding/locale/brand.properties", getter_AddRefs( brandBundle ) );
     if (brandBundle) {
-      brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(), &mBrandName );
+      brandBundle->GetStringFromName(MOZ_UTF16("brandShortName"), &mBrandName );
     }
   }
 
   if (!mBrandName) {
     mBrandName = ToNewUnicode(NS_LITERAL_STRING("Mozilla Document"));
   }
 
 }
--- a/layout/style/ErrorReporter.cpp
+++ b/layout/style/ErrorReporter.cpp
@@ -322,34 +322,34 @@ ErrorReporter::ReportUnexpectedEOF(const
   if (!ShouldReportErrors()) return;
 
   nsAutoString innerStr;
   sStringBundle->GetStringFromName(NS_ConvertASCIItoUTF16(aMessage).get(),
                                    getter_Copies(innerStr));
   const PRUnichar *params[1] = { innerStr.get() };
 
   nsAutoString str;
-  sStringBundle->FormatStringFromName(NS_LITERAL_STRING("PEUnexpEOF2").get(),
+  sStringBundle->FormatStringFromName(MOZ_UTF16("PEUnexpEOF2"),
                                       params, ArrayLength(params),
                                       getter_Copies(str));
   AddToError(str);
 }
 
 void
 ErrorReporter::ReportUnexpectedEOF(PRUnichar aExpected)
 {
   if (!ShouldReportErrors()) return;
 
   const PRUnichar expectedStr[] = {
     PRUnichar('\''), aExpected, PRUnichar('\''), PRUnichar(0)
   };
   const PRUnichar *params[1] = { expectedStr };
 
   nsAutoString str;
-  sStringBundle->FormatStringFromName(NS_LITERAL_STRING("PEUnexpEOF2").get(),
+  sStringBundle->FormatStringFromName(MOZ_UTF16("PEUnexpEOF2"),
                                       params, ArrayLength(params),
                                       getter_Copies(str));
   AddToError(str);
 }
 
 } // namespace css
 } // namespace mozilla
 
rename from layout/style/nsDOMMediaQueryList.cpp
rename to layout/style/MediaQueryList.cpp
--- a/layout/style/nsDOMMediaQueryList.cpp
+++ b/layout/style/MediaQueryList.cpp
@@ -1,89 +1,103 @@
 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
 /* 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/. */
 
 /* implements DOM interface for querying and observing media queries */
 
-#include "nsDOMMediaQueryList.h"
+#include "mozilla/dom/MediaQueryList.h"
 #include "nsPresContext.h"
 #include "nsIMediaList.h"
 #include "nsCSSParser.h"
-#include "nsDOMClassInfoID.h" // DOMCI_DATA
+#include "nsIDocument.h"
 
-nsDOMMediaQueryList::nsDOMMediaQueryList(nsPresContext *aPresContext,
-                                         const nsAString &aMediaQueryList)
+namespace mozilla {
+namespace dom {
+
+MediaQueryList::MediaQueryList(nsPresContext *aPresContext,
+                               const nsAString &aMediaQueryList)
   : mPresContext(aPresContext),
     mMediaList(new nsMediaList),
     mMatchesValid(false)
 {
   PR_INIT_CLIST(this);
 
+  SetIsDOMBinding();
+
   nsCSSParser parser;
   parser.ParseMediaList(aMediaQueryList, nullptr, 0, mMediaList, false);
 }
 
-nsDOMMediaQueryList::~nsDOMMediaQueryList()
+MediaQueryList::~MediaQueryList()
 {
   if (mPresContext) {
     PR_REMOVE_LINK(this);
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMMediaQueryList)
+NS_IMPL_CYCLE_COLLECTION_CLASS(MediaQueryList)
 
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMMediaQueryList)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresContext)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListeners)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(MediaQueryList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresContext)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListeners)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallbacks)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMMediaQueryList)
-if (tmp->mPresContext) {
-  PR_REMOVE_LINK(tmp);
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPresContext)
-}
-tmp->RemoveAllListeners();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MediaQueryList)
+  if (tmp->mPresContext) {
+    PR_REMOVE_LINK(tmp);
+    NS_IMPL_CYCLE_COLLECTION_UNLINK(mPresContext)
+  }
+  tmp->RemoveAllListeners();
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-DOMCI_DATA(MediaQueryList, nsDOMMediaQueryList)
+NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(MediaQueryList)
 
-NS_INTERFACE_MAP_BEGIN(nsDOMMediaQueryList)
+NS_INTERFACE_MAP_BEGIN(MediaQueryList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMMediaQueryList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDOMMediaQueryList)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MediaQueryList)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(MediaQueryList)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMMediaQueryList)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMMediaQueryList)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaQueryList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaQueryList)
 
 NS_IMETHODIMP
-nsDOMMediaQueryList::GetMedia(nsAString &aMedia)
+MediaQueryList::GetMedia(nsAString &aMedia)
 {
   mMediaList->GetText(aMedia);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMMediaQueryList::GetMatches(bool *aMatches)
+MediaQueryList::GetMatches(bool *aMatches)
+{
+  *aMatches = Matches();
+  return NS_OK;
+}
+
+bool
+MediaQueryList::Matches()
 {
   if (!mMatchesValid) {
     NS_ABORT_IF_FALSE(!HasListeners(),
                       "when listeners present, must keep mMatches current");
     RecomputeMatches();
   }
 
-  *aMatches = mMatches;
-  return NS_OK;
+  return mMatches;
 }
 
 NS_IMETHODIMP
-nsDOMMediaQueryList::AddListener(nsIDOMMediaQueryListListener *aListener)
+MediaQueryList::AddListener(nsIDOMMediaQueryListListener *aListener)
 {
   if (!aListener) {
     return NS_OK;
   }
 
   if (!HasListeners()) {
     // When we have listeners, the pres context owns a reference to
     // this.  This is a cyclic reference that can only be broken by
@@ -102,64 +116,135 @@ nsDOMMediaQueryList::AddListener(nsIDOMM
     if (!HasListeners()) {
       // Append failed; undo the AddRef above.
       NS_RELEASE_THIS();
     }
   }
   return NS_OK;
 }
 
+void
+MediaQueryList::AddListener(MediaQueryListListener& aListener)
+{
+  if (!HasListeners()) {
+    // When we have listeners, the pres context owns a reference to
+    // this.  This is a cyclic reference that can only be broken by
+    // cycle collection.
+    NS_ADDREF_THIS();
+  }
+
+  if (!mMatchesValid) {
+    NS_ABORT_IF_FALSE(!HasListeners(),
+                      "when listeners present, must keep mMatches current");
+    RecomputeMatches();
+  }
+
+  for (uint32_t i = 0; i < mCallbacks.Length(); ++i) {
+    if (aListener == *mCallbacks[i]) {
+      // Already registered
+      return;
+    }
+  }
+
+  mCallbacks.AppendElement(&aListener);
+  if (!HasListeners()) {
+    // Append failed; undo the AddRef above.
+    NS_RELEASE_THIS();
+  }
+}
+
 NS_IMETHODIMP
-nsDOMMediaQueryList::RemoveListener(nsIDOMMediaQueryListListener *aListener)
+MediaQueryList::RemoveListener(nsIDOMMediaQueryListListener *aListener)
 {
   bool removed = mListeners.RemoveElement(aListener);
   NS_ABORT_IF_FALSE(!mListeners.Contains(aListener),
                     "duplicate occurrence of listeners");
 
   if (removed && !HasListeners()) {
     // See NS_ADDREF_THIS() in AddListener.
     NS_RELEASE_THIS();
   }
 
   return NS_OK;
 }
 
 void
-nsDOMMediaQueryList::RemoveAllListeners()
+MediaQueryList::RemoveListener(MediaQueryListListener& aListener)
+{
+  for (uint32_t i = 0; i < mCallbacks.Length(); ++i) {
+    if (aListener == *mCallbacks[i]) {
+      mCallbacks.RemoveElementAt(i);
+      if (!HasListeners()) {
+        // See NS_ADDREF_THIS() in AddListener.
+        NS_RELEASE_THIS();
+      }
+      break;
+    }
+  }
+}
+
+void
+MediaQueryList::RemoveAllListeners()
 {
   bool hadListeners = HasListeners();
   mListeners.Clear();
+  mCallbacks.Clear();
   if (hadListeners) {
     // See NS_ADDREF_THIS() in AddListener.
     NS_RELEASE_THIS();
   }
 }
 
 void
-nsDOMMediaQueryList::RecomputeMatches()
+MediaQueryList::RecomputeMatches()
 {
   if (!mPresContext) {
     return;
   }
 
   mMatches = mMediaList->Matches(mPresContext, nullptr);
   mMatchesValid = true;
 }
 
 void
-nsDOMMediaQueryList::MediumFeaturesChanged(NotifyList &aListenersToNotify)
+MediaQueryList::MediumFeaturesChanged(NotifyList &aListenersToNotify)
 {
   mMatchesValid = false;
 
-  if (mListeners.Length()) {
+  if (HasListeners()) {
     bool oldMatches = mMatches;
     RecomputeMatches();
     if (mMatches != oldMatches) {
       for (uint32_t i = 0, i_end = mListeners.Length(); i != i_end; ++i) {
         HandleChangeData *d = aListenersToNotify.AppendElement();
         if (d) {
           d->mql = this;
           d->listener = mListeners[i];
         }
       }
+      for (uint32_t i = 0, i_end = mCallbacks.Length(); i != i_end; ++i) {
+        HandleChangeData *d = aListenersToNotify.AppendElement();
+        if (d) {
+          d->mql = this;
+          d->callback = mCallbacks[i];
+        }
+      }
     }
   }
 }
+
+nsISupports*
+MediaQueryList::GetParentObject() const
+{
+  if (!mPresContext) {
+    return nullptr;
+  }
+  return mPresContext->Document();
+}
+
+JSObject*
+MediaQueryList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return MediaQueryListBinding::Wrap(aCx, aScope, this);
+}
+
+} // namespace dom
+} // namespace mozilla
rename from layout/style/nsDOMMediaQueryList.h
rename to layout/style/MediaQueryList.h
--- a/layout/style/nsDOMMediaQueryList.h
+++ b/layout/style/MediaQueryList.h
@@ -1,61 +1,79 @@
 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
 /* 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/. */
 
 /* implements DOM interface for querying and observing media queries */
 
-#ifndef nsDOMMediaQueryList_h_
-#define nsDOMMediaQueryList_h_
+#ifndef mozilla_dom_MediaQueryList_h
+#define mozilla_dom_MediaQueryList_h
 
 #include "nsIDOMMediaQueryList.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "prclist.h"
 #include "mozilla/Attributes.h"
+#include "nsWrapperCache.h"
+#include "mozilla/dom/MediaQueryListBinding.h"
 
 class nsPresContext;
 class nsMediaList;
 
-class nsDOMMediaQueryList MOZ_FINAL : public nsIDOMMediaQueryList,
-                                      public PRCList
+namespace mozilla {
+namespace dom {
+
+class MediaQueryList MOZ_FINAL : public nsIDOMMediaQueryList,
+                                 public nsWrapperCache,
+                                 public PRCList
 {
 public:
   // The caller who constructs is responsible for calling Evaluate
   // before calling any other methods.
-  nsDOMMediaQueryList(nsPresContext *aPresContext,
-                      const nsAString &aMediaQueryList);
+  MediaQueryList(nsPresContext *aPresContext,
+                 const nsAString &aMediaQueryList);
 private:
-  ~nsDOMMediaQueryList();
+  ~MediaQueryList();
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMMediaQueryList)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaQueryList)
 
   NS_DECL_NSIDOMMEDIAQUERYLIST
 
+  nsISupports* GetParentObject() const;
+
   struct HandleChangeData {
-    nsRefPtr<nsDOMMediaQueryList> mql;
+    nsRefPtr<MediaQueryList> mql;
     nsCOMPtr<nsIDOMMediaQueryListListener> listener;
+    nsCOMPtr<mozilla::dom::MediaQueryListListener> callback;
   };
 
   typedef FallibleTArray< nsCOMPtr<nsIDOMMediaQueryListListener> > ListenerList;
+  typedef FallibleTArray< nsRefPtr<mozilla::dom::MediaQueryListListener> > CallbackList;
   typedef FallibleTArray<HandleChangeData> NotifyList;
 
   // Appends listeners that need notification to aListenersToNotify
   void MediumFeaturesChanged(NotifyList &aListenersToNotify);
 
-  bool HasListeners() const { return !mListeners.IsEmpty(); }
+  bool HasListeners() const { return !mListeners.IsEmpty() || !mCallbacks.IsEmpty(); }
 
   void RemoveAllListeners();
 
+  JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+  // WebIDL methods
+  // The XPCOM GetMedia method is good
+  bool Matches();
+  void AddListener(mozilla::dom::MediaQueryListListener& aListener);
+  void RemoveListener(mozilla::dom::MediaQueryListListener& aListener);
+
 private:
   void RecomputeMatches();
 
   // We only need a pointer to the pres context to support lazy
   // reevaluation following dynamic changes.  However, this lazy
   // reevaluation is perhaps somewhat important, since some usage
   // patterns may involve the creation of large numbers of
   // MediaQueryList objects which almost immediately become garbage
@@ -69,11 +87,15 @@ private:
   // is equivalent to being in that pres context's mDOMMediaQueryLists
   // linked list.
   nsRefPtr<nsPresContext> mPresContext;
 
   nsRefPtr<nsMediaList> mMediaList;
   bool mMatches;
   bool mMatchesValid;
   ListenerList mListeners;
+  CallbackList mCallbacks;
 };
 
-#endif /* !defined(nsDOMMediaQueryList_h_) */
+} // namespace dom
+} // namespace mozilla
+
+#endif /* !defined(mozilla_dom_MediaQueryList_h) */
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -27,17 +27,16 @@ EXPORTS += [
     'nsCSSPseudoElements.h',
     'nsCSSRuleProcessor.h',
     'nsCSSScanner.h',
     'nsCSSStyleSheet.h',
     'nsCSSValue.h',
     'nsDOMCSSAttrDeclaration.h',
     'nsDOMCSSDeclaration.h',
     'nsDOMCSSRGBColor.h',
-    'nsDOMMediaQueryList.h',
     'nsICSSDeclaration.h',
     'nsICSSLoaderObserver.h',
     'nsICSSPseudoComparator.h',
     'nsICSSRuleList.h',
     'nsICSSStyleRuleDOMWrapper.h',
     'nsIStyleRule.h',
     'nsIStyleRuleProcessor.h',
     'nsIStyleSheet.h',
@@ -62,16 +61,17 @@ EXPORTS.mozilla += [
     'CSSVariableDeclarations.h',
     'CSSVariableResolver.h',
     'CSSVariableValues.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'CSS.h',
     'CSSValue.h',
+    'MediaQueryList.h',
 ]
 
 EXPORTS.mozilla.css += [
     'Declaration.h',
     'ErrorReporter.h',
     'GroupRule.h',
     'ImageLoader.h',
     'ImportRule.h',
@@ -86,16 +86,17 @@ UNIFIED_SOURCES += [
     'CSS.cpp',
     'CSSVariableDeclarations.cpp',
     'CSSVariableResolver.cpp',
     'CSSVariableValues.cpp',
     'Declaration.cpp',
     'ErrorReporter.cpp',
     'ImageLoader.cpp',
     'Loader.cpp',
+    'MediaQueryList.cpp',
     'nsAnimationManager.cpp',
     'nsComputedDOMStyle.cpp',
     'nsCSSAnonBoxes.cpp',
     'nsCSSDataBlock.cpp',
     'nsCSSKeywords.cpp',
     'nsCSSParser.cpp',
     'nsCSSProps.cpp',
     'nsCSSPseudoClasses.cpp',
@@ -104,17 +105,16 @@ UNIFIED_SOURCES += [
     'nsCSSScanner.cpp',
     'nsCSSStyleSheet.cpp',
     'nsCSSValue.cpp',
     'nsDOMCSSAttrDeclaration.cpp',
     'nsDOMCSSDeclaration.cpp',
     'nsDOMCSSRect.cpp',
     'nsDOMCSSRGBColor.cpp',
     'nsDOMCSSValueList.cpp',
-    'nsDOMMediaQueryList.cpp',
     'nsHTMLCSSStyleSheet.cpp',
     'nsHTMLStyleSheet.cpp',
     'nsLayoutStylesheetCache.cpp',
     'nsMediaFeatures.cpp',
     'nsNthIndexCache.cpp',
     'nsROCSSPrimitiveValue.cpp',
     'nsRuleData.cpp',
     'nsRuleNode.cpp',
--- a/layout/style/test/test_media_query_list.html
+++ b/layout/style/test/test_media_query_list.html
@@ -265,24 +265,30 @@ function run() {
   })();
 
   /* Bug 716751: null-dereference crash */
   (function() {
     iframe.style.width = "200px";
     subroot.offsetWidth; // flush layout
 
     var mql = subwin.matchMedia("(min-width: 150px)");
-    mql.addListener(null);
+    SimpleTest.doesThrow(function() {
+      mql.addListener(null);
+    }, "expected an exception");
 
     iframe.style.width = "100px";
     subroot.offsetWidth; // flush layout
     // With the bug, we crash here.  No need for test assertions.
 
-    mql.removeListener(null);
-    mql.removeListener(null);
+    SimpleTest.doesThrow(function() {
+      mql.removeListener(null);
+    }, "expected an exception");
+    SimpleTest.doesThrow(function() {
+      mql.removeListener(null);
+    }, "expected an exception");
   })();
 
   /* Bug 753777: test that things work in a freshly-created iframe */
   (function() {
     var iframe = document.createElement("iframe");
     document.body.appendChild(iframe);
 
     is(iframe.contentWindow.matchMedia("(min-width: 1px)").matches, true,
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -358,34 +358,34 @@ nsTreeBodyFrame::EnsureView()
     }
     nsCOMPtr<nsIBoxObject> box = do_QueryInterface(mTreeBoxObject);
     if (box) {
       nsWeakFrame weakFrame(this);
       nsCOMPtr<nsITreeView> treeView;
       mTreeBoxObject->GetView(getter_AddRefs(treeView));
       if (treeView && weakFrame.IsAlive()) {
         nsXPIDLString rowStr;
-        box->GetProperty(NS_LITERAL_STRING("topRow").get(),
+        box->GetProperty(MOZ_UTF16("topRow"),
                          getter_Copies(rowStr));
         nsAutoString rowStr2(rowStr);
         nsresult error;
         int32_t rowIndex = rowStr2.ToInteger(&error);
 
         // Set our view.
         SetView(treeView);
         ENSURE_TRUE(weakFrame.IsAlive());
 
         // Scroll to the given row.
         // XXX is this optimal if we haven't laid out yet?
         ScrollToRow(rowIndex);
         ENSURE_TRUE(weakFrame.IsAlive());
 
         // Clear out the property info for the top row, but we always keep the
         // view current.
-        box->RemoveProperty(NS_LITERAL_STRING("topRow").get());
+        box->RemoveProperty(MOZ_UTF16("topRow"));
       }
     }
   }
 }
 
 void
 nsTreeBodyFrame::ManageReflowCallback(const nsRect& aRect, nscoord aHorzWidth)
 {
--- a/media/libcubeb/src/cubeb_wasapi.cpp
+++ b/media/libcubeb/src/cubeb_wasapi.cpp
@@ -687,18 +687,16 @@ handle_channel_layout(cubeb_stream * stm
     assert(closest_pcm->SubFormat == format_pcm->SubFormat);
     CoTaskMemFree(*mix_format);
     *mix_format = closest;
   } else if (hr == AUDCLNT_E_UNSUPPORTED_FORMAT) {
     /* Not supported, no suggestion, there is a bug somewhere. */
     assert(false && "Format not supported, and no suggestion from WASAPI.");
   } else if (hr == S_OK) {
     LOG("Requested format accepted by WASAPI.");
-  } else {
-    assert(false && "Not reached.");
   }
 }
 
 int
 wasapi_stream_init(cubeb * context, cubeb_stream ** stream,
                    char const * stream_name, cubeb_stream_params stream_params,
                    unsigned int latency, cubeb_data_callback data_callback,
                    cubeb_state_callback state_callback, void * user_ptr)
--- a/mobile/android/base/tests/testMasterPassword.java
+++ b/mobile/android/base/tests/testMasterPassword.java
@@ -179,34 +179,43 @@ public class testMasterPassword extends 
         mAsserter.ok(mSolo.waitForText("Browser Blank Page 01"), "Waiting for blank browser page after exiting settings", "Blank browser page present");
     }
 
     public void verifyLoginPage(String password, String badPassword) {
         String LOGIN_URL = getAbsoluteUrl("/robocop/robocop_login.html");
         String option [] = {"Save", "Don't save"};
 
         doorhangerDisplayed(LOGIN_URL);// Check that the doorhanger is displayed
+
+        // TODO: Remove this hack -- see bug 915449
+        mSolo.sleep(2000);
+
         for (String item:option) {
             if (item.equals("Save")) {
-                mAsserter.ok(mSolo.waitForText("Save"), "Checking if Save option is present", "Save option is present");
-                mSolo.clickOnButton(item);
+                final String OK_BUTTON_LABEL = "^OK$";
+                final String SAVE_BUTTON_LABEL = "^Save$";
+                mAsserter.ok(mSolo.waitForText(SAVE_BUTTON_LABEL), "Checking if Save option is present", "Save option is present");
+                mSolo.clickOnButton(SAVE_BUTTON_LABEL);
 
                 // Verify that the Master Password isn't deactivated when the password field is empty
                 closeTabletKeyboard();
-                mSolo.clickOnButton("OK");
+                waitForText(OK_BUTTON_LABEL);
+                mSolo.clickOnButton(OK_BUTTON_LABEL);
 
                 // Verify that the Master Password isn't deactivated when using the wrong password
                 closeTabletKeyboard();
                 editPasswordField(0, badPassword);
-                mSolo.clickOnButton("OK");
+                waitForText(OK_BUTTON_LABEL);
+                mSolo.clickOnButton(OK_BUTTON_LABEL);
 
                 // Verify that the Master Password is deactivated when using the right password
                 closeTabletKeyboard();
                 editPasswordField(0, password);
-                mSolo.clickOnButton("OK");
+                waitForText(OK_BUTTON_LABEL);
+                mSolo.clickOnButton(OK_BUTTON_LABEL);
 
                 // Verify that the Master Password is triggered once per session
                 noDoorhangerDisplayed(LOGIN_URL);// Check that the doorhanger isn't displayed
             } else {
                 clearPrivateData();
                 doorhangerDisplayed(LOGIN_URL);// Check that the doorhanger is displayed
                 mAsserter.ok(mSolo.waitForText("Don't save"), "Checking if Don't save option is present again", "Don't save option is present again");
                 mSolo.clickOnText("Don't save");
--- a/modules/libpref/src/Preferences.cpp
+++ b/modules/libpref/src/Preferences.cpp
@@ -545,17 +545,17 @@ Preferences::Observe(nsISupports *aSubje
                      const PRUnichar *someData)
 {
   if (XRE_GetProcessType() == GeckoProcessType_Content)
     return NS_ERROR_NOT_AVAILABLE;
 
   nsresult rv = NS_OK;
 
   if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
-    if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
+    if (!nsCRT::strcmp(someData, MOZ_UTF16("shutdown-cleanse"))) {
       if (mCurrentFile) {
         mCurrentFile->Remove(false);
         mCurrentFile = nullptr;
       }
     } else {
       rv = SavePrefFile(nullptr);
     }
   } else if (!strcmp(aTopic, "load-extension-defaults")) {
--- a/netwerk/base/src/nsIOService.cpp
+++ b/netwerk/base/src/nsIOService.cpp
@@ -678,18 +678,18 @@ nsIOService::SetOffline(bool offline)
         mozilla::services::GetObserverService();
 
     NS_ASSERTION(observerService, "The observer service should not be null");
 
     if (XRE_GetProcessType() == GeckoProcessType_Default) {
         if (observerService) {
             (void)observerService->NotifyObservers(nullptr,
                 NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC, offline ? 
-                NS_LITERAL_STRING("true").get() :
-                NS_LITERAL_STRING("false").get());
+                MOZ_UTF16("true") :
+                MOZ_UTF16("false"));
         }
     }
 
     nsIIOService *subject = static_cast<nsIIOService *>(this);
     while (mSetOfflineValue != mOffline) {
         offline = mSetOfflineValue;
 
         if (offline && !mOffline) {
--- a/netwerk/cache2/CacheFile.cpp
+++ b/netwerk/cache2/CacheFile.cpp
@@ -400,16 +400,18 @@ CacheFile::Init(const nsACString &aKey,
                 bool aCreateNew,
                 bool aMemoryOnly,
                 bool aPriority,
                 bool aKeyIsHash,
                 CacheFileListener *aCallback)
 {
   MOZ_ASSERT(!mListener);
   MOZ_ASSERT(!mHandle);
+  MOZ_ASSERT(!(aCreateNew && aKeyIsHash));
+  MOZ_ASSERT(!(aMemoryOnly && aKeyIsHash));
 
   nsresult rv;
 
   mKey = aKey;
   mMemoryOnly = aMemoryOnly;
   mKeyIsHash = aKeyIsHash;
 
   LOG(("CacheFile::Init() [this=%p, key=%s, createNew=%d, memoryOnly=%d, "
@@ -701,16 +703,23 @@ nsresult
 CacheFile::OnMetadataRead(nsresult aResult)
 {
   MOZ_ASSERT(mListener);
 
   LOG(("CacheFile::OnMetadataRead() [this=%p, rv=0x%08x]", this, aResult));
 
   bool isNew = false;
   if (NS_SUCCEEDED(aResult)) {
+    MOZ_ASSERT(!mMetadata->KeyIsHash());
+
+    if (mKeyIsHash) {
+      mMetadata->GetKey(mKey);
+      mKeyIsHash = false;
+    }
+
     mReady = true;
     mDataSize = mMetadata->Offset();
     if (mDataSize == 0 && mMetadata->ElementsSize() == 0) {
       isNew = true;
       mMetadata->MarkDirty();
     }
   }
 
--- a/netwerk/cache2/CacheFileMetadata.cpp
+++ b/netwerk/cache2/CacheFileMetadata.cpp
@@ -97,41 +97,71 @@ CacheFileMetadata::SetHandle(CacheFileHa
   LOG(("CacheFileMetadata::SetHandle() [this=%p, handle=%p]", this, aHandle));
 
   MOZ_ASSERT(!mHandle);
 
   mHandle = aHandle;
 }
 
 nsresult
+CacheFileMetadata::GetKey(nsACString &_retval)
+{
+  _retval = mKey;
+  return NS_OK;
+}
+
+bool
+CacheFileMetadata::KeyIsHash()
+{
+  return mKeyIsHash;
+}
+
+nsresult
 CacheFileMetadata::ReadMetadata(CacheFileMetadataListener *aListener)
 {
   LOG(("CacheFileMetadata::ReadMetadata() [this=%p, listener=%p]", this, aListener));
 
   MOZ_ASSERT(!mListener);
   MOZ_ASSERT(!mHashArray);
   MOZ_ASSERT(!mBuf);
   MOZ_ASSERT(!mWriteBuf);
 
   nsresult rv;
 
   int64_t size = mHandle->FileSize();
   MOZ_ASSERT(size != -1);
 
   if (size == 0) {
+    if (mKeyIsHash) {
+      LOG(("CacheFileMetadata::ReadMetadata() - Filesize == 0, cannot create "
+           "empty metadata since key is a hash. [this=%p]", this));
+
+      CacheFileIOManager::DoomFile(mHandle, nullptr);
+      return NS_ERROR_NOT_AVAILABLE;
+    }
+
     // this is a new entry
     LOG(("CacheFileMetadata::ReadMetadata() - Filesize == 0, creating empty "
          "metadata. [this=%p]", this));
 
     InitEmptyMetadata();
     aListener->OnMetadataRead(NS_OK);
     return NS_OK;
   }
 
   if (size < int64_t(sizeof(CacheFileMetadataHeader) + 2*sizeof(uint32_t))) {
+    if (mKeyIsHash) {
+      LOG(("CacheFileMetadata::ReadMetadata() - File is corrupted, cannot "
+           "create empty metadata since key is a hash. [this=%p, "
+           "filesize=%lld]", this, size));
+
+      CacheFileIOManager::DoomFile(mHandle, nullptr);
+      return NS_ERROR_FILE_CORRUPTED;
+    }
+
     // there must be at least checksum, header and offset
     LOG(("CacheFileMetadata::ReadMetadata() - File is corrupted, creating "
          "empty metadata. [this=%p, filesize=%lld]", this, size));
 
     InitEmptyMetadata();
     aListener->OnMetadataRead(NS_OK);
     return NS_OK;
   }
@@ -148,16 +178,25 @@ CacheFileMetadata::ReadMetadata(CacheFil
   DoMemoryReport(MemoryUsage());
 
   LOG(("CacheFileMetadata::ReadMetadata() - Reading metadata from disk, trying "
        "offset=%lld, filesize=%lld [this=%p]", offset, size, this));
 
   mListener = aListener;
   rv = CacheFileIOManager::Read(mHandle, offset, mBuf, mBufSize, this);
   if (NS_FAILED(rv)) {
+    if (mKeyIsHash) {
+      LOG(("CacheFileMetadata::ReadMetadata() - CacheFileIOManager::Read() "
+           "failed synchronously, cannot create empty metadata since key is "
+           "a hash. [this=%p, rv=0x%08x]", this, rv));
+
+      CacheFileIOManager::DoomFile(mHandle, nullptr);
+      return rv;
+    }
+
     LOG(("CacheFileMetadata::ReadMetadata() - CacheFileIOManager::Read() failed"
          " synchronously, creating empty metadata. [this=%p, rv=0x%08x]",
          this, rv));
 
     mListener = nullptr;
     InitEmptyMetadata();
     aListener->OnMetadataRead(NS_OK);
     return NS_OK;
@@ -170,16 +209,17 @@ nsresult
 CacheFileMetadata::WriteMetadata(uint32_t aOffset,
                                  CacheFileMetadataListener *aListener)
 {
   LOG(("CacheFileMetadata::WriteMetadata() [this=%p, offset=%d, listener=%p]",
        this, aOffset, aListener));
 
   MOZ_ASSERT(!mListener);
   MOZ_ASSERT(!mWriteBuf);
+  MOZ_ASSERT(!mKeyIsHash);
 
   nsresult rv;
 
   mIsDirty = false;
 
   mWriteBuf = static_cast<char *>(moz_xmalloc(sizeof(uint32_t) +
                 mHashCount * sizeof(CacheHashUtils::Hash16_t) +
                 sizeof(CacheFileMetadataHeader) + mKey.Length() + 1 +
@@ -428,44 +468,68 @@ nsresult
 CacheFileMetadata::OnDataRead(CacheFileHandle *aHandle, char *aBuf,
                               nsresult aResult)
 {
   LOG(("CacheFileMetadata::OnDataRead() [this=%p, handle=%p, result=0x%08x]",
        this, aHandle, aResult));
 
   MOZ_ASSERT(mListener);
 
-  nsresult rv;
+  nsresult rv, retval;
   nsCOMPtr<CacheFileMetadataListener> listener;
 
   if (NS_FAILED(aResult)) {
-    LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() failed, "
-         "creating empty metadata. [this=%p, rv=0x%08x]", this, aResult));
+    if (mKeyIsHash) {
+      LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() "
+           "failed, cannot create empty metadata since key is a hash. [this=%p,"
+           " rv=0x%08x]", this, aResult));
 
-    InitEmptyMetadata();
+      CacheFileIOManager::DoomFile(mHandle, nullptr);
+      retval = aResult;
+    }
+    else {
+      LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() failed"
+           ", creating empty metadata. [this=%p, rv=0x%08x]", this, aResult));
+
+      InitEmptyMetadata();
+      retval = NS_OK;
+    }
+
     mListener.swap(listener);
-    listener->OnMetadataRead(NS_OK);
+    listener->OnMetadataRead(retval);
     return NS_OK;
   }
 
   // check whether we have read all necessary data
   uint32_t realOffset = PR_ntohl(*(reinterpret_cast<uint32_t *>(
                                  mBuf + mBufSize - sizeof(uint32_t))));
 
   int64_t size = mHandle->FileSize();
   MOZ_ASSERT(size != -1);
 
   if (realOffset >= size) {
-    LOG(("CacheFileMetadata::OnDataRead() - Invalid realOffset, creating empty "
-         "metadata. [this=%p, realOffset=%d, size=%lld]", this, realOffset,
-         size));
+    if (mKeyIsHash) {
+      LOG(("CacheFileMetadata::OnDataRead() - Invalid realOffset, cannot create"
+           "empty metadata since key is a hash. [this=%p, realOffset=%d, "
+           "size=%lld]", this, realOffset, size));
 
-    InitEmptyMetadata();
+      CacheFileIOManager::DoomFile(mHandle, nullptr);
+      retval = NS_ERROR_FILE_CORRUPTED;
+    }
+    else {
+      LOG(("CacheFileMetadata::OnDataRead() - Invalid realOffset, creating "
+           "empty metadata. [this=%p, realOffset=%d, size=%lld]", this,
+           realOffset, size));
+
+      InitEmptyMetadata();
+      retval = NS_OK;
+    }
+
     mListener.swap(listener);
-    listener->OnMetadataRead(NS_OK);
+    listener->OnMetadataRead(retval);
     return NS_OK;
   }
 
   uint32_t usedOffset = size - mBufSize;
 
   if (realOffset < usedOffset) {
     uint32_t missing = usedOffset - realOffset;
     // we need to read more data
@@ -475,40 +539,65 @@ CacheFileMetadata::OnDataRead(CacheFileH
 
     DoMemoryReport(MemoryUsage());
 
     LOG(("CacheFileMetadata::OnDataRead() - We need to read %d more bytes to "
          "have full metadata. [this=%p]", missing, this));
 
     rv = CacheFileIOManager::Read(mHandle, realOffset, mBuf, missing, this);
     if (NS_FAILED(rv)) {
-      LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() failed"
-           " synchronously, creating empty metadata. [this=%p, rv=0x%08x]",
-           this, rv));
+      if (mKeyIsHash) {
+        LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() "
+             "failed synchronously, cannot create empty metadata since key is "
+             "a hash. [this=%p, rv=0x%08x]", this, rv));
 
-      InitEmptyMetadata();
+        CacheFileIOManager::DoomFile(mHandle, nullptr);
+        retval = rv;
+      }
+      else {
+        LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() "
+             "failed synchronously, creating empty metadata. [this=%p, "
+             "rv=0x%08x]", this, rv));
+
+        InitEmptyMetadata();
+        retval = NS_OK;
+      }
+
       mListener.swap(listener);
-      listener->OnMetadataRead(rv);
+      listener->OnMetadataRead(retval);
       return NS_OK;
     }
 
     return NS_OK;
   }
 
   // We have all data according to offset information at the end of the entry.
   // Try to parse it.
   rv = ParseMetadata(realOffset, realOffset - usedOffset);
   if (NS_FAILED(rv)) {
-    LOG(("CacheFileMetadata::OnDataRead() - Error parsing metadata, creating "
-         "empty metadata. [this=%p]", this));
-    InitEmptyMetadata();
+    if (mKeyIsHash) {
+      LOG(("CacheFileMetadata::OnDataRead() - Error parsing metadata, cannot "
+           "create empty metadata since key is a hash. [this=%p]", this));
+
+      CacheFileIOManager::DoomFile(mHandle, nullptr);
+      retval = rv;
+    }
+    else {
+      LOG(("CacheFileMetadata::OnDataRead() - Error parsing metadata, creating "
+           "empty metadata. [this=%p]", this));
+      InitEmptyMetadata();
+      retval = NS_OK;
+    }
+  }
+  else {
+    retval = NS_OK;
   }
 
   mListener.swap(listener);
-  listener->OnMetadataRead(NS_OK);
+  listener->OnMetadataRead(retval);
 
   return NS_OK;
 }
 
 nsresult
 CacheFileMetadata::OnFileDoomed(CacheFileHandle *aHandle, nsresult aResult)
 {
   MOZ_CRASH("CacheFileMetadata::OnFileDoomed should not be called!");
@@ -577,29 +666,35 @@ CacheFileMetadata::ParseMetadata(uint32_
 
   // check that key ends with \0
   if (mBuf[elementsOffset - 1] != 0) {
     LOG(("CacheFileMetadata::ParseMetadata() - Elements not null terminated. "
          "[this=%p]", this));
     return NS_ERROR_FILE_CORRUPTED;
   }
 
-  if (!mKeyIsHash) {
-    uint32_t keySize = reinterpret_cast<CacheFileMetadataHeader *>(
-                         mBuf + hdrOffset)->mKeySize;
+  nsAutoCString origKey;
+
+  uint32_t keySize = reinterpret_cast<CacheFileMetadataHeader *>(
+                       mBuf + hdrOffset)->mKeySize;
 
+  if (mKeyIsHash) {
+    // get the original key
+    origKey.Assign(mBuf + keyOffset, keySize);
+  }
+  else {
     if (keySize != mKey.Length()) {
-      LOG(("CacheFileMetadata::ParseMetadata() - Key collision (1), key=%s [this=%p]",
-           nsCString(mBuf + keyOffset, keySize).get(), this));
+      LOG(("CacheFileMetadata::ParseMetadata() - Key collision (1), key=%s "
+           "[this=%p]", nsCString(mBuf + keyOffset, keySize).get(), this));
       return NS_ERROR_FILE_CORRUPTED;
     }
 
     if (memcmp(mKey.get(), mBuf + keyOffset, mKey.Length()) != 0) {
-      LOG(("CacheFileMetadata::ParseMetadata() - Key collision (2), key=%s [this=%p]",
-           nsCString(mBuf + keyOffset, keySize).get(), this));
+      LOG(("CacheFileMetadata::ParseMetadata() - Key collision (2), key=%s "
+           "[this=%p]", nsCString(mBuf + keyOffset, keySize).get(), this));
       return NS_ERROR_FILE_CORRUPTED;
     }
   }
 
   // check metadata hash (data from hashesOffset to metaposOffset)
   CacheHashUtils::Hash32_t hash;
   hash = CacheHashUtils::Hash(mBuf + hashesOffset,
                               metaposOffset - hashesOffset);
@@ -627,16 +722,21 @@ CacheFileMetadata::ParseMetadata(uint32_
   memcpy(&mMetaHdr, mBuf + hdrOffset, sizeof(CacheFileMetadataHeader));
   mMetaHdr.mFetchCount++;
   MarkDirty();
 
   mElementsSize = metaposOffset - elementsOffset;
   memmove(mBuf, mBuf + elementsOffset, mElementsSize);
   mOffset = aMetaOffset;
 
+  if (mKeyIsHash) {
+    mKey = origKey;
+    mKeyIsHash = false;
+  }
+
   // TODO: shrink memory if buffer is too big
 
   DoMemoryReport(MemoryUsage());
 
   return NS_OK;
 }
 
 nsresult
--- a/netwerk/cache2/CacheFileMetadata.h
+++ b/netwerk/cache2/CacheFileMetadata.h
@@ -51,16 +51,19 @@ public:
 
   CacheFileMetadata(CacheFileHandle *aHandle,
                     const nsACString &aKey,
                     bool aKeyIsHash);
   CacheFileMetadata(const nsACString &aKey);
 
   void SetHandle(CacheFileHandle *aHandle);
 
+  nsresult GetKey(nsACString &_retval);
+  bool     KeyIsHash();
+
   nsresult ReadMetadata(CacheFileMetadataListener *aListener);
   nsresult WriteMetadata(uint32_t aOffset,
                          CacheFileMetadataListener *aListener);
 
   const char * GetElement(const char *aKey);
   nsresult     SetElement(const char *aKey, const char *aValue);
 
   CacheHashUtils::Hash16_t GetHash(uint32_t aIndex);
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -1558,17 +1558,17 @@ nsCookieService::Observe(nsISupports    
                          const char      *aTopic,
                          const PRUnichar *aData)
 {
   // check the topic
   if (!strcmp(aTopic, "profile-before-change")) {
     // The profile is about to change,
     // or is going away because the application is shutting down.
     if (mDBState && mDBState->dbConn &&
-        !nsCRT::strcmp(aData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
+        !nsCRT::strcmp(aData, MOZ_UTF16("shutdown-cleanse"))) {
       // Clear the cookie db if we're in the default DBState.
       RemoveAll();
     }
 
     // Close the default DB connection and null out our DBStates before
     // changing.
     CloseDBStates();
 
@@ -1651,17 +1651,17 @@ nsCookieService::SetCookieString(nsIURI 
   // The aPrompt argument is deprecated and unused.  Avoid introducing new
   // code that uses this argument by warning if the value is non-null.
   MOZ_ASSERT(!aPrompt);
   if (aPrompt) {
     nsCOMPtr<nsIConsoleService> aConsoleService =
         do_GetService("@mozilla.org/consoleservice;1");
     if (aConsoleService) {
       aConsoleService->LogStringMessage(
-        NS_LITERAL_STRING("Non-null prompt ignored by nsCookieService.").get());
+        MOZ_UTF16("Non-null prompt ignored by nsCookieService."));
     }
   }
   return SetCookieStringCommon(aHostURI, aCookieHeader, nullptr, aChannel,
                                false);
 }
 
 NS_IMETHODIMP
 nsCookieService::SetCookieStringFromHttp(nsIURI     *aHostURI,
@@ -1674,17 +1674,17 @@ nsCookieService::SetCookieStringFromHttp
   // The aPrompt argument is deprecated and unused.  Avoid introducing new
   // code that uses this argument by warning if the value is non-null.
   MOZ_ASSERT(!aPrompt);
   if (aPrompt) {
     nsCOMPtr<nsIConsoleService> aConsoleService =
         do_GetService("@mozilla.org/consoleservice;1");
     if (aConsoleService) {
       aConsoleService->LogStringMessage(
-        NS_LITERAL_STRING("Non-null prompt ignored by nsCookieService.").get());
+        MOZ_UTF16("Non-null prompt ignored by nsCookieService."));
     }
   }
   return SetCookieStringCommon(aHostURI, aCookieHeader, aServerTime, aChannel,
                                true);
 }
 
 nsresult
 nsCookieService::SetCookieStringCommon(nsIURI *aHostURI,
@@ -1860,17 +1860,17 @@ nsCookieService::NotifyThirdParty(nsIURI
                                       topic,
                                       referringHostUTF16.get());
     return;
   } while (0);
 
   // This can fail for a number of reasons, in which kind we fallback to "?"
   mObserverService->NotifyObservers(aHostURI,
                                     topic,
-                                    NS_LITERAL_STRING("?").get());
+                                    MOZ_UTF16("?"));
 }
 
 // notify observers that the cookie list changed. there are five possible
 // values for aData:
 // "deleted" means a cookie was deleted. aSubject is the deleted cookie.
 // "added"   means a cookie was added. aSubject is the added cookie.
 // "changed" means a cookie was altered. aSubject is the new cookie.
 // "cleared" means the entire cookie list was cleared. aSubject is null.
@@ -1959,17 +1959,17 @@ nsCookieService::RemoveAll()
     } else {
       // Recreate the database.
       COOKIE_LOGSTRING(PR_LOG_DEBUG,
         ("RemoveAll(): corruption detected with rv 0x%x", rv));
       HandleCorruptDB(mDefaultDBState);
     }
   }
 
-  NotifyChanged(nullptr, NS_LITERAL_STRING("cleared").get());
+  NotifyChanged(nullptr, MOZ_UTF16("cleared"));
   return NS_OK;
 }
 
 static PLDHashOperator
 COMArrayCallback(nsCookieEntry *aEntry,
                  void          *aArg)
 {
   nsCOMArray<nsICookie> *data = static_cast<nsCOMArray<nsICookie> *>(aArg);
@@ -2085,17 +2085,17 @@ nsCookieService::Remove(const nsACString
     NS_NewURI(getter_AddRefs(uri), host);
 
     if (uri)
       mPermissionService->SetAccess(uri, nsICookiePermission::ACCESS_DENY);
   }
 
   if (cookie) {
     // Everything's done. Notify observers.
-    NotifyChanged(cookie, NS_LITERAL_STRING("deleted").get());
+    NotifyChanged(cookie, MOZ_UTF16("deleted"));
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCookieService::Remove(const nsACString &aHost,
                         const nsACString &aName,
@@ -3019,17 +3019,17 @@ nsCookieService::AddInternal(const nsCoo
       // Remove the old cookie.
       RemoveCookieFromList(matchIter);
 
       // If the new cookie has expired -- i.e. the intent was simply to delete
       // the old cookie -- then we're done.
       if (aCookie->Expiry() <= currentTime) {
         COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader,
           "previously stored cookie was deleted");
-        NotifyChanged(oldCookie, NS_LITERAL_STRING("deleted").get());
+        NotifyChanged(oldCookie, MOZ_UTF16("deleted"));
         return;
       }
 
       // Preserve creation time of cookie for ordering purposes.
       aCookie->SetCreationTime(oldCookie->CreationTime());
     }
 
   } else {
@@ -3070,21 +3070,21 @@ nsCookieService::AddInternal(const nsCoo
   // Add the cookie to the db. We do not supply a params array for batching
   // because this might result in removals and additions being out of order.
   AddCookieToList(aKey, aCookie, mDBState, nullptr);
   COOKIE_LOGSUCCESS(SET_COOKIE, aHostURI, aCookieHeader, aCookie, foundCookie);
 
   // Now that list mutations are complete, notify observers. We do it here
   // because observers may themselves attempt to mutate the list.
   if (purgedList) {
-    NotifyChanged(purgedList, NS_LITERAL_STRING("batch-deleted").get());
+    NotifyChanged(purgedList, MOZ_UTF16("batch-deleted"));
   }
 
-  NotifyChanged(aCookie, foundCookie ? NS_LITERAL_STRING("changed").get()
-                                     : NS_LITERAL_STRING("added").get());
+  NotifyChanged(aCookie, foundCookie ? MOZ_UTF16("changed")
+                                     : MOZ_UTF16("added"));
 }
 
 /******************************************************************************
  * nsCookieService impl:
  * private cookie header parsing functions
  ******************************************************************************/
 
 // The following comment block elucidates the function of ParseAttributes.
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -1480,17 +1480,17 @@ nsHttpChannel::PromptTempRedirect()
             do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
     if (NS_FAILED(rv)) return rv;
 
     nsCOMPtr<nsIStringBundle> stringBundle;
     rv = bundleService->CreateBundle(NECKO_MSGS_URL, getter_AddRefs(stringBundle));
     if (NS_FAILED(rv)) return rv;
 
     nsXPIDLString messageString;
-    rv = stringBundle->GetStringFromName(NS_LITERAL_STRING("RepostFormData").get(), getter_Copies(messageString));
+    rv = stringBundle->GetStringFromName(MOZ_UTF16("RepostFormData"), getter_Copies(messageString));
     // GetStringFromName can return NS_OK and nullptr messageString.
     if (NS_SUCCEEDED(rv) && messageString) {
         bool repost = false;
 
         nsCOMPtr<nsIPrompt> prompt;
         GetCallback(prompt);
         if (!prompt)
             return NS_ERROR_NO_INTERFACE;
--- a/netwerk/streamconv/converters/mozTXTToHTMLConv.cpp
+++ b/netwerk/streamconv/converters/mozTXTToHTMLConv.cpp
@@ -108,32 +108,32 @@ mozTXTToHTMLConv::UnescapeStr(const PRUn
 {
   const PRUnichar * subString = nullptr;
   for (uint32_t i = aStartPos; int32_t(i) - aStartPos < aLength;)
   {
     int32_t remainingChars = i - aStartPos;
     if (aInString[i] == '&')
     {
       subString = &aInString[i];
-      if (!nsCRT::strncmp(subString, NS_LITERAL_STRING("&lt;").get(), MinInt(4, aLength - remainingChars)))
+      if (!nsCRT::strncmp(subString, MOZ_UTF16("&lt;"), MinInt(4, aLength - remainingChars)))
       {
         aOutString.Append(PRUnichar('<'));
         i += 4;
       }
-      else if (!nsCRT::strncmp(subString, NS_LITERAL_STRING("&gt;").get(), MinInt(4, aLength - remainingChars)))
+      else if (!nsCRT::strncmp(subString, MOZ_UTF16("&gt;"), MinInt(4, aLength - remainingChars)))
       {
         aOutString.Append(PRUnichar('>'));
         i += 4;
       }
-      else if (!nsCRT::strncmp(subString, NS_LITERAL_STRING("&amp;").get(), MinInt(5, aLength - remainingChars)))
+      else if (!nsCRT::strncmp(subString, MOZ_UTF16("&amp;"), MinInt(5, aLength - remainingChars)))
       {
         aOutString.Append(PRUnichar('&'));
         i += 5;
       }
-      else if (!nsCRT::strncmp(subString, NS_LITERAL_STRING("&quot;").get(), MinInt(6, aLength - remainingChars)))
+      else if (!nsCRT::strncmp(subString, MOZ_UTF16("&quot;"), MinInt(6, aLength - remainingChars)))
       {
         aOutString.Append(PRUnichar('"'));
         i += 6;
       }
       else
       {
         aOutString += aInString[i];
         i++;
@@ -164,50 +164,50 @@ mozTXTToHTMLConv::CompleteAbbreviatedURL
     {
       aOutString.AssignLiteral("mailto:");
       aOutString += aInString;
     }
   }
   else if (aInString[pos] == '.')
   {
     if (ItMatchesDelimited(aInString, aInLength,
-                           NS_LITERAL_STRING("www.").get(), 4, LT_IGNORE, LT_IGNORE))
+                           MOZ_UTF16("www."), 4, LT_IGNORE, LT_IGNORE))
     {
       aOutString.AssignLiteral("http://");
       aOutString += aInString;
     }
-    else if (ItMatchesDelimited(aInString,aInLength, NS_LITERAL_STRING("ftp.").get(), 4, LT_IGNORE, LT_IGNORE))
+    else if (ItMatchesDelimited(aInString,aInLength, MOZ_UTF16("ftp."), 4, LT_IGNORE, LT_IGNORE))
     { 
       aOutString.AssignLiteral("ftp://");
       aOutString += aInString;
     }
   }
 }
 
 bool
 mozTXTToHTMLConv::FindURLStart(const PRUnichar * aInString, int32_t aInLength,
                                const uint32_t pos, const modetype check,
                                uint32_t& start)
 {
   switch(check)
   { // no breaks, because end of blocks is never reached
   case RFC1738:
   {
-    if (!nsCRT::strncmp(&aInString[MaxInt(pos - 4, 0)], NS_LITERAL_STRING("<URL:").get(), 5))
+    if (!nsCRT::strncmp(&aInString[MaxInt(pos - 4, 0)], MOZ_UTF16("<URL:"), 5))
     {
       start = pos + 1;
       return true;
     }
     else
       return false;
   }
   case RFC2396E:
   {
     nsString temp(aInString, aInLength);
-    int32_t i = pos <= 0 ? kNotFound : temp.RFindCharInSet(NS_LITERAL_STRING("<>\"").get(), pos - 1);
+    int32_t i = pos <= 0 ? kNotFound : temp.RFindCharInSet(MOZ_UTF16("<>\""), pos - 1);
     if (i != kNotFound && (temp[uint32_t(i)] == '<' ||
                            temp[uint32_t(i)] == '"'))
     {
       start = uint32_t(++i);
       return start < pos;
     }
     else
       return false;
@@ -276,17 +276,17 @@ mozTXTToHTMLConv::FindURLEnd(const PRUni
 {
   switch(check)
   { // no breaks, because end of blocks is never reached
   case RFC1738:
   case RFC2396E:
   {
     nsString temp(aInString, aInStringLength);
 
-    int32_t i = temp.FindCharInSet(NS_LITERAL_STRING("<>\"").get(), pos + 1);
+    int32_t i = temp.FindCharInSet(MOZ_UTF16("<>\""), pos + 1);
     if (i != kNotFound && temp[uint32_t(i--)] ==
         (check == RFC1738 || temp[start - 1] == '<' ? '>' : '"'))
     {
       end = uint32_t(i);
       return end > pos;
     }
     return false;
   }
@@ -914,25 +914,25 @@ mozTXTToHTMLConv::GlyphHit(const PRUnich
   {
       aOutputString.AppendLiteral("<span class='moz-txt-formfeed'></span>");
       glyphTextLen = 1;
       return true;
   }
   if (text0 == '+' || text1 == '+')
   {
     if (ItMatchesDelimited(aInString, aInLength,
-                           NS_LITERAL_STRING(" +/-").get(), 4,
+                           MOZ_UTF16(" +/-"), 4,
                            LT_IGNORE, LT_IGNORE))
     {
       aOutputString.AppendLiteral(" &plusmn;");
       glyphTextLen = 4;
       return true;
     }
     if (col0 && ItMatchesDelimited(aInString, aInLength,
-                                   NS_LITERAL_STRING("+/-").get(), 3,
+                                   MOZ_UTF16("+/-"), 3,
                                    LT_IGNORE, LT_IGNORE))
     {
       aOutputString.AppendLiteral("&plusmn;");
       glyphTextLen = 3;
       return true;
     }
   }
 
@@ -1116,48 +1116,48 @@ mozTXTToHTMLConv::ScanTXT(const PRUnicha
         newOffset = &aInString[i-1];
         newLength = aInStringLength - i + 1;
       }
 
       switch (aInString[i]) // Performance increase
       {
       case '*':
         if (StructPhraseHit(newOffset, newLength, i == 0,
-                            NS_LITERAL_STRING("*").get(), 1,
+                            MOZ_UTF16("*"), 1,
                             "b", "class=\"moz-txt-star\"",
                             aOutString, structPhrase_strong))
         {
           i++;
           continue;
         }
         break;
       case '/':
         if (StructPhraseHit(newOffset, newLength, i == 0,
-                            NS_LITERAL_STRING("/").get(), 1,
+                            MOZ_UTF16("/"), 1,
                             "i", "class=\"moz-txt-slash\"",
                             aOutString, structPhrase_italic))
         {
           i++;
           continue;
         }
         break;
       case '_':
         if (StructPhraseHit(newOffset, newLength, i == 0,
-                            NS_LITERAL_STRING("_").get(), 1,
+                            MOZ_UTF16("_"), 1,
                             "span" /* <u> is deprecated */,
                             "class=\"moz-txt-underscore\"",
                             aOutString, structPhrase_underline))
         {
           i++;
           continue;
         }
         break;
       case '|':
         if (StructPhraseHit(newOffset, newLength, i == 0,
-                            NS_LITERAL_STRING("|").get(), 1,
+                            MOZ_UTF16("|"), 1,
                             "code", "class=\"moz-txt-verticalline\"",
                             aOutString, structPhrase_code))
         {
           i++;
           continue;
         }
         break;
       }
--- a/netwerk/streamconv/converters/nsIndexedToHTML.cpp
+++ b/netwerk/streamconv/converters/nsIndexedToHTML.cpp
@@ -532,17 +532,17 @@ nsIndexedToHTML::DoOnStartRequest(nsIReq
     htmlEscSpec.Adopt(nsEscapeHTML2(unEscapeSpec.get(),
                                     unEscapeSpec.Length()));
 
     nsXPIDLString title;
     const PRUnichar* formatTitle[] = {
         htmlEscSpec.get()
     };
 
-    rv = mBundle->FormatStringFromName(NS_LITERAL_STRING("DirTitle").get(),
+    rv = mBundle->FormatStringFromName(MOZ_UTF16("DirTitle"),
                                        formatTitle,
                                        sizeof(formatTitle)/sizeof(PRUnichar*),
                                        getter_Copies(title));
     if (NS_FAILED(rv)) return rv;
 
     // we want to convert string bundle to NCR
     // to ensure they're shown in any charsets
     AppendNonAsciiToNCR(title, buffer);
@@ -589,76 +589,76 @@ nsIndexedToHTML::DoOnStartRequest(nsIReq
     buffer.AppendLiteral("</head>\n<body dir=\"");
     buffer.Append(direction);
     buffer.AppendLiteral("\">\n<h1>");
     
     const PRUnichar* formatHeading[] = {
         htmlEscSpec.get()
     };
 
-    rv = mBundle->FormatStringFromName(NS_LITERAL_STRING("DirTitle").get(),
+    rv = mBundle->FormatStringFromName(MOZ_UTF16("DirTitle"),
                                        formatHeading,
                                        sizeof(formatHeading)/sizeof(PRUnichar*),
                                        getter_Copies(title));
     if (NS_FAILED(rv)) return rv;
     
     AppendNonAsciiToNCR(title, buffer);
     buffer.AppendLiteral("</h1>\n");
 
     if (!parentStr.IsEmpty()) {
         nsXPIDLString parentText;
-        rv = mBundle->GetStringFromName(NS_LITERAL_STRING("DirGoUp").get(),
+        rv = mBundle->GetStringFromName(MOZ_UTF16("DirGoUp"),
                                         getter_Copies(parentText));
         if (NS_FAILED(rv)) return rv;
 
         buffer.AppendLiteral("<p id=\"UI_goUp\"><a class=\"up\" href=\"");
 
         NS_ConvertUTF8toUTF16 utf16ParentStr(parentStr);
         nsString htmlParentStr;
         htmlParentStr.Adopt(nsEscapeHTML2(utf16ParentStr.get(), utf16ParentStr.Length()));
         buffer.Append(htmlParentStr);
         buffer.AppendLiteral("\">");
         AppendNonAsciiToNCR(parentText, buffer);
         buffer.AppendLiteral("</a></p>\n");
     }
 
     if (isSchemeFile) {
         nsXPIDLString showHiddenText;
-        rv = mBundle->GetStringFromName(NS_LITERAL_STRING("ShowHidden").get(),
+        rv = mBundle->GetStringFromName(MOZ_UTF16("ShowHidden"),
                                         getter_Copies(showHiddenText));
         if (NS_FAILED(rv)) return rv;
 
         buffer.AppendLiteral("<p id=\"UI_showHidden\" style=\"display:none\"><label><input type=\"checkbox\" checked onchange=\"updateHidden()\">");
         AppendNonAsciiToNCR(showHiddenText, buffer);
         buffer.AppendLiteral("</label></p>\n");
     }
 
     buffer.AppendLiteral("<table>\n");
 
     nsXPIDLString columnText;
 
     buffer.AppendLiteral(" <thead>\n"
                          "  <tr>\n"
                          "   <th>");
 
-    rv = mBundle->GetStringFromName(NS_LITERAL_STRING("DirColName").get(),
+    rv = mBundle->GetStringFromName(MOZ_UTF16("DirColName"),
                                     getter_Copies(columnText));
     if (NS_FAILED(rv)) return rv;
     AppendNonAsciiToNCR(columnText, buffer);
     buffer.AppendLiteral("</th>\n"
                          "   <th>");
 
-    rv = mBundle->GetStringFromName(NS_LITERAL_STRING("DirColSize").get(),
+    rv = mBundle->GetStringFromName(MOZ_UTF16("DirColSize"),
                                     getter_Copies(columnText));
     if (NS_FAILED(rv)) return rv;
     AppendNonAsciiToNCR(columnText, buffer);
     buffer.AppendLiteral("</th>\n"
                          "   <th colspan=\"2\">");
 
-    rv = mBundle->GetStringFromName(NS_LITERAL_STRING("DirColMTime").get(),
+    rv = mBundle->GetStringFromName(MOZ_UTF16("DirColMTime"),
                                     getter_Copies(columnText));
     if (NS_FAILED(rv)) return rv;
     AppendNonAsciiToNCR(columnText, buffer);
     buffer.AppendLiteral("</th>\n"
                          "  </tr>\n"
                          " </thead>\n");
     buffer.AppendLiteral(" <tbody>\n");
 
@@ -932,17 +932,17 @@ nsIndexedToHTML::OnIndexAvailable(nsIReq
             htmlFileExt.Adopt(nsEscapeHTML2(utf16LocEscaped.get(), utf16LocEscaped.Length()));
             pushBuffer.Append(htmlFileExt);
         } else {
             pushBuffer.AppendLiteral("unknown");
         }
         pushBuffer.AppendLiteral("?size=16\" alt=\"");
 
         nsXPIDLString altText;
-        rv = mBundle->GetStringFromName(NS_LITERAL_STRING("DirFileLabel").get(),
+        rv = mBundle->GetStringFromName(MOZ_UTF16("DirFileLabel"),
                                         getter_Copies(altText));
         if (NS_FAILED(rv)) return rv;
         AppendNonAsciiToNCR(altText, pushBuffer);
         pushBuffer.AppendLiteral("\">");
     }
 
     pushBuffer.Append(escapedShort);
     pushBuffer.AppendLiteral("</a></td>\n <td");
--- a/netwerk/streamconv/converters/nsTXTToHTMLConv.cpp
+++ b/netwerk/streamconv/converters/nsTXTToHTMLConv.cpp
@@ -5,17 +5,17 @@
 
 #include "nsTXTToHTMLConv.h"
 #include "nsEscape.h"
 #include "nsStringStream.h"
 #include "nsAutoPtr.h"
 #include "nsIChannel.h"
 #include <algorithm>
 
-#define TOKEN_DELIMITERS NS_LITERAL_STRING("\t\r\n ").get()
+#define TOKEN_DELIMITERS MOZ_UTF16("\t\r\n ")
 
 // nsISupports methods
 NS_IMPL_ISUPPORTS4(nsTXTToHTMLConv,
                    nsIStreamConverter,
                    nsITXTToHTMLConv,
                    nsIRequestObserver,
                    nsIStreamListener)
 
--- a/parser/html/nsHtml5PlainTextUtils.cpp
+++ b/parser/html/nsHtml5PlainTextUtils.cpp
@@ -26,15 +26,15 @@ nsHtml5PlainTextUtils::NewLinkAttributes
   nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
   NS_ASSERTION(NS_SUCCEEDED(rv) && bundleService, "The bundle service could not be loaded");
   nsCOMPtr<nsIStringBundle> bundle;
   rv = bundleService->CreateBundle("chrome://global/locale/browser.properties",
                                    getter_AddRefs(bundle));
   NS_ASSERTION(NS_SUCCEEDED(rv) && bundle, "chrome://global/locale/browser.properties could not be loaded");
   nsXPIDLString title;
   if (bundle) {
-    bundle->GetStringFromName(NS_LITERAL_STRING("plainText.wordWrap").get(), getter_Copies(title));
+    bundle->GetStringFromName(MOZ_UTF16("plainText.wordWrap"), getter_Copies(title));
   }
 
   nsString* titleCopy = new nsString(title);
   linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_TITLE, titleCopy);
   return linkAttrs;
 }
--- a/parser/htmlparser/tests/mochitest/parser_datreader.js
+++ b/parser/htmlparser/tests/mochitest/parser_datreader.js
@@ -143,20 +143,16 @@ function addLevels(walker, buf, indent) 
             buf += "otherns ";
           }
           buf += walker.currentNode.localName + ">";
           if (walker.currentNode.hasAttributes()) {
             var valuesByName = {};
             var attrs = walker.currentNode.attributes;
             for (var i = 0; i < attrs.length; ++i) {
               var localName = attrs[i].localName;
-              if (localName.indexOf("_moz-") == 0) {
-                // Skip bogus attributes added by the MathML implementation
-                continue;
-              }
               var name;
               var attrNs = attrs[i].namespaceURI;
               if (null == attrNs) {
                 name = localName;
               } else if ("http://www.w3.org/XML/1998/namespace" == attrNs) {
                 name = "xml " + localName;
               } else if ("http://www.w3.org/1999/xlink" == attrNs) {
                 name = "xlink " + localName;
--- a/rdf/base/src/nsRDFContainerUtils.cpp
+++ b/rdf/base/src/nsRDFContainerUtils.cpp
@@ -333,17 +333,17 @@ RDFContainerUtilsImpl::RDFContainerUtils
             gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "nextVal"),
                                      &kRDF_nextVal);
             gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Bag"),
                                      &kRDF_Bag);
             gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Seq"),
                                      &kRDF_Seq);
             gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Alt"),
                                      &kRDF_Alt);
-            gRDFService->GetLiteral(NS_LITERAL_STRING("1").get(), &kOne);
+            gRDFService->GetLiteral(MOZ_UTF16("1"), &kOne);
         }
     }
 }
 
 
 RDFContainerUtilsImpl::~RDFContainerUtilsImpl()
 {
 #ifdef DEBUG_REFS
--- a/rdf/base/src/nsRDFContentSink.cpp
+++ b/rdf/base/src/nsRDFContentSink.cpp
@@ -1386,17 +1386,17 @@ RDFContentSinkImpl::ReinitContainer(nsIR
     // Mega-kludge to deal with the fact that Make[Seq|Alt|Bag] is
     // idempotent, and as such, containers will have state (e.g.,
     // RDF:nextVal) maintained in the graph across loads. This
     // re-initializes each container's RDF:nextVal to '1', and 'marks'
     // the container as such.
     nsresult rv;
 
     nsCOMPtr<nsIRDFLiteral> one;
-    rv = gRDFService->GetLiteral(NS_LITERAL_STRING("1").get(), getter_AddRefs(one));
+    rv = gRDFService->GetLiteral(MOZ_UTF16("1"), getter_AddRefs(one));
     if (NS_FAILED(rv)) return rv;
 
     // Re-initialize the 'nextval' property
     nsCOMPtr<nsIRDFNode> nextval;
     rv = mDataSource->GetTarget(aContainer, kRDF_nextVal, true, getter_AddRefs(nextval));
     if (NS_FAILED(rv)) return rv;
 
     rv = mDataSource->Change(aContainer, kRDF_nextVal, nextval, one);
--- a/rdf/datasource/src/nsFileSystemDataSource.cpp
+++ b/rdf/datasource/src/nsFileSystemDataSource.cpp
@@ -292,17 +292,17 @@ FileSystemDataSource::GetTarget(nsIRDFRe
     if (! tv)
         return NS_RDF_NO_VALUE;
 
     if (source == mNC_FileSystemRoot)
     {
         if (property == mNC_pulse)
         {
             nsIRDFLiteral   *pulseLiteral;
-            mRDFService->GetLiteral(NS_LITERAL_STRING("12").get(), &pulseLiteral);
+            mRDFService->GetLiteral(MOZ_UTF16("12"), &pulseLiteral);
             *target = pulseLiteral;
             return NS_OK;
         }
     }
     else if (isFileURI(source))
     {
         if (property == mNC_Name)
         {
@@ -404,17 +404,17 @@ FileSystemDataSource::GetTarget(nsIRDFRe
             nsCOMPtr<nsIRDFLiteral> literal;
             mRDFService->GetLiteral(url.get(), getter_AddRefs(literal));
             rv = literal->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
             return(rv);
         }
         else if (property == mNC_pulse)
         {
             nsCOMPtr<nsIRDFLiteral> pulseLiteral;
-            mRDFService->GetLiteral(NS_LITERAL_STRING("12").get(), getter_AddRefs(pulseLiteral));
+            mRDFService->GetLiteral(MOZ_UTF16("12"), getter_AddRefs(pulseLiteral));
             rv = pulseLiteral->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
             return(rv);
         }
         else if (property == mNC_Child)
         {
             // Oh this is evil. Somebody kill me now.
             nsCOMPtr<nsISimpleEnumerator> children;
             rv = GetFolderList(source, false, true, getter_AddRefs(children));
@@ -480,17 +480,17 @@ FileSystemDataSource::GetTargets(nsIRDFR
     {
         if (property == mNC_Child)
         {
             return GetVolumeList(targets);
         }
         else if (property == mNC_pulse)
         {
             nsCOMPtr<nsIRDFLiteral> pulseLiteral;
-            mRDFService->GetLiteral(NS_LITERAL_STRING("12").get(),
+            mRDFService->GetLiteral(MOZ_UTF16("12"),
                                     getter_AddRefs(pulseLiteral));
             return NS_NewSingletonEnumerator(targets, pulseLiteral);
         }
     }
     else if (isFileURI(source))
     {
         if (property == mNC_Child)
         {
@@ -524,17 +524,17 @@ FileSystemDataSource::GetTargets(nsIRDFR
             rv = mRDFService->GetLiteral(url.get(), getter_AddRefs(literal));
             if (NS_FAILED(rv)) return rv;
 
             return NS_NewSingletonEnumerator(targets, literal);
         }
         else if (property == mNC_pulse)
         {
             nsCOMPtr<nsIRDFLiteral> pulseLiteral;
-            rv = mRDFService->GetLiteral(NS_LITERAL_STRING("12").get(),
+            rv = mRDFService->GetLiteral(MOZ_UTF16("12"),
                 getter_AddRefs(pulseLiteral));
             if (NS_FAILED(rv)) return rv;
 
             return NS_NewSingletonEnumerator(targets, pulseLiteral);
         }
     }
 
     return NS_NewEmptyEnumerator(targets);
--- a/security/manager/boot/src/nsSecurityWarningDialogs.cpp
+++ b/security/manager/boot/src/nsSecurityWarningDialogs.cpp
@@ -50,17 +50,17 @@ nsSecurityWarningDialogs::Init()
 
 NS_IMETHODIMP 
 nsSecurityWarningDialogs::ConfirmPostToInsecureFromSecure(nsIInterfaceRequestor *ctx, bool* _result)
 {
   nsresult rv;
 
   // The Telemetry clickthrough constant is 1 more than the constant for the dialog.
   rv = ConfirmDialog(ctx, nullptr, // No preference for this one - it's too important
-                     NS_LITERAL_STRING("PostToInsecureFromSecureMessage").get(),
+                     MOZ_UTF16("PostToInsecureFromSecureMessage"),
                      nullptr,
                      nsISecurityUITelemetry::WARNING_CONFIRM_POST_TO_INSECURE_FROM_SECURE,
                      _result);
 
   return rv;
 }
 
 nsresult
@@ -101,25 +101,25 @@ nsSecurityWarningDialogs::ConfirmDialog(
 
   // Get Prompt to use
   nsCOMPtr<nsIPrompt> prompt = do_GetInterface(ctx);
   if (!prompt) return NS_ERROR_FAILURE;
 
   // Get messages strings from localization file
   nsXPIDLString windowTitle, message, alertMe, cont;
 
-  mStringBundle->GetStringFromName(NS_LITERAL_STRING("Title").get(),
+  mStringBundle->GetStringFromName(MOZ_UTF16("Title"),
                                    getter_Copies(windowTitle));
   mStringBundle->GetStringFromName(messageName,
                                    getter_Copies(message));
   if (showAgainName) {
     mStringBundle->GetStringFromName(showAgainName,
                                      getter_Copies(alertMe));
   }
-  mStringBundle->GetStringFromName(NS_LITERAL_STRING("Continue").get(),
+  mStringBundle->GetStringFromName(MOZ_UTF16("Continue"),
                                    getter_Copies(cont));
   // alertMe is allowed to be null
   if (!windowTitle || !message || !cont) return NS_ERROR_FAILURE;
       
   // Replace # characters with newlines to lay out the dialog.
   PRUnichar* msgchars = message.BeginWriting();
   
   uint32_t i = 0;
--- a/security/manager/pki/src/nsNSSDialogs.cpp
+++ b/security/manager/pki/src/nsNSSDialogs.cpp
@@ -198,22 +198,22 @@ nsNSSDialogs::NotifyCACertExists(nsIInte
   nsCOMPtr<nsIPromptService> promptSvc(do_GetService(NS_PROMPTSERVICE_CONTRACTID));
   if (!promptSvc)
     return NS_ERROR_FAILURE;
 
   // Get the parent window for the dialog
   nsCOMPtr<nsIDOMWindow> parent = do_GetInterface(ctx);
 
   nsAutoString title;
-  rv = mPIPStringBundle->GetStringFromName(NS_LITERAL_STRING("caCertExistsTitle").get(),
+  rv = mPIPStringBundle->GetStringFromName(MOZ_UTF16("caCertExistsTitle"),
                                            getter_Copies(title));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoString msg;
-  rv = mPIPStringBundle->GetStringFromName(NS_LITERAL_STRING("caCertExistsMessage").get(),
+  rv = mPIPStringBundle->GetStringFromName(MOZ_UTF16("caCertExistsMessage"),
                                            getter_Copies(msg));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = promptSvc->Alert(parent, title.get(), msg.get());
 
   return rv;
 }
 
--- a/security/manager/ssl/src/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/src/SSLServerCertVerification.cpp
@@ -904,19 +904,30 @@ AuthCertificate(TransportSecurityInfo * 
                                                infoObject);
     if (rv != SECSuccess) {
       // Due to buggy servers that will staple expired OCSP responses
       // (see for example http://trac.nginx.org/nginx/ticket/425),
       // don't terminate the connection if the stapled response is expired.
       // We will fall back to fetching revocation information.
       PRErrorCode ocspErrorCode = PR_GetError();
       if (ocspErrorCode != SEC_ERROR_OCSP_OLD_RESPONSE) {
+        // stapled OCSP response present but invalid for some reason
+        Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING, 4);
         return rv;
+      } else {
+        // stapled OCSP response present but expired
+        Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING, 3);
       }
+    } else {
+      // stapled OCSP response present and good
+      Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING, 1);
     }
+  } else {
+    // no stapled OCSP response
+    Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING, 2);
   }
 
   CERTCertList *verifyCertChain = nullptr;
   SECOidTag evOidPolicy;
   rv = PSM_SSL_PKIX_AuthCertificate(cert, infoObject, infoObject->GetHostNameRaw(),
                                     &verifyCertChain, &evOidPolicy);
 
   // We want to remember the CA certs in the temp db, so that the application can find the
--- a/security/manager/ssl/src/nsCertOverrideService.cpp
+++ b/security/manager/ssl/src/nsCertOverrideService.cpp
@@ -140,17 +140,17 @@ nsCertOverrideService::Observe(nsISuppor
 {
   // check the topic
   if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
     // The profile is about to change,
     // or is going away because the application is shutting down.
 
     ReentrantMonitorAutoEnter lock(monitor);
 
-    if (!nsCRT::strcmp(aData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
+    if (!nsCRT::strcmp(aData, MOZ_UTF16("shutdown-cleanse"))) {
       RemoveAllFromMemory();
       // delete the storage file
       if (mSettingsFile) {
         mSettingsFile->Remove(false);
       }
     } else {
       RemoveAllFromMemory();
     }
--- a/security/manager/ssl/src/nsCrypto.cpp
+++ b/security/manager/ssl/src/nsCrypto.cpp
@@ -2119,20 +2119,20 @@ nsP12Runnable::Run()
 
   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
   if (NS_FAILED(rv))
     return rv;
 
   //Build up the message that let's the user know we're trying to 
   //make PKCS12 backups of the new certs.
   nssComponent->GetPIPNSSBundleString("ForcedBackup1", final);
-  final.Append(NS_LITERAL_STRING("\n\n").get());
+  final.Append(MOZ_UTF16("\n\n"));
   nssComponent->GetPIPNSSBundleString("ForcedBackup2", temp);
   final.Append(temp.get());
-  final.Append(NS_LITERAL_STRING("\n\n").get());
+  final.Append(MOZ_UTF16("\n\n"));
 
   nssComponent->GetPIPNSSBundleString("ForcedBackup3", temp);
 
   final.Append(temp.get());
   nsNSSComponent::ShowAlertWithConstructedString(final);
 
   nsCOMPtr<nsIFilePicker> filePicker = 
                         do_CreateInstance("@mozilla.org/filepicker;1", &rv);
--- a/security/manager/ssl/tests/unit/test_ocsp_stapling.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_stapling.js
@@ -103,10 +103,25 @@ function run_test() {
   );
   add_ocsp_test("ocsp-stapling-empty.example.com",
                 getXPCOMStatusFromNSS(SEC_ERROR_OCSP_MALFORMED_RESPONSE), true);
   // ocsp-stapling-expired.example.com and
   // ocsp-stapling-expired-fresh-ca.example.com are handled in
   // test_ocsp_stapling_expired.js
 
   add_test(function() { fakeOCSPResponder.stop(run_next_test); });
+
+  add_test(check_ocsp_stapling_telemetry);
   run_next_test();
 }
+
+function check_ocsp_stapling_telemetry() {
+  let histogram = Cc["@mozilla.org/base/telemetry;1"]
+                    .getService(Ci.nsITelemetry)
+                    .getHistogramById("SSL_OCSP_STAPLING")
+                    .snapshot();
+  do_check_eq(histogram.counts[0], 0); // histogram bucket 0 is unused
+  do_check_eq(histogram.counts[1], 1); // 1 connection with a good response
+  do_check_eq(histogram.counts[2], 14); // 14 connections with no stapled resp.
+  do_check_eq(histogram.counts[3], 0); // 0 connections with an expired response
+  do_check_eq(histogram.counts[4], 11); // 11 connections with bad responses
+  run_next_test();
+}
--- a/security/manager/ssl/tests/unit/test_ocsp_stapling_expired.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_stapling_expired.js
@@ -76,10 +76,24 @@ function run_test() {
                 oldValidityPeriodOCSPResponseGood);
   add_ocsp_test("ocsp-stapling-expired.example.com",
                 getXPCOMStatusFromNSS(SEC_ERROR_REVOKED_CERTIFICATE),
                 ocspResponseRevoked);
   add_ocsp_test("ocsp-stapling-expired-fresh-ca.example.com",
                 getXPCOMStatusFromNSS(SEC_ERROR_REVOKED_CERTIFICATE),
                 ocspResponseRevoked);
   add_test(function() { ocspResponder.stop(run_next_test); });
+  add_test(check_ocsp_stapling_telemetry);
   run_next_test();
 }
+
+function check_ocsp_stapling_telemetry() {
+  let histogram = Cc["@mozilla.org/base/telemetry;1"]
+                    .getService(Ci.nsITelemetry)
+                    .getHistogramById("SSL_OCSP_STAPLING")
+                    .snapshot();
+  do_check_eq(histogram.counts[0], 0); // histogram bucket 0 is unused
+  do_check_eq(histogram.counts[1], 0); // 0 connections with a good response
+  do_check_eq(histogram.counts[2], 0); // 0 connections with no stapled resp.
+  do_check_eq(histogram.counts[3], 8); // 8 connections with an expired response
+  do_check_eq(histogram.counts[4], 0); // 0 connections with bad responses
+  run_next_test();
+}
--- a/testing/marionette/client/marionette/tests/unit/test_text.py
+++ b/testing/marionette/client/marionette/tests/unit/test_text.py
@@ -1,13 +1,14 @@
 # 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/.
 
 from marionette_test import MarionetteTestCase
+from keys import Keys
 
 
 class TestText(MarionetteTestCase):
     def test_getText(self):
         test_html = self.marionette.absolute_url("test.html")
         self.marionette.navigate(test_html)
         l = self.marionette.find_element("id", "mozLink")
         self.assertEqual("Click me!", l.text)
@@ -22,8 +23,193 @@ class TestText(MarionetteTestCase):
 
     def test_sendKeys(self):
         test_html = self.marionette.absolute_url("test.html")
         self.marionette.navigate(test_html)
         l = self.marionette.find_element("name", "myInput")
         self.assertEqual("asdf", self.marionette.execute_script("return arguments[0].value;", [l]))
         l.send_keys("o")
         self.assertEqual("asdfo", self.marionette.execute_script("return arguments[0].value;", [l]))
+
+    def test_send_keys_to_type_input(self):
+        test_html = self.marionette.absolute_url("html5/test_html_inputs.html")
+        self.marionette.navigate(test_html)
+        num_input = self.marionette.find_element('id', 'number')
+        self.assertEqual("", self.marionette.execute_script("return arguments[0].value", [num_input]))
+        num_input.send_keys("1234")
+        self.assertEqual('1234', self.marionette.execute_script("return arguments[0].value", [num_input]))
+
+    def test_should_fire_key_press_events(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        key_reporter = self.marionette.find_element("id", "keyReporter")
+        key_reporter.send_keys("a")
+
+        result = self.marionette.find_element("id", "result")
+        self.assertTrue("press:" in result.text)
+
+    def test_should_fire_key_down_events(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        key_reporter = self.marionette.find_element("id", "keyReporter")
+        key_reporter.send_keys("a")
+
+        result = self.marionette.find_element("id", "result")
+        self.assertTrue("down:" in result.text)
+
+    def test_should_fire_key_up_events(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        key_reporter = self.marionette.find_element("id", "keyReporter")
+        key_reporter.send_keys("a")
+
+        result = self.marionette.find_element("id", "result")
+        self.assertTrue("up:" in result.text)
+
+    def test_should_type_lowercase_characters(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        key_reporter = self.marionette.find_element("id", "keyReporter")
+        key_reporter.send_keys("abc def")
+
+        self.assertEqual("abc def", key_reporter.get_attribute('value'))
+
+    def test_should_type_uppercase_characters(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        key_reporter = self.marionette.find_element("id", "keyReporter")
+        key_reporter.send_keys("ABC DEF")
+
+        self.assertEqual("ABC DEF", key_reporter.get_attribute('value'))
+
+    def test_should_type_a_quote_characters(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        key_reporter = self.marionette.find_element("id", "keyReporter")
+        key_reporter.send_keys('"')
+
+        self.assertEqual('"', key_reporter.get_attribute('value'))
+
+    def test_should_type_an_at_character(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        key_reporter = self.marionette.find_element("id", "keyReporter")
+        key_reporter.send_keys('@')
+
+        self.assertEqual('@', key_reporter.get_attribute('value'))
+
+    def test_should_type_a_mix_of_upper_and_lower_case_character(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        key_reporter = self.marionette.find_element("id", "keyReporter")
+        key_reporter.send_keys('me@EXampLe.com')
+
+        self.assertEqual('me@EXampLe.com', key_reporter.get_attribute('value'))
+
+    def test_arrow_keys_are_not_printable(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        key_reporter = self.marionette.find_element("id", "keyReporter")
+        key_reporter.send_keys(Keys.ARROW_LEFT)
+
+        self.assertEqual('', key_reporter.get_attribute('value'))
+
+    def test_will_simulate_a_key_up_when_entering_text_into_input_elements(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        element = self.marionette.find_element("id", "keyUp")
+        element.send_keys("I like cheese")
+
+        result = self.marionette.find_element("id", "result")
+        self.assertEqual(result.text, "I like cheese")
+
+    def test_will_simulate_a_key_down_when_entering_text_into_input_elements(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        element = self.marionette.find_element("id", "keyDown")
+        element.send_keys("I like cheese")
+
+        result = self.marionette.find_element("id", "result")
+        # Because the key down gets the result before the input element is
+        # filled, we're a letter short here
+        self.assertEqual(result.text, "I like chees")
+
+    def test_will_simulate_a_key_press_when_entering_text_into_input_elements(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        element = self.marionette.find_element("id", "keyPress")
+        element.send_keys("I like cheese")
+
+        result = self.marionette.find_element("id", "result")
+        # Because the key down gets the result before the input element is
+        # filled, we're a letter short here
+        self.assertEqual(result.text, "I like chees")
+
+    def test_will_simulate_a_keyup_when_entering_text_into_textareas(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        element = self.marionette.find_element("id", "keyUpArea")
+        element.send_keys("I like cheese")
+
+        result = self.marionette.find_element("id", "result")
+        self.assertEqual(result.text, "I like cheese")
+
+    def test_will_simulate_a_keydown_when_entering_text_into_textareas(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        element = self.marionette.find_element("id", "keyDownArea")
+        element.send_keys("I like cheese")
+
+        result = self.marionette.find_element("id", "result")
+        # Because the key down gets the result before the input element is
+        # filled, we're a letter short here
+        self.assertEqual(result.text, "I like chees")
+
+    def test_will_simulate_a_keypress_when_entering_text_into_textareas(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        element = self.marionette.find_element("id", "keyPressArea")
+        element.send_keys("I like cheese")
+
+        result = self.marionette.find_element("id", "result")
+        # Because the key down gets the result before the input element is
+        # filled, we're a letter short here
+        self.assertEqual(result.text, "I like chees")
+
+    def test_should_report_key_code_of_arrow_keys_up_down_events(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        result = self.marionette.find_element("id", "result")
+        element = self.marionette.find_element("id", "keyReporter")
+        element.send_keys(Keys.ARROW_DOWN)
+        self.assertTrue("down: 40" in result.text.strip())
+        self.assertTrue("up: 40" in result.text.strip())
+
+        element.send_keys(Keys.ARROW_UP)
+        self.assertTrue("down: 38" in result.text.strip())
+        self.assertTrue("up: 38" in result.text.strip())
+
+        element.send_keys(Keys.ARROW_LEFT)
+        self.assertTrue("down: 37" in result.text.strip())
+        self.assertTrue("up: 37" in result.text.strip())
+
+        element.send_keys(Keys.ARROW_RIGHT)
+        self.assertTrue("down: 39" in result.text.strip())
+        self.assertTrue("up: 39" in result.text.strip())
+
+        #  And leave no rubbish/printable keys in the "keyReporter"
+        self.assertEqual(element.get_attribute("value"), "")
+
+    def testNumericNonShiftKeys(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        element = self.marionette.find_element("id", "keyReporter")
+        numericLineCharsNonShifted = "`1234567890-=[]\\,.'/42"
+        element.send_keys(numericLineCharsNonShifted)
+        self.assertEqual(element.get_attribute("value"), numericLineCharsNonShifted)
+
+    def testShouldTypeAnInteger(self):
+        test_html = self.marionette.absolute_url("javascriptPage.html")
+        self.marionette.navigate(test_html)
+        element = self.marionette.find_element("id", "keyReporter")
+        element.send_keys(1234)
+        self.assertEqual(element.get_attribute("value"), "1234")
+
new file mode 100644
--- /dev/null
+++ b/testing/marionette/client/marionette/www/html5/test_html_inputs.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<input id='number' type=number>
\ No newline at end of file
--- a/testing/marionette/marionette-listener.js
+++ b/testing/marionette/marionette-listener.js
@@ -1499,28 +1499,211 @@ function isElementSelected(msg) {
   }
 }
 
 /**
  * Send keys to element
  */
 function sendKeysToElement(msg) {
   let command_id = msg.json.command_id;
-  try {
-    let el = elementManager.getKnownElement(msg.json.id, curFrame);
-    if (checkVisible(el)) {
-      utils.type(curFrame.document, el, msg.json.value.join(""), true);
-      sendOk(command_id);
+
+  let el = elementManager.getKnownElement(msg.json.id, curFrame);
+  if (checkVisible(el)) {
+    if (el.mozIsTextField && el.mozIsTextField(false)) {
+      var currentTextLength = el.value ? el.value.length : 0;
+      el.selectionStart = currentTextLength;
+      el.selectionEnd = currentTextLength;
     }
-    else {
-      sendError("Element is not visible", 11, null, command_id)
-    }
+    el.focus();
+    var value = msg.json.value.join("");
+    let hasShift = null;
+    let hasCtrl = null;
+    let hasAlt = null;
+    let hasMeta = null;
+    for (var i = 0; i < value.length; i++) {
+      let upper = value.charAt(i).toUpperCase();
+      var keyCode = null;
+      var c = value.charAt(i);
+      switch (c) {
+        case '\uE001':
+          keyCode = "VK_CANCEL";
+          break;
+        case '\uE002':
+          keyCode = "VK_HELP";
+          break;
+        case '\uE003':
+          keyCode = "VK_BACK_SPACE";
+          break;
+        case '\uE004':
+          keyCode = "VK_TAB";
+          break;
+        case '\uE005':
+          keyCode = "VK_CLEAR";
+          break;
+        case '\uE006':
+          keyCode = "VK_RETURN";
+          break;
+        case '\uE007':
+          keyCode = "VK_ENTER";
+          break;
+        case '\uE008':
+          keyCode = "VK_SHIFT";
+          hasShift = !hasShift;
+          break;
+        case '\uE009':
+          keyCode = "VK_CONTROL";
+          controlKey = !controlKey;
+          break;
+        case '\uE00A':
+          keyCode = "VK_ALT";
+          altKey = !altKey;
+          break;
+        case '\uE03D':
+          keyCode = "VK_META";
+          metaKey = !metaKey;
+          break;
+        case '\uE00B':
+          keyCode = "VK_PAUSE";
+          break;
+        case '\uE00C':
+          keyCode = "VK_ESCAPE";
+          break;
+        case '\uE00D':
+          keyCode = "VK_Space";  // printable
+          break;
+        case '\uE00E':
+          keyCode = "VK_PAGE_UP";
+          break;
+        case '\uE00F':
+          keyCode = "VK_PAGE_DOWN";
+          break;
+        case '\uE010':
+          keyCode = "VK_END";
+          break;
+        case '\uE011':
+          keyCode = "VK_HOME";
+          break;
+        case '\uE012':
+          keyCode = "VK_LEFT";
+          break;
+        case '\uE013':
+          keyCode = "VK_UP";
+          break;
+        case '\uE014':
+          keyCode = "VK_RIGHT";
+          break;
+        case '\uE015':
+          keyCode = "VK_DOWN";
+          break;
+        case '\uE016':
+          keyCode = "VK_INSERT";
+          break;
+        case '\uE017':
+          keyCode = "VK_DELETE";
+          break;
+        case '\uE018':
+          keyCode = "VK_SEMICOLON";
+          break;
+        case '\uE019':
+          keyCode = "VK_EQUALS";
+          break;
+        case '\uE01A':
+          keyCode = "VK_NUMPAD0";
+          break;
+        case '\uE01B':
+          keyCode = "VK_NUMPAD1";
+          break;
+        case '\uE01C':
+          keyCode = "VK_NUMPAD2";
+          break;
+        case '\uE01D':
+          keyCode = "VK_NUMPAD3";
+          break;
+        case '\uE01E':
+          keyCode = "VK_NUMPAD4";
+          break;
+        case '\uE01F':
+          keyCode = "VK_NUMPAD5";
+          break;
+        case '\uE020':
+          keyCode = "VK_NUMPAD6";
+          break;
+        case '\uE021':
+          keyCode = "VK_NUMPAD7";
+          break;
+        case '\uE022':
+          keyCode = "VK_NUMPAD8";
+          break;
+        case '\uE023':
+          keyCode = "VK_NUMPAD9";
+          break;
+        case '\uE024':
+          keyCode = "VK_MULTIPLY";
+          break;
+        case '\uE025':
+          keyCode = "VK_ADD";
+          break;
+        case '\uE026':
+          keyCode = "VK_SEPARATOR";
+          break;
+        case '\uE027':
+          keyCode = "VK_SUBTRACT";
+          break;
+        case '\uE028':
+          keyCode = "VK_DECIMAL";
+          break;
+        case '\uE029':
+          keyCode = "VK_DIVIDE";
+          break;
+        case '\uE031':
+          keyCode = "VK_F1";
+          break;
+        case '\uE032':
+          keyCode = "VK_F2";
+          break;
+        case '\uE033':
+          keyCode = "VK_F3";
+          break;
+        case '\uE034':
+          keyCode = "VK_F4";
+          break;
+        case '\uE035':
+          keyCode = "VK_F5";
+          break;
+        case '\uE036':
+          keyCode = "VK_F6";
+          break;
+        case '\uE037':
+          keyCode = "VK_F7";
+          break;
+        case '\uE038':
+          keyCode = "VK_F8";
+          break;
+        case '\uE039':
+          keyCode = "VK_F9";
+          break;
+        case '\uE03A':
+          keyCode = "VK_F10";
+          break;
+        case '\uE03B':
+          keyCode = "VK_F11";
+          break;
+        case '\uE03C':
+          keyCode = "VK_F12";
+          break;
+      }
+      hasShift = value.charAt(i) == upper;
+      utils.synthesizeKey(keyCode || value[i],
+                          { shiftKey: hasShift, ctrlKey: hasCtrl, altKey: hasAlt, metaKey: hasMeta },
+                          curFrame);
+    };
+    sendOk(command_id);
   }
-  catch (e) {
-    sendError(e.message, e.code, e.stack, command_id);
+  else {
+    sendError("Element is not visible", 11, null, command_id)
   }
 }
 
 /**
  * Get the position of an element
  */
 function getElementPosition(msg) {
   let command_id = msg.json.command_id;
--- a/toolkit/components/commandlines/nsCommandLine.cpp
+++ b/toolkit/components/commandlines/nsCommandLine.cpp
@@ -546,17 +546,17 @@ nsCommandLine::EnumerateHandlers(Enumera
     rv = catman->GetCategoryEntry("command-line-handler",
 				  entry.get(),
 				  getter_Copies(contractID));
     if (NS_FAILED(rv))
       continue;
 
     nsCOMPtr<nsICommandLineHandler> clh(do_GetService(contractID.get()));
     if (!clh) {
-      LogConsoleMessage(NS_LITERAL_STRING("Contract ID '%s' was registered as a command line handler for entry '%s', but could not be created.").get(),
+      LogConsoleMessage(MOZ_UTF16("Contract ID '%s' was registered as a command line handler for entry '%s', but could not be created."),
                         contractID.get(), entry.get());
       continue;
     }
 
     rv = (aCallback)(clh, this, aClosure);
     if (rv == NS_ERROR_ABORT)
       break;
 
--- a/toolkit/components/downloads/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/nsDownloadManager.cpp
@@ -1365,17 +1365,17 @@ nsDownloadManager::GetDefaultDownloadsDi
   // Vista:
   // Downloads
   // XP/2K:
   // My Documents/Downloads
   // Linux:
   // XDG user dir spec, with a fallback to Home/Downloads
 
   nsXPIDLString folderName;
-  mBundle->GetStringFromName(NS_LITERAL_STRING("downloadsFolder").get(),
+  mBundle->GetStringFromName(MOZ_UTF16("downloadsFolder"),
                              getter_Copies(folderName));
 
 #if defined (XP_MACOSX)
   rv = dirService->Get(NS_OSX_DEFAULT_DOWNLOAD_DIR,
                        NS_GET_IID(nsIFile),
                        getter_AddRefs(downloadDir));
   NS_ENSURE_SUCCESS(rv, rv);
 #elif defined(XP_WIN)
@@ -2433,52 +2433,52 @@ nsDownloadManager::Observe(nsISupports *
       CleanUp();
   } else if (strcmp(aTopic, "quit-application-requested") == 0 &&
              currDownloadCount) {
     nsCOMPtr<nsISupportsPRBool> cancelDownloads =
       do_QueryInterface(aSubject, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 #ifndef XP_MACOSX
     ConfirmCancelDownloads(currDownloadCount, cancelDownloads,
-                           NS_LITERAL_STRING("quitCancelDownloadsAlertTitle").get(),
-                           NS_LITERAL_STRING("quitCancelDownloadsAlertMsgMultiple").get(),
-                           NS_LITERAL_STRING("quitCancelDownloadsAlertMsg").get(),
-                           NS_LITERAL_STRING("dontQuitButtonWin").get());
+                           MOZ_UTF16("quitCancelDownloadsAlertTitle"),
+                           MOZ_UTF16("quitCancelDownloadsAlertMsgMultiple"),
+                           MOZ_UTF16("quitCancelDownloadsAlertMsg"),
+                           MOZ_UTF16("dontQuitButtonWin"));
 #else
     ConfirmCancelDownloads(currDownloadCount, cancelDownloads,
-                           NS_LITERAL_STRING("quitCancelDownloadsAlertTitle").get(),
-                           NS_LITERAL_STRING("quitCancelDownloadsAlertMsgMacMultiple").get(),
-                           NS_LITERAL_STRING("quitCancelDownloadsAlertMsgMac").get(),
-                           NS_LITERAL_STRING("dontQuitButtonMac").get());
+                           MOZ_UTF16("quitCancelDownloadsAlertTitle"),
+                           MOZ_UTF16("quitCancelDownloadsAlertMsgMacMultiple"),
+                           MOZ_UTF16("quitCancelDownloadsAlertMsgMac"),
+                           MOZ_UTF16("dontQuitButtonMac"));
 #endif
   } else if (strcmp(aTopic, "offline-requested") == 0 && currDownloadCount) {
     nsCOMPtr<nsISupportsPRBool> cancelDownloads =
       do_QueryInterface(aSubject, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
     ConfirmCancelDownloads(currDownloadCount, cancelDownloads,
-                           NS_LITERAL_STRING("offlineCancelDownloadsAlertTitle").get(),
-                           NS_LITERAL_STRING("offlineCancelDownloadsAlertMsgMultiple").get(),
-                           NS_LITERAL_STRING("offlineCancelDownloadsAlertMsg").get(),
-                           NS_LITERAL_STRING("dontGoOfflineButton").get());
+                           MOZ_UTF16("offlineCancelDownloadsAlertTitle"),
+                           MOZ_UTF16("offlineCancelDownloadsAlertMsgMultiple"),
+                           MOZ_UTF16("offlineCancelDownloadsAlertMsg"),
+                           MOZ_UTF16("dontGoOfflineButton"));
   }
   else if (strcmp(aTopic, NS_IOSERVICE_GOING_OFFLINE_TOPIC) == 0) {
     // Pause all downloads, and mark them to auto-resume.
     (void)PauseAllDownloads(true);
   }
   else if (strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC) == 0 &&
            nsDependentString(aData).EqualsLiteral(NS_IOSERVICE_ONLINE)) {
     // We can now resume all downloads that are supposed to auto-resume.
     (void)ResumeAllDownloads(false);
   }
   else if (strcmp(aTopic, "alertclickcallback") == 0) {
     nsCOMPtr<nsIDownloadManagerUI> dmui =
       do_GetService("@mozilla.org/download-manager-ui;1", &rv);
     NS_ENSURE_SUCCESS(rv, rv);
     return dmui->Show(nullptr, nullptr, nsIDownloadManagerUI::REASON_USER_INTERACTED,
-                      aData && NS_strcmp(aData, NS_LITERAL_STRING("private").get()) == 0);
+                      aData && NS_strcmp(aData, MOZ_UTF16("private")) == 0);
   } else if (strcmp(aTopic, "sleep_notification") == 0 ||
              strcmp(aTopic, "suspend_process_notification") == 0) {
     // Pause downloads if we're sleeping, and mark the downloads as auto-resume
     (void)PauseAllDownloads(true);
   } else if (strcmp(aTopic, "wake_notification") == 0 ||
              strcmp(aTopic, "resume_process_notification") == 0) {
     int32_t resumeOnWakeDelay = 10000;
     nsCOMPtr<nsIPrefBranch> pref = do_GetService(NS_PREFSERVICE_CONTRACTID);
@@ -2503,20 +2503,20 @@ nsDownloadManager::Observe(nsISupports *
     // private browsing mode (thereby cancelling them). Otherwise, silently proceed.
     if (!mCurrentPrivateDownloads.Count())
       return NS_OK;
 
     nsCOMPtr<nsISupportsPRBool> cancelDownloads = do_QueryInterface(aSubject, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     ConfirmCancelDownloads(mCurrentPrivateDownloads.Count(), cancelDownloads,
-                           NS_LITERAL_STRING("leavePrivateBrowsingCancelDownloadsAlertTitle").get(),
-                           NS_LITERAL_STRING("leavePrivateBrowsingWindowsCancelDownloadsAlertMsgMultiple").get(),
-                           NS_LITERAL_STRING("leavePrivateBrowsingWindowsCancelDownloadsAlertMsg").get(),
-                           NS_LITERAL_STRING("dontLeavePrivateBrowsingButton").get());
+                           MOZ_UTF16("leavePrivateBrowsingCancelDownloadsAlertTitle"),
+                           MOZ_UTF16("leavePrivateBrowsingWindowsCancelDownloadsAlertMsgMultiple"),
+                           MOZ_UTF16("leavePrivateBrowsingWindowsCancelDownloadsAlertMsg"),
+                           MOZ_UTF16("dontLeavePrivateBrowsingButton"));
   }
 
   return NS_OK;
 }
 
 void
 nsDownloadManager::ConfirmCancelDownloads(int32_t aCount,
                                           nsISupportsPRBool *aCancelDownloads,
@@ -2536,31 +2536,31 @@ nsDownloadManager::ConfirmCancelDownload
   mBundle->GetStringFromName(aTitle, getter_Copies(title));
 
   nsAutoString countString;
   countString.AppendInt(aCount);
   const PRUnichar *strings[1] = { countString.get() };
   if (aCount > 1) {
     mBundle->FormatStringFromName(aCancelMessageMultiple, strings, 1,
                                   getter_Copies(message));
-    mBundle->FormatStringFromName(NS_LITERAL_STRING("cancelDownloadsOKTextMultiple").get(),
+    mBundle->FormatStringFromName(MOZ_UTF16("cancelDownloadsOKTextMultiple"),
                                   strings, 1, getter_Copies(quitButton));
   } else {
     mBundle->GetStringFromName(aCancelMessageSingle, getter_Copies(message));
-    mBundle->GetStringFromName(NS_LITERAL_STRING("cancelDownloadsOKText").get(),
+    mBundle->GetStringFromName(MOZ_UTF16("cancelDownloadsOKText"),
                                getter_Copies(quitButton));
   }
 
   mBundle->GetStringFromName(aDontCancelButton, getter_Copies(dontQuitButton));
 
   // Get Download Manager window, to be parent of alert.
   nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID);
   nsCOMPtr<nsIDOMWindow> dmWindow;
   if (wm) {
-    wm->GetMostRecentWindow(NS_LITERAL_STRING("Download:Manager").get(),
+    wm->GetMostRecentWindow(MOZ_UTF16("Download:Manager"),
                             getter_AddRefs(dmWindow));
   }
 
   // Show alert.
   nsCOMPtr<nsIPromptService> prompter(do_GetService(NS_PROMPTSERVICE_CONTRACTID));
   if (prompter) {
     int32_t flags = (nsIPromptService::BUTTON_TITLE_IS_STRING * nsIPromptService::BUTTON_POS_0) + (nsIPromptService::BUTTON_TITLE_IS_STRING * nsIPromptService::BUTTON_POS_1);
     bool nothing = false;
@@ -2703,20 +2703,20 @@ nsDownload::SetState(DownloadState aStat
             mDownloadManager->mCurrentDownloads.Count();
         if (showTaskbarAlert && size == 0) {
           nsCOMPtr<nsIAlertsService> alerts =
             do_GetService("@mozilla.org/alerts-service;1");
           if (alerts) {
               nsXPIDLString title, message;
 
               mDownloadManager->mBundle->GetStringFromName(
-                  NS_LITERAL_STRING("downloadsCompleteTitle").get(),
+                  MOZ_UTF16("downloadsCompleteTitle"),
                   getter_Copies(title));
               mDownloadManager->mBundle->GetStringFromName(
-                  NS_LITERAL_STRING("downloadsCompleteMsg").get(),
+                  MOZ_UTF16("downloadsCompleteMsg"),
                   getter_Copies(message));
 
               bool removeWhenDone =
                 mDownloadManager->GetRetentionBehavior() == 0;
 
               // If downloads are automatically removed per the user's
               // retention policy, there's no reason to make the text clickable
               // because if it is, they'll click open the download manager and
@@ -3674,34 +3674,34 @@ nsDownload::FailDownload(nsresult aStatu
   // Grab the bundle before potentially losing our member variables
   nsCOMPtr<nsIStringBundle> bundle = mDownloadManager->mBundle;
 
   (void)SetState(nsIDownloadManager::DOWNLOAD_FAILED);
 
   // Get title for alert.
   nsXPIDLString title;
   nsresult rv = bundle->GetStringFromName(
-    NS_LITERAL_STRING("downloadErrorAlertTitle").get(), getter_Copies(title));
+    MOZ_UTF16("downloadErrorAlertTitle"), getter_Copies(title));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Get a generic message if we weren't supplied one
   nsXPIDLString message;
   message = aMessage;
   if (message.IsEmpty()) {
     rv = bundle->GetStringFromName(
-      NS_LITERAL_STRING("downloadErrorGeneric").get(), getter_Copies(message));
+      MOZ_UTF16("downloadErrorGeneric"), getter_Copies(message));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Get Download Manager window to be parent of alert
   nsCOMPtr<nsIWindowMediator> wm =
     do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIDOMWindow> dmWindow;
-  rv = wm->GetMostRecentWindow(NS_LITERAL_STRING("Download:Manager").get(),
+  rv = wm->GetMostRecentWindow(MOZ_UTF16("Download:Manager"),
                                getter_AddRefs(dmWindow));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Show alert
   nsCOMPtr<nsIPromptService> prompter =
     do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   return prompter->Alert(dmWindow, title, message);
--- a/toolkit/components/filepicker/nsFileView.cpp
+++ b/toolkit/components/filepicker/nsFileView.cpp
@@ -849,17 +849,17 @@ nsFileView::FilterFiles()
       // need to check return value for GetLeafName()
       continue;
     }
     
     if (!isHidden) {
       for (uint32_t j = 0; j < filterCount; ++j) {
         bool matched = false;
         if (!nsCRT::strcmp(mCurrentFilters.ElementAt(j),
-                           NS_LITERAL_STRING("..apps").get()))
+                           MOZ_UTF16("..apps")))
         {
           file->IsExecutable(&matched);
         } else
           matched = (NS_WildCardMatch(ucsLeafName.get(),
                                       mCurrentFilters.ElementAt(j),
                                       true) == MATCH);
 
         if (matched) {
--- a/toolkit/components/places/Database.cpp
+++ b/toolkit/components/places/Database.cpp
@@ -867,35 +867,35 @@ Database::CreateBookmarkRoots()
   if (NS_FAILED(rv)) return rv;
 
   nsXPIDLString rootTitle;
   // The first root's title is an empty string.
   rv = CreateRoot(mMainConn, NS_LITERAL_CSTRING("places"), rootTitle);
   if (NS_FAILED(rv)) return rv;
 
   // Fetch the internationalized folder name from the string bundle.
-  rv = bundle->GetStringFromName(NS_LITERAL_STRING("BookmarksMenuFolderTitle").get(),
+  rv = bundle->GetStringFromName(MOZ_UTF16("BookmarksMenuFolderTitle"),
                                  getter_Copies(rootTitle));
   if (NS_FAILED(rv)) return rv;
   rv = CreateRoot(mMainConn, NS_LITERAL_CSTRING("menu"), rootTitle);
   if (NS_FAILED(rv)) return rv;
 
-  rv = bundle->GetStringFromName(NS_LITERAL_STRING("BookmarksToolbarFolderTitle").get(),
+  rv = bundle->GetStringFromName(MOZ_UTF16("BookmarksToolbarFolderTitle"),
                                  getter_Copies(rootTitle));
   if (NS_FAILED(rv)) return rv;
   rv = CreateRoot(mMainConn, NS_LITERAL_CSTRING("toolbar"), rootTitle);
   if (NS_FAILED(rv)) return rv;
 
-  rv = bundle->GetStringFromName(NS_LITERAL_STRING("TagsFolderTitle").get(),
+  rv = bundle->GetStringFromName(MOZ_UTF16("TagsFolderTitle"),
                                  getter_Copies(rootTitle));
   if (NS_FAILED(rv)) return rv;
   rv = CreateRoot(mMainConn, NS_LITERAL_CSTRING("tags"), rootTitle);
   if (NS_FAILED(rv)) return rv;
 
-  rv = bundle->GetStringFromName(NS_LITERAL_STRING("UnsortedBookmarksFolderTitle").get(),
+  rv = bundle->GetStringFromName(MOZ_UTF16("UnsortedBookmarksFolderTitle"),
                                  getter_Copies(rootTitle));
   if (NS_FAILED(rv)) return rv;
   rv = CreateRoot(mMainConn, NS_LITERAL_CSTRING("unfiled"), rootTitle);
   if (NS_FAILED(rv)) return rv;
 
 #if DEBUG
   nsCOMPtr<mozIStorageStatement> stmt;
   rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
--- a/toolkit/components/places/PlacesDBUtils.jsm
+++ b/toolkit/components/places/PlacesDBUtils.jsm
@@ -960,18 +960,18 @@ this.PlacesDBUtils = {
       places_root: PlacesUtils.placesRootId
     };
 
     let outstandingProbes = 0;
 
     function reportResult(aProbe, aValue) {
       outstandingProbes--;
 
+      let value = aValue;
       try {
-        let value = aValue;
         if ("callback" in aProbe) {
           value = aProbe.callback(value);
         }
         probeValues[aProbe.histogram] = value;
         Services.telemetry.getHistogramById(aProbe.histogram).add(value);
       } catch (ex) {
         Components.utils.reportError("Error adding value " + value +
                                      " to histogram " + aProbe.histogram +
--- a/toolkit/components/places/nsNavHistory.cpp
+++ b/toolkit/components/places/nsNavHistory.cpp
@@ -1527,78 +1527,78 @@ PlacesSQLQueryBuilder::SelectAsDay()
     // These are used as limits for the inside containers.
     nsAutoCString sqlFragmentContainerBeginTime, sqlFragmentContainerEndTime;
     // These are used to query if the container should be visible.
     nsAutoCString sqlFragmentSearchBeginTime, sqlFragmentSearchEndTime;
     switch(i) {
        case 0:
         // Today
          history->GetStringFromName(
-          NS_LITERAL_STRING("finduri-AgeInDays-is-0").get(), dateName);
+          MOZ_UTF16("finduri-AgeInDays-is-0"), dateName);
         // From start of today
         sqlFragmentContainerBeginTime = NS_LITERAL_CSTRING(
           "(strftime('%s','now','localtime','start of day','utc')*1000000)");
         // To now (tomorrow)
         sqlFragmentContainerEndTime = NS_LITERAL_CSTRING(
           "(strftime('%s','now','localtime','start of day','+1 day','utc')*1000000)");
         // Search for the same timeframe.
         sqlFragmentSearchBeginTime = sqlFragmentContainerBeginTime;
         sqlFragmentSearchEndTime = sqlFragmentContainerEndTime;
          break;
        case 1:
         // Yesterday
          history->GetStringFromName(
-          NS_LITERAL_STRING("finduri-AgeInDays-is-1").get(), dateName);
+          MOZ_UTF16("finduri-AgeInDays-is-1"), dateName);
         // From start of yesterday
         sqlFragmentContainerBeginTime = NS_LITERAL_CSTRING(
           "(strftime('%s','now','localtime','start of day','-1 day','utc')*1000000)");
         // To start of today
         sqlFragmentContainerEndTime = NS_LITERAL_CSTRING(
           "(strftime('%s','now','localtime','start of day','utc')*1000000)");
         // Search for the same timeframe.
         sqlFragmentSearchBeginTime = sqlFragmentContainerBeginTime;
         sqlFragmentSearchEndTime = sqlFragmentContainerEndTime;
         break;
       case 2:
         // Last 7 days
         history->GetAgeInDaysString(7,
-          NS_LITERAL_STRING("finduri-AgeInDays-last-is").get(), dateName);
+          MOZ_UTF16("finduri-AgeInDays-last-is"), dateName);
         // From start of 7 days ago
         sqlFragmentContainerBeginTime = NS_LITERAL_CSTRING(
           "(strftime('%s','now','localtime','start of day','-7 days','utc')*1000000)");
         // To now (tomorrow)
         sqlFragmentContainerEndTime = NS_LITERAL_CSTRING(
           "(strftime('%s','now','localtime','start of day','+1 day','utc')*1000000)");
         // This is an overlapped container, but we show it only if there are
         // visits older than yesterday.
         sqlFragmentSearchBeginTime = sqlFragmentContainerBeginTime;
         sqlFragmentSearchEndTime = NS_LITERAL_CSTRING(
           "(strftime('%s','now','localtime','start of day','-2 days','utc')*1000000)");
         break;
       case 3:
         // This month
         history->GetStringFromName(
-          NS_LITERAL_STRING("finduri-AgeInMonths-is-0").get(), dateName);
+          MOZ_UTF16("finduri-AgeInMonths-is-0"), dateName);
         // From start of this month
         sqlFragmentContainerBeginTime = NS_LITERAL_CSTRING(
           "(strftime('%s','now','localtime','start of month','utc')*1000000)");
         // To now (tomorrow)
         sqlFragmentContainerEndTime = NS_LITERAL_CSTRING(
           "(strftime('%s','now','localtime','start of day','+1 day','utc')*1000000)");
         // This is an overlapped container, but we show it only if there are
         // visits older than 7 days ago.
         sqlFragmentSearchBeginTime = sqlFragmentContainerBeginTime;
         sqlFragmentSearchEndTime = NS_LITERAL_CSTRING(
           "(strftime('%s','now','localtime','start of day','-7 days','utc')*1000000)");
          break;
        default:
         if (i == HISTORY_ADDITIONAL_DATE_CONT_NUM + 6) {
           // Older than 6 months
           history->GetAgeInDaysString(6,
-            NS_LITERAL_STRING("finduri-AgeInMonths-isgreater").get(), dateName);
+            MOZ_UTF16("finduri-AgeInMonths-isgreater"), dateName);
           // From start of epoch
           sqlFragmentContainerBeginTime = NS_LITERAL_CSTRING(
             "(datetime(0, 'unixepoch')*1000000)");
           // To start of 6 months ago ( 5 months + this month).
           sqlFragmentContainerEndTime = NS_LITERAL_CSTRING(
             "(strftime('%s','now','localtime','start of month','-5 months','utc')*1000000)");
           // Search for the same timeframe.
           sqlFragmentSearchBeginTime = sqlFragmentContainerBeginTime;
@@ -1688,17 +1688,17 @@ PlacesSQLQueryBuilder::SelectAsDay()
 nsresult
 PlacesSQLQueryBuilder::SelectAsSite()
 {
   nsAutoCString localFiles;
 
   nsNavHistory *history = nsNavHistory::GetHistoryService();
   NS_ENSURE_STATE(history);
 
-  history->GetStringFromName(NS_LITERAL_STRING("localhost").get(), localFiles);
+  history->GetStringFromName(MOZ_UTF16("localhost"), localFiles);
   mAddParams.Put(NS_LITERAL_CSTRING("localhost"), localFiles);
 
   // If there are additional conditions the query has to join on visits too.
   nsAutoCString visitsJoin;
   nsAutoCString additionalConditions;
   nsAutoCString timeConstraints;
   if (!mConditions.IsEmpty()) {
     visitsJoin.AssignLiteral("JOIN moz_historyvisits v ON v.place_id = h.id ");
@@ -4112,17 +4112,17 @@ void
 nsNavHistory::TitleForDomain(const nsCString& domain, nsACString& aTitle)
 {
   if (! domain.IsEmpty()) {
     aTitle = domain;
     return;
   }
 
   // use the localized one instead
-  GetStringFromName(NS_LITERAL_STRING("localhost").get(), aTitle);
+  GetStringFromName(MOZ_UTF16("localhost"), aTitle);
 }
 
 void
 nsNavHistory::GetAgeInDaysString(int32_t aInt, const PRUnichar *aName,
                                  nsACString& aResult)
 {
   nsIStringBundle *bundle = GetBundle();
   if (bundle) {
@@ -4182,17 +4182,17 @@ nsNavHistory::GetMonthYear(int32_t aMont
     nsAutoString yearString;
     yearString.AppendInt(aYear);
     const PRUnichar* strings[2] = {
       NS_ConvertUTF8toUTF16(monthName).get()
     , yearString.get()
     };
     nsXPIDLString value;
     if (NS_SUCCEEDED(bundle->FormatStringFromName(
-          NS_LITERAL_STRING("finduri-MonthYear").get(), strings, 2,
+          MOZ_UTF16("finduri-MonthYear"), strings, 2,
           getter_Copies(value)
         ))) {
       CopyUTF16toUTF8(value, aResult);
       return;
     }
   }
   aResult.AppendLiteral("finduri-MonthYear");
 }
--- a/toolkit/components/places/nsNavHistoryResult.cpp
+++ b/toolkit/components/places/nsNavHistoryResult.cpp
@@ -4713,17 +4713,17 @@ nsNavHistoryResult::OnVisit(nsIURI* aURI
       NS_ENSURE_SUCCESS(rv, rv);
       nsAutoCString title;
       rv = firstChild->GetTitle(title);
       NS_ENSURE_SUCCESS(rv, rv);
       nsNavHistory* history = nsNavHistory::GetHistoryService();
       NS_ENSURE_TRUE(history, NS_OK);
       nsAutoCString todayLabel;
       history->GetStringFromName(
-        NS_LITERAL_STRING("finduri-AgeInDays-is-0").get(), todayLabel);
+        MOZ_UTF16("finduri-AgeInDays-is-0"), todayLabel);
       todayIsMissing = !todayLabel.Equals(title);
     }
   }
 
   if (!added || todayIsMissing) {
     // None of registered query observers has accepted our URI.  This means,
     // that a matching query either was not expanded or it does not exist.
     uint32_t resultType = mRootNode->mOptions->ResultType();
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -4688,10 +4688,15 @@
     "kind": "enumerated",
     "n_values": 512,
     "description": "Bitmask of reasons we did not false start when libssl would have let us (see key in nsNSSCallbacks.cpp)"
   },
   "SSL_HANDSHAKE_TYPE": { 
     "kind": "enumerated",
     "n_values": 8,
     "description": "Type of handshake (1=resumption, 2=false started, 3=chose not to false start, 4=not allowed to false start)"
+  },
+  "SSL_OCSP_STAPLING": {
+    "kind": "enumerated",
+    "n_values": 8,
+    "description": "Status of OCSP stapling on this handshake (1=present, good; 2=none; 3=present, expired; 4=present, other error)"
   }
 }
--- a/toolkit/system/gnome/nsAlertsIconListener.cpp
+++ b/toolkit/system/gnome/nsAlertsIconListener.cpp
@@ -257,17 +257,17 @@ nsAlertsIconListener::InitAlertAsync(con
     nsAutoCString appShortName;
     if (bundleService) {
       nsCOMPtr<nsIStringBundle> bundle;
       bundleService->CreateBundle("chrome://branding/locale/brand.properties",
                                   getter_AddRefs(bundle));
       nsAutoString appName;
 
       if (bundle) {
-        bundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
+        bundle->GetStringFromName(MOZ_UTF16("brandShortName"),
                                   getter_Copies(appName));
         appShortName = NS_ConvertUTF16toUTF8(appName);
       } else {
         NS_WARNING("brand.properties not present, using default application name");
         appShortName.AssignLiteral("Mozilla");
       }
     } else {
       appShortName.AssignLiteral("Mozilla");
--- a/toolkit/xre/ProfileReset.cpp
+++ b/toolkit/xre/ProfileReset.cpp
@@ -75,17 +75,17 @@ ProfileResetCleanup(nsIToolkitProfile* a
   rv = sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
   if (!sb) return NS_ERROR_FAILURE;
 
   NS_ConvertUTF8toUTF16 appName(gAppData->name);
   const PRUnichar* params[] = {appName.get(), appName.get()};
 
   nsXPIDLString resetBackupDirectoryName;
 
-  static const PRUnichar* kResetBackupDirectory = NS_LITERAL_STRING("resetBackupDirectory").get();
+  static const PRUnichar* kResetBackupDirectory = MOZ_UTF16("resetBackupDirectory");
   rv = sb->FormatStringFromName(kResetBackupDirectory, params, 2,
                                 getter_Copies(resetBackupDirectoryName));
 
   // Get info to copy the old root profile dir to the desktop as a backup.
   nsCOMPtr<nsIFile> backupDest, containerDest, profileDest;
   rv = NS_GetSpecialDirectory(NS_OS_DESKTOP_DIR, getter_AddRefs(backupDest));
   if (NS_FAILED(rv)) {
     // Fall back to the home directory if the desktop is not available.
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1774,17 +1774,17 @@ ProfileLockedDialog(nsIFile* aProfileDir
     static const PRUnichar kRestartNoUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','N','o','U','n','l','o','c','k','e','r','M','a','c','\0'}; // "restartMessageNoUnlockerMac"
     static const PRUnichar kRestartUnlocker[] = {'r','e','s','t','a','r','t','M','e','s','s','a','g','e','U','n','l','o','c','k','e','r','M','a','c','\0'}; // "restartMessageUnlockerMac"
 #endif
 
     sb->FormatStringFromName(aUnlocker ? kRestartUnlocker : kRestartNoUnlocker,
                              params, 2, getter_Copies(killMessage));
 
     nsXPIDLString killTitle;
-    sb->FormatStringFromName(NS_LITERAL_STRING("restartTitle").get(),
+    sb->FormatStringFromName(MOZ_UTF16("restartTitle"),
                              params, 1, getter_Copies(killTitle));
 
     if (!killMessage || !killTitle)
       return NS_ERROR_FAILURE;
 
     nsCOMPtr<nsIPromptService> ps
       (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
     NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
@@ -1860,17 +1860,17 @@ ProfileMissingDialog(nsINativeAppSupport
   
     nsXPIDLString missingMessage;
   
     // profileMissing  
     static const PRUnichar kMissing[] = {'p','r','o','f','i','l','e','M','i','s','s','i','n','g','\0'};
     sb->FormatStringFromName(kMissing, params, 2, getter_Copies(missingMessage));
   
     nsXPIDLString missingTitle;
-    sb->FormatStringFromName(NS_LITERAL_STRING("profileMissingTitle").get(),
+    sb->FormatStringFromName(MOZ_UTF16("profileMissingTitle"),
                              params, 1, getter_Copies(missingTitle));
   
     if (missingMessage && missingTitle) {
       nsCOMPtr<nsIPromptService> ps
         (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
       NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
   
       ps->Alert(nullptr, missingTitle, missingMessage);
@@ -4232,16 +4232,46 @@ public:
   ~WinRTInitWrapper() {
     if (SUCCEEDED(mResult)) {
       ::RoUninitialize();
     }
   }
   HRESULT mResult;
 };
 
+#ifndef AHE_TYPE
+enum AHE_TYPE {
+  AHE_DESKTOP = 0,
+  AHE_IMMERSIVE = 1
+};
+#endif
+
+/*
+ * The Windows launcher uses this value to decide what front end ui
+ * to launch. We always launch the same ui unless the user
+ * specifically asks to switch. Update the value on every startup
+ * based on the environment requested.
+ */
+void
+SetLastWinRunType(AHE_TYPE aType)
+{
+  HKEY key;
+  LONG result = RegOpenKeyExW(HKEY_CURRENT_USER,
+                              L"SOFTWARE\\Mozilla\\Firefox",
+                              0, KEY_WRITE, &key);
+  if (result != ERROR_SUCCESS) {
+    return;
+  }
+  DWORD value = (DWORD)aType;
+  result = RegSetValueEx(key, L"MetroLastAHE", 0, REG_DWORD,
+                         reinterpret_cast<LPBYTE>(&value),
+                         sizeof(DWORD));
+  RegCloseKey(key);
+}
+
 int
 XRE_mainMetro(int argc, char* argv[], const nsXREAppData* aAppData)
 {
   char aLocal;
   GeckoProfilerInitRAII profilerGuard(&aLocal);
   PROFILER_LABEL("Startup", "XRE_Main");
 
   nsresult rv = NS_OK;
@@ -4299,16 +4329,19 @@ XRE_main(int argc, char* argv[], const n
 #if !defined(MOZ_METRO) || !defined(XP_WIN)
   XREMain main;
   int result = main.XRE_main(argc, argv, aAppData);
   mozilla::RecordShutdownEndTimeStamp();
   return result;
 #else
   if (aFlags == XRE_MAIN_FLAG_USE_METRO) {
     SetWindowsEnvironment(WindowsEnvironmentType_Metro);
+    SetLastWinRunType(AHE_IMMERSIVE);
+  } else {
+    SetLastWinRunType(AHE_DESKTOP);
   }
 
   // Desktop
   if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
     XREMain main;
     int result = main.XRE_main(argc, argv, aAppData);
     mozilla::RecordShutdownEndTimeStamp();
     return result;
--- a/toolkit/xre/nsNativeAppSupportOS2.cpp
+++ b/toolkit/xre/nsNativeAppSupportOS2.cpp
@@ -1367,17 +1367,17 @@ void nsNativeAppSupportOS2::ParseDDEArg(
     WinDdeQueryString( args, temp.BeginWriting(), temp.Length(), CP_WINANSI );
     // Parse out the given arg.
     ParseDDEArg(temp.get(), index, aString);
     return;
 }
 
 void nsNativeAppSupportOS2::ActivateLastWindow() {
     nsCOMPtr<nsIDOMWindow> navWin;
-    GetMostRecentWindow( NS_LITERAL_STRING("navigator:browser").get(), getter_AddRefs( navWin ) );
+    GetMostRecentWindow( MOZ_UTF16("navigator:browser"), getter_AddRefs( navWin ) );
     if ( navWin )
         // Activate that window.
         activateWindow( navWin );
     else
         // Need to create a Navigator window, then.
         OpenBrowserWindow();
 }
 
--- a/toolkit/xre/nsNativeAppSupportWin.cpp
+++ b/toolkit/xre/nsNativeAppSupportWin.cpp
@@ -1237,17 +1237,17 @@ HDDEDATA nsNativeAppSupportWin::CreateDD
                                            mApplication,
                                            CF_TEXT,
                                            0 );
     return result;
 }
 
 void nsNativeAppSupportWin::ActivateLastWindow() {
     nsCOMPtr<nsIDOMWindow> navWin;
-    GetMostRecentWindow( NS_LITERAL_STRING("navigator:browser").get(), getter_AddRefs( navWin ) );
+    GetMostRecentWindow( MOZ_UTF16("navigator:browser"), getter_AddRefs( navWin ) );
     if ( navWin ) {
         // Activate that window.
         activateWindow( navWin );
     } else {
         // Need to create a Navigator window, then.
         OpenBrowserWindow();
     }
 }
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -1837,17 +1837,17 @@ void nsExternalAppHandler::SendStatusCha
               } else if (mTransfer) {
                 mTransfer->OnStatusChange(nullptr, (type == kReadError) ? aRequest : nullptr, rv, msgText);
               }
               else
               if (XRE_GetProcessType() == GeckoProcessType_Default) {
                 // We don't have a listener.  Simply show the alert ourselves.
                 nsCOMPtr<nsIPrompt> prompter(do_GetInterface(mWindowContext));
                 nsXPIDLString title;
-                bundle->FormatStringFromName(NS_LITERAL_STRING("title").get(),
+                bundle->FormatStringFromName(MOZ_UTF16("title"),
                                              strings,
                                              1,
                                              getter_Copies(title));
                 if (prompter)
                 {
                   prompter->Alert(title, msgText);
                 }
               }
--- a/uriloader/exthandler/os2/nsOSHelperAppService.cpp
+++ b/uriloader/exthandler/os2/nsOSHelperAppService.cpp
@@ -1333,17 +1333,17 @@ WpsGetDefaultHandler(const char *aFileEx
       uint32_t handle;
       // the handle may be zero if the WPS class provides the default handler
       if (NS_SUCCEEDED(rwsSvc->HandlerFromExtension(aFileExt, &handle, aDescription)))
         return handle;
     }
   }
 
   // no RWS or RWS failed to return at least a description
-  if (NS_FAILED(GetNLSString(NS_LITERAL_STRING("wpsDefaultOS2").get(),
+  if (NS_FAILED(GetNLSString(MOZ_UTF16("wpsDefaultOS2"),
                              aDescription)))
     aDescription.Assign(NS_LITERAL_STRING("WPS default"));
 
   return 0;
 }
 
 //------------------------------------------------------------------------
 
@@ -1383,17 +1383,17 @@ WpsMimeInfoFromExtension(const char *aFi
     ustr.Truncate();
 
   if (ustr.IsEmpty()) {
     nsAutoCString extUpper;
     ToUpperCase(nsDependentCString(aFileExt), extUpper);
     CopyUTF8toUTF16(extUpper, ustr);
 
     nsAutoString fileType;
-    if (NS_FAILED(GetNLSString(NS_LITERAL_STRING("fileType").get(), fileType)))
+    if (NS_FAILED(GetNLSString(MOZ_UTF16("fileType"), fileType)))
       ustr.Assign(NS_LITERAL_STRING("%S file"));
     int pos = -1;
     if ((pos = fileType.Find("%S")) > -1)
       fileType.Replace(pos, 2, ustr);
     aMI->SetDescription(fileType);
   }
 }
 
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -566,17 +566,17 @@ nsAppShell::ProcessNextNativeEvent(bool 
 
     case AndroidGeckoEvent::LOW_MEMORY:
         // TODO hook in memory-reduction stuff for different levels here
         if (curEvent->MetaState() >= AndroidGeckoEvent::MEMORY_PRESSURE_MEDIUM) {
             nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
             if (os) {
                 os->NotifyObservers(nullptr,
                                     "memory-pressure",
-                                    NS_LITERAL_STRING("low-memory").get());
+                                    MOZ_UTF16("low-memory"));
             }
         }
         break;
 
     case AndroidGeckoEvent::NETWORK_LINK_CHANGE:
     {
         nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
         if (os) {
--- a/widget/android/nsPrintOptionsAndroid.cpp
+++ b/widget/android/nsPrintOptionsAndroid.cpp
@@ -7,17 +7,17 @@
 #include "nsPrintSettingsImpl.h"
 
 class nsPrintSettingsAndroid : public nsPrintSettings {
 public:
   nsPrintSettingsAndroid()
   {
     // The aim here is to set up the objects enough that silent printing works
     SetOutputFormat(nsIPrintSettings::kOutputFormatPDF);
-    SetPrinterName(NS_LITERAL_STRING("PDF printer").get());
+    SetPrinterName(MOZ_UTF16("PDF printer"));
     
   }
 };
 
 nsPrintOptionsAndroid::nsPrintOptionsAndroid()
 {
 }
 
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -100,17 +100,17 @@ public:
             }
         }
 
         // Notify observers that the screen state has just changed.
         nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
         if (observerService) {
           observerService->NotifyObservers(
             nullptr, "screen-state-changed",
-            mIsOn ? NS_LITERAL_STRING("on").get() : NS_LITERAL_STRING("off").get()
+            mIsOn ? MOZ_UTF16("on") : MOZ_UTF16("off")
           );
         }
 
         return NS_OK;
     }
 
 private:
     bool mIsOn;
--- a/widget/gtk/nsDeviceContextSpecG.cpp
+++ b/widget/gtk/nsDeviceContextSpecG.cpp
@@ -815,39 +815,39 @@ NS_IMETHODIMP nsPrinterEnumeratorGTK::In
     printerFeatures.SetNumOrientationRecords(2);
 #endif /* SET_PRINTER_FEATURES_VIA_PREFS */
 
     /* PostScript module does not support changing the plex mode... */
 #ifdef SET_PRINTER_FEATURES_VIA_PREFS
     printerFeatures.SetCanChangePlex(false);
 #endif /* SET_PRINTER_FEATURES_VIA_PREFS */
     DO_PR_DEBUG_LOG(("setting default plex to '%s'\n", "default"));
-    aPrintSettings->SetPlexName(NS_LITERAL_STRING("default").get());
+    aPrintSettings->SetPlexName(MOZ_UTF16("default"));
 #ifdef SET_PRINTER_FEATURES_VIA_PREFS
     printerFeatures.SetPlexRecord(0, "default");
     printerFeatures.SetNumPlexRecords(1);
 #endif /* SET_PRINTER_FEATURES_VIA_PREFS */
 
     /* PostScript module does not support changing the resolution mode... */
 #ifdef SET_PRINTER_FEATURES_VIA_PREFS
     printerFeatures.SetCanChangeResolutionName(false);
 #endif /* SET_PRINTER_FEATURES_VIA_PREFS */
     DO_PR_DEBUG_LOG(("setting default resolution to '%s'\n", "default"));
-    aPrintSettings->SetResolutionName(NS_LITERAL_STRING("default").get());
+    aPrintSettings->SetResolutionName(MOZ_UTF16("default"));
 #ifdef SET_PRINTER_FEATURES_VIA_PREFS
     printerFeatures.SetResolutionNameRecord(0, "default");
     printerFeatures.SetNumResolutionNameRecords(1);
 #endif /* SET_PRINTER_FEATURES_VIA_PREFS */
 
     /* PostScript module does not support changing the colorspace... */
 #ifdef SET_PRINTER_FEATURES_VIA_PREFS
     printerFeatures.SetCanChangeColorspace(false);
 #endif /* SET_PRINTER_FEATURES_VIA_PREFS */
     DO_PR_DEBUG_LOG(("setting default colorspace to '%s'\n", "default"));
-    aPrintSettings->SetColorspace(NS_LITERAL_STRING("default").get());
+    aPrintSettings->SetColorspace(MOZ_UTF16("default"));
 #ifdef SET_PRINTER_FEATURES_VIA_PREFS
     printerFeatures.SetColorspaceRecord(0, "default");
     printerFeatures.SetNumColorspaceRecords(1);
 #endif /* SET_PRINTER_FEATURES_VIA_PREFS */   
 
 #ifdef SET_PRINTER_FEATURES_VIA_PREFS
     printerFeatures.SetCanChangePaperSize(true);
 #endif /* SET_PRINTER_FEATURES_VIA_PREFS */
--- a/widget/gtk/nsPrintDialogGTK.cpp
+++ b/widget/gtk/nsPrintDialogGTK.cpp
@@ -55,33 +55,33 @@ ShowCustomDialog(GtkComboBox *changed_bo
   GtkWindow* printDialog = GTK_WINDOW(user_data);
   nsCOMPtr<nsIStringBundleService> bundleSvc =
        do_GetService(NS_STRINGBUNDLE_CONTRACTID);
 
   nsCOMPtr<nsIStringBundle> printBundle;
   bundleSvc->CreateBundle("chrome://global/locale/printdialog.properties", getter_AddRefs(printBundle));
   nsXPIDLString intlString;
 
-  printBundle->GetStringFromName(NS_LITERAL_STRING("headerFooterCustom").get(), getter_Copies(intlString));
+  printBundle->GetStringFromName(MOZ_UTF16("headerFooterCustom"), getter_Copies(intlString));
   GtkWidget* prompt_dialog = gtk_dialog_new_with_buttons(NS_ConvertUTF16toUTF8(intlString).get(), printDialog,
 #if (MOZ_WIDGET_GTK == 2)
                                                          (GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
 #else
                                                          (GtkDialogFlags)(GTK_DIALOG_MODAL),
 #endif
                                                          GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
                                                          GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
                                                          nullptr);
   gtk_dialog_set_default_response(GTK_DIALOG(prompt_dialog), GTK_RESPONSE_ACCEPT);
   gtk_dialog_set_alternative_button_order(GTK_DIALOG(prompt_dialog),
                                           GTK_RESPONSE_ACCEPT,
                                           GTK_RESPONSE_REJECT,
                                           -1);
 
-  printBundle->GetStringFromName(NS_LITERAL_STRING("customHeaderFooterPrompt").get(), getter_Copies(intlString));
+  printBundle->GetStringFromName(MOZ_UTF16("customHeaderFooterPrompt"), getter_Copies(intlString));
   GtkWidget* custom_label = gtk_label_new(NS_ConvertUTF16toUTF8(intlString).get());
   GtkWidget* custom_entry = gtk_entry_new();
   GtkWidget* question_icon = gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
 
   // To be convenient, prefill the textbox with the existing value, if any, and select it all so they can easily
   // both edit it and type in a new one.
   const char* current_text = (const char*) g_object_get_data(G_OBJECT(changed_box), "custom-text");
   if (current_text) {
--- a/widget/gtk/nsSound.cpp
+++ b/widget/gtk/nsSound.cpp
@@ -123,17 +123,17 @@ ca_context_get_default()
     nsCOMPtr<nsIStringBundleService> bundleService =
         mozilla::services::GetStringBundleService();
     if (bundleService) {
         nsCOMPtr<nsIStringBundle> brandingBundle;
         bundleService->CreateBundle("chrome://branding/locale/brand.properties",
                                     getter_AddRefs(brandingBundle));
         if (brandingBundle) {
             nsAutoString wbrand;
-            brandingBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
+            brandingBundle->GetStringFromName(MOZ_UTF16("brandShortName"),
                                               getter_Copies(wbrand));
             NS_ConvertUTF16toUTF8 brand(wbrand);
 
             ca_context_change_props(ctx, "application.name", brand.get(),
                                     nullptr);
         }
     }
 
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -3312,17 +3312,17 @@ GetBrandName(nsXPIDLString& brandName)
     nsCOMPtr<nsIStringBundle> bundle;
     if (bundleService)
         bundleService->CreateBundle(
             "chrome://branding/locale/brand.properties",
             getter_AddRefs(bundle));
 
     if (bundle)
         bundle->GetStringFromName(
-            NS_LITERAL_STRING("brandShortName").get(),
+            MOZ_UTF16("brandShortName"),
             getter_Copies(brandName));
 
     if (brandName.IsEmpty())
         brandName.Assign(NS_LITERAL_STRING("Mozilla"));
 }
 
 static GdkWindow *
 CreateGdkWindow(GdkWindow *parent, GtkWidget *widget)
--- a/widget/os2/nsRwsService.cpp
+++ b/widget/os2/nsRwsService.cpp
@@ -310,17 +310,17 @@ nsRwsService::HandlerFromPath(const char
                     RWSI_ASIS,   0, 32,
                     RWSI_ASIS,   0, (ULONG)-1);
 
       // if there's no associated program, create dummy values
       // (if chosen, the WPS will open the file's Properties notebook)
       if (rc) {
         if (rc == RWSSRV_FUNCTIONFAILED) {
           *aHandle = 0;
-          AssignNLSString(NS_LITERAL_STRING("wpsDefaultOS2").get(), _retval);
+          AssignNLSString(MOZ_UTF16("wpsDefaultOS2"), _retval);
           rv = NS_OK;
         }
         else
           ERRMSG(rc, "wpQueryAssociatedProgram")
         break;
       }
 
       // get a ptr to the return value's data structure;  then get
@@ -355,58 +355,58 @@ nsRwsService::HandlerFromPath(const char
     // the default view is provided by the file's WPS class;
     // in this case, *aHandle is 0
 
     // see if it's a known view that can be given a meaningful name
     switch (defView) {
       case 0xbc2b: {
         rv = IsDescendedFrom(wpsFilePtr, "MMImage");
         if (NS_SUCCEEDED(rv))
-          AssignNLSString(NS_LITERAL_STRING("mmImageViewerOS2").get(), _retval);
+          AssignNLSString(MOZ_UTF16("mmImageViewerOS2"), _retval);
         break;
       }
 
       case 0xbc0d:    // Audio editor
       case 0xbc21:    // Video editor
       case 0xbc17:    // Midi editor
       case 0xbbef:    // Play
       case 0xbbe5: {  // Player
         rv = IsDescendedFrom(wpsFilePtr, "MMAudio");
         if (NS_SUCCEEDED(rv)) {
-          AssignNLSString(NS_LITERAL_STRING("mmAudioPlayerOS2").get(), _retval);
+          AssignNLSString(MOZ_UTF16("mmAudioPlayerOS2"), _retval);
           break;
         }
 
         rv = IsDescendedFrom(wpsFilePtr, "MMVideo");
         if (NS_SUCCEEDED(rv)) {
-          AssignNLSString(NS_LITERAL_STRING("mmVideoPlayerOS2").get(), _retval);
+          AssignNLSString(MOZ_UTF16("mmVideoPlayerOS2"), _retval);
           break;
         }
 
         rv = IsDescendedFrom(wpsFilePtr, "MMMIDI");
         if (NS_SUCCEEDED(rv))
-          AssignNLSString(NS_LITERAL_STRING("mmMidiPlayerOS2").get(), _retval);
+          AssignNLSString(MOZ_UTF16("mmMidiPlayerOS2"), _retval);
 
         break;
       }
 
       case 0x7701: {
         rv = IsDescendedFrom(wpsFilePtr, "TSArcMgr");
         if (NS_SUCCEEDED(rv))
-          AssignNLSString(NS_LITERAL_STRING("odZipFolderOS2").get(), _retval);
+          AssignNLSString(MOZ_UTF16("odZipFolderOS2"), _retval);
         break;
       }
 
       // this has to go last because TSEnhDataFile replaces
       // WPDataFile; if present, all data files are descended from it
       case 0xb742:
       case 0xa742: {
         rv = IsDescendedFrom(wpsFilePtr, "TSEnhDataFile");
         if (NS_SUCCEEDED(rv))
-          AssignNLSString(NS_LITERAL_STRING("odTextViewOS2").get(), _retval);
+          AssignNLSString(MOZ_UTF16("odTextViewOS2"), _retval);
         break;
       }
     } // end switch
 
     if (NS_SUCCEEDED(rv))
       break;
 
     // the name of this view is unknown, so create a generic name
@@ -426,17 +426,17 @@ nsRwsService::HandlerFromPath(const char
     nsAutoChar16Buffer buffer;
     int32_t bufLength;
     rv = MultiByteToWideChar(0, pszTitle, strlen(pszTitle),
                              buffer, bufLength);
     if (NS_FAILED(rv))
       break;
 
     nsAutoString classViewer;
-    AssignNLSString(NS_LITERAL_STRING("classViewerOS2").get(), classViewer);
+    AssignNLSString(MOZ_UTF16("classViewerOS2"), classViewer);
     int pos = -1;
     if ((pos = classViewer.Find("%S")) > -1)
       classViewer.Replace(pos, 2, buffer.Elements());
     _retval.Assign(classViewer);
     rv = NS_OK;
   } while (0);
 
   // free the pHdr allocated by the final call
@@ -742,17 +742,17 @@ static void AssignNLSString(const PRUnic
       "chrome://mozapps/locale/downloads/unknownContentType.properties",
       getter_AddRefs(bundle));
     if (NS_FAILED(rv))
       break;
 
     // if we can't fetch the requested string, try to get "WPS Default"
     rv = bundle->GetStringFromName(aKey, getter_Copies(title));
     if (NS_FAILED(rv))
-      rv = bundle->GetStringFromName(NS_LITERAL_STRING("wpsDefaultOS2").get(),
+      rv = bundle->GetStringFromName(MOZ_UTF16("wpsDefaultOS2"),
                                      getter_Copies(title));
   } while (0);
 
   if (NS_SUCCEEDED(rv))
     result.Assign(title);
   else
     result.Assign(NS_LITERAL_STRING("WPS Default"));
 }
--- a/widget/qt/nsWindow.cpp
+++ b/widget/qt/nsWindow.cpp
@@ -2152,17 +2152,17 @@ GetBrandName(nsXPIDLString& brandName)
     nsCOMPtr<nsIStringBundle> bundle;
     if (bundleService)
         bundleService->CreateBundle(
             "chrome://branding/locale/brand.properties",
             getter_AddRefs(bundle));
 
     if (bundle)
         bundle->GetStringFromName(
-            NS_LITERAL_STRING("brandShortName").get(),
+            MOZ_UTF16("brandShortName"),
             getter_Copies(brandName));
 
     if (brandName.IsEmpty())
         brandName.Assign(NS_LITERAL_STRING("Mozilla"));
 }
 
 
 nsresult
--- a/widget/windows/AudioSession.cpp
+++ b/widget/windows/AudioSession.cpp
@@ -202,17 +202,17 @@ AudioSession::Start()
     nsCOMPtr<nsIStringBundleService> bundleService = 
       do_GetService(NS_STRINGBUNDLE_CONTRACTID);
     NS_ENSURE_TRUE(bundleService, NS_ERROR_FAILURE);
     nsCOMPtr<nsIStringBundle> bundle;
     bundleService->CreateBundle("chrome://branding/locale/brand.properties",
                                 getter_AddRefs(bundle));
     NS_ENSURE_TRUE(bundle, NS_ERROR_FAILURE);
 
-    bundle->GetStringFromName(NS_LITERAL_STRING("brandFullName").get(),
+    bundle->GetStringFromName(MOZ_UTF16("brandFullName"),
                               getter_Copies(mDisplayName));
 
     wchar_t *buffer;
     mIconPath.GetMutableData(&buffer, MAX_PATH);
 
     // XXXkhuey we should provide a way for a xulrunner app to specify an icon
     // that's not in the product binary.
     ::GetModuleFileNameW(nullptr, buffer, MAX_PATH);
--- a/widget/windows/nsDataObj.cpp
+++ b/widget/windows/nsDataObj.cpp
@@ -1025,17 +1025,17 @@ nsDataObj :: GetFileDescriptorInternetSh
     return E_OUTOFMEMORY;
   }
 
   // get a valid filename in the following order: 1) from the page title, 
   // 2) localized string for an untitled page, 3) just use "Untitled.URL"
   if (!CreateFilenameFromTextA(title, ".URL", 
                                fileGroupDescA->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) {
     nsXPIDLString untitled;
-    if (!GetLocalizedString(NS_LITERAL_STRING("noPageTitle").get(), untitled) ||
+    if (!GetLocalizedString(MOZ_UTF16("noPageTitle"), untitled) ||
         !CreateFilenameFromTextA(untitled, ".URL", 
                                  fileGroupDescA->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) {
       strcpy(fileGroupDescA->fgd[0].cFileName, "Untitled.URL");
     }
   }
 
   // one file in the file block
   fileGroupDescA->cItems = 1;
@@ -1063,23 +1063,23 @@ nsDataObj :: GetFileDescriptorInternetSh
   LPFILEGROUPDESCRIPTORW fileGroupDescW = reinterpret_cast<LPFILEGROUPDESCRIPTORW>(::GlobalLock(fileGroupDescHandle));
   if (!fileGroupDescW) {
     ::GlobalFree(fileGroupDescHandle);
     return E_OUTOFMEMORY;
   }
 
   // get a valid filename in the following order: 1) from the page title, 
   // 2) localized string for an untitled page, 3) just use "Untitled.URL"
-  if (!CreateFilenameFromTextW(title, NS_LITERAL_STRING(".URL").get(), 
+  if (!CreateFilenameFromTextW(title, MOZ_UTF16(".URL"), 
                                fileGroupDescW->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) {
     nsXPIDLString untitled;
-    if (!GetLocalizedString(NS_LITERAL_STRING("noPageTitle").get(), untitled) ||
-        !CreateFilenameFromTextW(untitled, NS_LITERAL_STRING(".URL").get(), 
+    if (!GetLocalizedString(MOZ_UTF16("noPageTitle"), untitled) ||
+        !CreateFilenameFromTextW(untitled, MOZ_UTF16(".URL"), 
                                  fileGroupDescW->fgd[0].cFileName, NS_MAX_FILEDESCRIPTOR)) {
-      wcscpy(fileGroupDescW->fgd[0].cFileName, NS_LITERAL_STRING("Untitled.URL").get());
+      wcscpy(fileGroupDescW->fgd[0].cFileName, MOZ_UTF16("Untitled.URL"));
     }
   }
 
   // one file in the file block
   fileGroupDescW->cItems = 1;
   fileGroupDescW->fgd[0].dwFlags = FD_LINKUI;
 
   ::GlobalUnlock( fileGroupDescHandle );
--- a/widget/windows/nsDeviceContextSpecWin.cpp
+++ b/widget/windows/nsDeviceContextSpecWin.cpp
@@ -255,17 +255,17 @@ GetFileNameForPrintSettings(nsIPrintSett
     mozilla::services::GetStringBundleService();
   if (!bundleService)
     return NS_ERROR_FAILURE;
   nsCOMPtr<nsIStringBundle> bundle;
   rv = bundleService->CreateBundle(NS_ERROR_GFX_PRINTER_BUNDLE_URL, getter_AddRefs(bundle));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsXPIDLString title;
-  rv = bundle->GetStringFromName(NS_LITERAL_STRING("PrintToFile").get(), getter_Copies(title));
+  rv = bundle->GetStringFromName(MOZ_UTF16("PrintToFile"), getter_Copies(title));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIWindowWatcher> wwatch =
     (do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDOMWindow> window;
   wwatch->GetActiveWindow(getter_AddRefs(window));
--- a/widget/windows/nsTextStore.cpp
+++ b/widget/windows/nsTextStore.cpp
@@ -3342,17 +3342,17 @@ nsTextStore::Initialize(void)
         MarkContextAsKeyboardDisabled(sTsfDisabledContext);
         MarkContextAsEmpty(sTsfDisabledContext);
       }
     }
   }
 
   if (sTsfThreadMgr && !sFlushTIPInputMessage) {
     sFlushTIPInputMessage = ::RegisterWindowMessageW(
-        NS_LITERAL_STRING("Flush TIP Input Message").get());
+        MOZ_UTF16("Flush TIP Input Message"));
   }
 
   if (!sTsfThreadMgr) {
     NS_IF_RELEASE(sMessagePump);
     NS_IF_RELEASE(sKeystrokeMgr);
   }
 
   PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
--- a/widget/windows/winrt/MetroContracts.cpp
+++ b/widget/windows/winrt/MetroContracts.cpp
@@ -411,17 +411,17 @@ FrameworkView::OnDataShareRequested(IDat
     do_GetService(NS_STRINGBUNDLE_CONTRACTID);
   NS_ENSURE_TRUE(bundleService, E_FAIL);
   nsCOMPtr<nsIStringBundle> brandBundle;
   nsString brandName;
   bundleService->CreateBundle("chrome://branding/locale/brand.properties",
     getter_AddRefs(brandBundle));
   NS_ENSURE_TRUE(brandBundle, E_FAIL);
   if(brandBundle) {
-    brandBundle->GetStringFromName(NS_LITERAL_STRING("brandFullName").get(),
+    brandBundle->GetStringFromName(MOZ_UTF16("brandFullName"),
                                    getter_Copies(brandName));
   }
 
   // Set these properties at the end.  Otherwise users can get a
   // "There was a problem with the data package" error when there
   // is simply nothing to share.
   props->put_ApplicationName(HStringReference(brandName.BeginReading()).Get());
   if (title.Length()) {
--- a/widget/xpwidgets/nsBaseFilePicker.cpp
+++ b/widget/xpwidgets/nsBaseFilePicker.cpp
@@ -166,57 +166,57 @@ nsBaseFilePicker::AppendFilters(int32_t 
   rv = stringService->CreateBundle(FILEPICKER_FILTERS, getter_AddRefs(filterBundle));
   if (NS_FAILED(rv))
     return NS_ERROR_FAILURE;
 
   nsXPIDLString title;
   nsXPIDLString filter;
 
   if (aFilterMask & filterAll) {
-    titleBundle->GetStringFromName(NS_LITERAL_STRING("allTitle").get(), getter_Copies(title));
-    filterBundle->GetStringFromName(NS_LITERAL_STRING("allFilter").get(), getter_Copies(filter));
+    titleBundle->GetStringFromName(MOZ_UTF16("allTitle"), getter_Copies(title));
+    filterBundle->GetStringFromName(MOZ_UTF16("allFilter"), getter_Copies(filter));
     AppendFilter(title,filter);
   }
   if (aFilterMask & filterHTML) {
-    titleBundle->GetStringFromName(NS_LITERAL_STRING("htmlTitle").get(), getter_Copies(title));
-    filterBundle->GetStringFromName(NS_LITERAL_STRING("htmlFilter").get(), getter_Copies(filter));
+    titleBundle->GetStringFromName(MOZ_UTF16("htmlTitle"), getter_Copies(title));
+    filterBundle->GetStringFromName(MOZ_UTF16("htmlFilter"), getter_Copies(filter));
     AppendFilter(title,filter);
   }
   if (aFilterMask & filterText) {
-    titleBundle->GetStringFromName(NS_LITERAL_STRING("textTitle").get(), getter_Copies(title));
-    filterBundle->GetStringFromName(NS_LITERAL_STRING("textFilter").get(), getter_Copies(filter));
+    titleBundle->GetStringFromName(MOZ_UTF16("textTitle"), getter_Copies(title));
+    filterBundle->GetStringFromName(MOZ_UTF16("textFilter"), getter_Copies(filter));
     AppendFilter(title,filter);
   }
   if (aFilterMask & filterImages) {
-    titleBundle->GetStringFromName(NS_LITERAL_STRING("imageTitle").get(), getter_Copies(title));
-    filterBundle->GetStringFromName(NS_LITERAL_STRING("imageFilter").get(), getter_Copies(filter));
+    titleBundle->GetStringFromName(MOZ_UTF16("imageTitle"), getter_Copies(title));
+    filterBundle->GetStringFromName(MOZ_UTF16("imageFilter"), getter_Copies(filter));
     AppendFilter(title,filter);
   }
   if (aFilterMask & filterAudio) {
-    titleBundle->GetStringFromName(NS_LITERAL_STRING("audioTitle").get(), getter_Copies(title));
-    filterBundle->GetStringFromName(NS_LITERAL_STRING("audioFilter").get(), getter_Copies(filter));
+    titleBundle->GetStringFromName(MOZ_UTF16("audioTitle"), getter_Copies(title));
+    filterBundle->GetStringFromName(MOZ_UTF16("audioFilter"), getter_Copies(filter));
     AppendFilter(title,filter);
   }
   if (aFilterMask & filterVideo) {
-    titleBundle->GetStringFromName(NS_LITERAL_STRING("videoTitle").get(), getter_Copies(title));
-    filterBundle->GetStringFromName(NS_LITERAL_STRING("videoFilter").get(), getter_Copies(filter));
+    titleBundle->GetStringFromName(MOZ_UTF16("videoTitle"), getter_Copies(title));
+    filterBundle->GetStringFromName(MOZ_UTF16("videoFilter"), getter_Copies(filter));
     AppendFilter(title,filter);
   }
   if (aFilterMask & filterXML) {
-    titleBundle->GetStringFromName(NS_LITERAL_STRING("xmlTitle").get(), getter_Copies(title));
-    filterBundle->GetStringFromName(NS_LITERAL_STRING("xmlFilter").get(), getter_Copies(filter));
+    titleBundle->GetStringFromName(MOZ_UTF16("xmlTitle"), getter_Copies(title));
+    filterBundle->GetStringFromName(MOZ_UTF16("xmlFilter"), getter_Copies(filter));
     AppendFilter(title,filter);
   }
   if (aFilterMask & filterXUL) {
-    titleBundle->GetStringFromName(NS_LITERAL_STRING("xulTitle").get(), getter_Copies(title));
-    filterBundle->GetStringFromName(NS_LITERAL_STRING("xulFilter").get(), getter_Copies(filter));
+    titleBundle->GetStringFromName(MOZ_UTF16("xulTitle"), getter_Copies(title));
+    filterBundle->GetStringFromName(MOZ_UTF16("xulFilter"), getter_Copies(filter));
     AppendFilter(title, filter);
   }
   if (aFilterMask & filterApps) {
-    titleBundle->GetStringFromName(NS_LITERAL_STRING("appsTitle").get(), getter_Copies(title));
+    titleBundle->GetStringFromName(MOZ_UTF16("appsTitle"), getter_Copies(title));
     // Pass the magic string "..apps" to the platform filepicker, which it
     // should recognize and do the correct platform behavior for.
     AppendFilter(title, NS_LITERAL_STRING("..apps"));
   }
   return NS_OK;
 }
 
 // Set the filter index
--- a/xpcom/base/nsMemoryImpl.cpp
+++ b/xpcom/base/nsMemoryImpl.cpp
@@ -43,17 +43,17 @@ NS_IMETHODIMP_(void)
 nsMemoryImpl::Free(void* ptr)
 {
     NS_Free(ptr);
 }
 
 NS_IMETHODIMP
 nsMemoryImpl::HeapMinimize(bool aImmediate)
 {
-    return FlushMemory(NS_LITERAL_STRING("heap-minimize").get(), aImmediate);
+    return FlushMemory(MOZ_UTF16("heap-minimize"), aImmediate);
 }
 
 NS_IMETHODIMP
 nsMemoryImpl::IsLowMemory(bool *result)
 {
     NS_ERROR("IsLowMemory is deprecated.  See bug 592308.");
     *result = false;
     return NS_OK;
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -1623,25 +1623,25 @@ public:
 
     nsCOMPtr<nsIObserverService> os = services::GetObserverService();
     if (!os) {
       return NS_ERROR_FAILURE;
     }
 
     if (mRemainingIters == 0) {
       os->NotifyObservers(nullptr, "after-minimize-memory-usage",
-                          NS_LITERAL_STRING("MinimizeMemoryUsageRunnable").get());
+                          MOZ_UTF16("MinimizeMemoryUsageRunnable"));
       if (mCallback) {
         mCallback->Run();
       }
       return NS_OK;
     }
 
     os->NotifyObservers(nullptr, "memory-pressure",
-                        NS_LITERAL_STRING("heap-minimize").get());
+                        MOZ_UTF16("heap-minimize"));
     mRemainingIters--;
     NS_DispatchToMainThread(this);
 
     return NS_OK;
   }
 
   NS_IMETHOD Cancel()
   {
--- a/xpcom/components/ManifestParser.cpp
+++ b/xpcom/components/ManifestParser.cpp
@@ -447,30 +447,30 @@ ParseManifest(NSLocationType type, FileL
       }
     }
   }
 
   nsAutoString osVersion;
 #if defined(XP_WIN)
   OSVERSIONINFO info = { sizeof(OSVERSIONINFO) };
   if (GetVersionEx(&info)) {
-    nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
+    nsTextFormatter::ssprintf(osVersion, MOZ_UTF16("%ld.%ld"),
                                          info.dwMajorVersion,
                                          info.dwMinorVersion);
   }
 #elif defined(MOZ_WIDGET_COCOA)
   SInt32 majorVersion, minorVersion;
   if ((Gestalt(gestaltSystemVersionMajor, &majorVersion) == noErr) &&
       (Gestalt(gestaltSystemVersionMinor, &minorVersion) == noErr)) {
-    nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
+    nsTextFormatter::ssprintf(osVersion, MOZ_UTF16("%ld.%ld"),
                                          majorVersion,
                                          minorVersion);
   }
 #elif defined(MOZ_WIDGET_GTK)
-  nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
+  nsTextFormatter::ssprintf(osVersion, MOZ_UTF16("%ld.%ld"),
                                        gtk_major_version,
                                        gtk_minor_version);
 #elif defined(MOZ_WIDGET_ANDROID)
   bool isTablet = false;
   if (mozilla::AndroidBridge::Bridge()) {
     mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", "RELEASE", osVersion);
     isTablet = mozilla::widget::android::GeckoAppShell::IsTablet();
   }
--- a/xpcom/tests/TestObserverService.cpp
+++ b/xpcom/tests/TestObserverService.cpp
@@ -94,23 +94,23 @@ int main(int argc, char *argv[])
  
         printf("Adding Observer-B as observer of topic-B...\n");
         rv = anObserverService->AddObserver(bObserver, topicB.get(), false);
         testResult(rv);
 
         printf("Testing Notify(observer-A, topic-A)...\n");
         rv = anObserverService->NotifyObservers( aObserver,
                                    topicA.get(),
-                                   NS_LITERAL_STRING("Testing Notify(observer-A, topic-A)").get() );
+                                   MOZ_UTF16("Testing Notify(observer-A, topic-A)") );
         testResult(rv);
 
         printf("Testing Notify(observer-B, topic-B)...\n");
         rv = anObserverService->NotifyObservers( bObserver,
                                    topicB.get(),
-                                   NS_LITERAL_STRING("Testing Notify(observer-B, topic-B)").get() );
+                                   MOZ_UTF16("Testing Notify(observer-B, topic-B)") );
         testResult(rv);
  
         printf("Testing EnumerateObserverList (for topic-A)...\n");
         nsCOMPtr<nsISimpleEnumerator> e;
         rv = anObserverService->EnumerateObservers(topicA.get(), getter_AddRefs(e));
 
         testResult(rv);
 
@@ -122,17 +122,17 @@ int main(int argc, char *argv[])
           {
               e->GetNext(getter_AddRefs(observer));
               printf("Calling observe on enumerated observer ");
               printString(reinterpret_cast<TestObserver*>
                                           (reinterpret_cast<void*>(observer.get()))->mName);
               printf("...\n");
               rv = observer->Observe( observer, 
                                       topicA.get(), 
-                                      NS_LITERAL_STRING("during enumeration").get() );
+                                      MOZ_UTF16("during enumeration") );
               testResult(rv);
           }
         }
         printf("...done enumerating observers of topic-A\n");
 
         printf("Removing Observer-A...\n");
         rv = anObserverService->RemoveObserver(aObserver, topicA.get());
         testResult(rv);
--- a/xpcom/tests/TestStrings.cpp
+++ b/xpcom/tests/TestStrings.cpp
@@ -1012,33 +1012,33 @@ static bool test_strip_chars_helper(cons
   nsAutoString tmp(str);
   nsAString& data = tmp;
   data.StripChars(strip, offset);
   return data.Equals(result);
 }
 
 static bool test_strip_chars()
 {
-  return test_strip_chars_helper(NS_LITERAL_STRING("foo \r \nbar").get(),
-                                 NS_LITERAL_STRING(" \n\r").get(),
+  return test_strip_chars_helper(MOZ_UTF16("foo \r \nbar"),
+                                 MOZ_UTF16(" \n\r"),
                                  NS_LITERAL_STRING("foobar")) &&
-         test_strip_chars_helper(NS_LITERAL_STRING("\r\nfoo\r\n").get(),
-                                 NS_LITERAL_STRING(" \n\r").get(),
+         test_strip_chars_helper(MOZ_UTF16("\r\nfoo\r\n"),
+                                 MOZ_UTF16(" \n\r"),
                                  NS_LITERAL_STRING("foo")) &&
-         test_strip_chars_helper(NS_LITERAL_STRING("foo").get(),
-                                 NS_LITERAL_STRING(" \n\r").get(),
+         test_strip_chars_helper(MOZ_UTF16("foo"),
+                                 MOZ_UTF16(" \n\r"),
                                  NS_LITERAL_STRING("foo")) &&
-         test_strip_chars_helper(NS_LITERAL_STRING("foo").get(),
-                                 NS_LITERAL_STRING("fo").get(),
+         test_strip_chars_helper(MOZ_UTF16("foo"),
+                                 MOZ_UTF16("fo"),
                                  NS_LITERAL_STRING("")) &&
-         test_strip_chars_helper(NS_LITERAL_STRING("foo").get(),
-                                 NS_LITERAL_STRING("foo").get(),
+         test_strip_chars_helper(MOZ_UTF16("foo"),
+                                 MOZ_UTF16("foo"),
                                  NS_LITERAL_STRING("")) &&
-         test_strip_chars_helper(NS_LITERAL_STRING(" foo").get(),
-                                 NS_LITERAL_STRING(" ").get(),
+         test_strip_chars_helper(MOZ_UTF16(" foo"),
+                                 MOZ_UTF16(" "),
                                  NS_LITERAL_STRING(" foo"), 1);
 }
 
 static bool test_huge_capacity()
 {
   nsString a, b, c, d, e, f, g, h, i, j, k, l, m, n;
   nsCString n1;
   bool fail = false;
--- a/xpfe/components/directory/nsDirectoryViewer.cpp
+++ b/xpfe/components/directory/nsDirectoryViewer.cpp
@@ -456,26 +456,26 @@ nsHTTPIndex::OnIndexAvailable(nsIRequest
         rv = Assert(entry, kNC_LastModified, val, true);
       }
 
       // filetype
       uint32_t type;
       rv = aIndex->GetType(&type);
       switch (type) {
       case nsIDirIndex::TYPE_UNKNOWN:
-        rv = mDirRDF->GetLiteral(NS_LITERAL_STRING("UNKNOWN").get(), getter_AddRefs(lit));
+        rv = mDirRDF->GetLiteral(MOZ_UTF16("UNKNOWN"), getter_AddRefs(lit));
         break;
       case nsIDirIndex::TYPE_DIRECTORY:
-        rv = mDirRDF->GetLiteral(NS_LITERAL_STRING("DIRECTORY").get(), getter_AddRefs(lit));
+        rv = mDirRDF->GetLiteral(MOZ_UTF16("DIRECTORY"), getter_AddRefs(lit));
         break;
       case nsIDirIndex::TYPE_FILE:
-        rv = mDirRDF->GetLiteral(NS_LITERAL_STRING("FILE").get(), getter_AddRefs(lit));
+        rv = mDirRDF->GetLiteral(MOZ_UTF16("FILE"), getter_AddRefs(lit));
         break;
       case nsIDirIndex::TYPE_SYMLINK:
-        rv = mDirRDF->GetLiteral(NS_LITERAL_STRING("SYMLINK").get(), getter_AddRefs(lit));
+        rv = mDirRDF->GetLiteral(MOZ_UTF16("SYMLINK"), getter_AddRefs(lit));
         break;
       }
       
       if (NS_FAILED(rv)) return rv;
       rv = Assert(entry, kNC_FileType, lit, true);
       if (NS_FAILED(rv)) return rv;
     }
 
@@ -583,19 +583,19 @@ nsHTTPIndex::CommonInit()
                          getter_AddRefs(kNC_LastModified));
     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Content-Type"),
                          getter_AddRefs(kNC_ContentType));
     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "File-Type"),
                          getter_AddRefs(kNC_FileType));
     mDirRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "IsContainer"),
                          getter_AddRefs(kNC_IsContainer));
 
-    rv = mDirRDF->GetLiteral(NS_LITERAL_STRING("true").get(), getter_AddRefs(kTrueLiteral));
+    rv = mDirRDF->GetLiteral(MOZ_UTF16("true"), getter_AddRefs(kTrueLiteral));
     if (NS_FAILED(rv)) return(rv);
-    rv = mDirRDF->GetLiteral(NS_LITERAL_STRING("false").get(), getter_AddRefs(kFalseLiteral));
+    rv = mDirRDF->GetLiteral(MOZ_UTF16("false"), getter_AddRefs(kFalseLiteral));
     if (NS_FAILED(rv)) return(rv);
 
     rv = NS_NewISupportsArray(getter_AddRefs(mConnectionList));
     if (NS_FAILED(rv)) return(rv);
 
     // note: don't register DS here
     return rv;
 }