Merge last PGO-green changeset from mozilla-inbound to mozilla-central
authorEd Morley <bmo@edmorley.co.uk>
Thu, 22 Dec 2011 11:28:36 +0000
changeset 83323 c5b90ea7e475e362314174aeb8cbfdf0c7391572
parent 83322 ed47a41ba26a1486e960ace1d50e38d1f5609cca (current diff)
parent 83240 d9e4c34ca1c603d61fe986249324090c84d0b146 (diff)
child 83324 33473863f42cb9a2f4913f89bac6428b9ace6b4e
child 83561 5b8368af3d70d0945ca042ff4b88c572725454e3
child 105491 74c7f055b86b0abc20216c27b4ba67dfbd07d312
push id4356
push userphilringnalda@gmail.com
push dateSun, 25 Dec 2011 05:53:32 +0000
treeherdermozilla-inbound@798b00a6fe29 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone12.0a1
first release with
nightly linux32
c5b90ea7e475 / 12.0a1 / 20111222150239 / files
nightly linux64
c5b90ea7e475 / 12.0a1 / 20111222150239 / files
nightly mac
c5b90ea7e475 / 12.0a1 / 20111222150239 / files
nightly win32
c5b90ea7e475 / 12.0a1 / 20111222150239 / files
nightly win64
c5b90ea7e475 / 12.0a1 / 20111222150239 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge last PGO-green changeset from mozilla-inbound to mozilla-central
mobile/android/base/resources/drawable-land-v14/address_bar_texture.png
mobile/android/base/resources/drawable-land-v14/address_bar_url_bg.9.png
mobile/android/base/resources/drawable-land-v14/address_bar_url_outline.9.png
mobile/android/base/resources/drawable-land-v14/tabs_normal.png
mobile/android/base/resources/drawable-land-v14/tabs_pressed.png
mobile/android/base/resources/drawable-port-v14/address_bar_texture.png
mobile/android/base/resources/drawable-port-v14/address_bar_url_bg.9.png
mobile/android/base/resources/drawable-port-v14/address_bar_url_outline.9.png
mobile/android/base/resources/drawable-port-v14/tabs_normal.png
mobile/android/base/resources/drawable-port-v14/tabs_pressed.png
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -332,17 +332,17 @@ var Scratchpad = {
                                 "Scratchpad", 1);
     }
     catch (ex) {
       this.openWebConsole();
 
       let contentWindow = this.gBrowser.selectedBrowser.contentWindow;
 
       let scriptError = Cc["@mozilla.org/scripterror;1"].
-                        createInstance(Ci.nsIScriptError2);
+                        createInstance(Ci.nsIScriptError);
 
       scriptError.initWithWindowID(ex.message + "\n" + ex.stack, ex.fileName,
                                    "", ex.lineNumber, 0, scriptError.errorFlag,
                                    "content javascript",
                                    this.getInnerWindowId(contentWindow));
 
       Services.console.logMessage(scriptError);
 
--- a/browser/devtools/webconsole/HUDService.jsm
+++ b/browser/devtools/webconsole/HUDService.jsm
@@ -6522,17 +6522,16 @@ HUDConsoleObserver = {
   observe: function HCO_observe(aSubject, aTopic, aData)
   {
     if (aTopic == "xpcom-shutdown") {
       this.uninit();
       return;
     }
 
     if (!(aSubject instanceof Ci.nsIScriptError) ||
-        !(aSubject instanceof Ci.nsIScriptError2) ||
         !aSubject.outerWindowID) {
       return;
     }
 
     switch (aSubject.category) {
       // We ignore chrome-originating errors as we only
       // care about content.
       case "XPConnect JavaScript":
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_603750_websocket.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_603750_websocket.js
@@ -16,18 +16,17 @@ let errors = 0;
 let lastWindowId = 0;
 let oldPref_ws;
 
 let TestObserver = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
 
   observe: function test_observe(aSubject)
   {
-    if (!(aSubject instanceof Ci.nsIScriptError) ||
-        !(aSubject instanceof Ci.nsIScriptError2)) {
+    if (!(aSubject instanceof Ci.nsIScriptError)) {
       return;
     }
 
     is(aSubject.category, "Web Socket", "received a Web Socket error");
     isnot(aSubject.sourceName.indexOf("test-bug-603750-websocket.js"), -1,
           "sourceName is correct");
 
     if (++errors == 2) {
--- a/build/binary-location.mk
+++ b/build/binary-location.mk
@@ -35,17 +35,17 @@
 # 
 # ***** END LICENSE BLOCK *****
 
 # finds the location of the browser and puts it in the variable $(browser_path)
 
 ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
 PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
 else
-ifeq ($(MOZ_BUILD_APP),mobile)
+ifeq ($(MOZ_BUILD_APP),mobile/xul)
 PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
 else
 PROGRAM = $(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
 endif
 endif
 
 TARGET_DIST = $(TARGET_DEPTH)/dist
 
--- a/config/system-headers
+++ b/config/system-headers
@@ -526,16 +526,17 @@ netinet/in_systm.h
 netinet/tcp.h
 new
 newexe.h
 new.h
 nl_types.h
 NodeInfo.h
 nss.h
 nssilock.h
+nsswitch.h
 objbase.h
 objidl.h
 Objsafe.h
 ojiapitests.h
 ole2.h
 oleidl.h
 OpenGL/OpenGL.h
 OpenTptInternet.h
@@ -745,16 +746,17 @@ sys/stack.h
 sys/statfs.h
 sys/stat.h
 sys/statvfs.h
 sys/syscall.h
 sys/sysctl.h
 sys/sysinfo.h
 sys/sysmp.h
 sys/syssgi.h
+sys/system_properties.h
 sys/systeminfo.h
 sys/timeb.h
 sys/time.h
 sys/times.h
 sys/ttycom.h
 sys/types.h
 sys/ucontext.h
 sys/uio.h
--- a/content/base/src/nsAttrAndChildArray.h
+++ b/content/base/src/nsAttrAndChildArray.h
@@ -39,16 +39,18 @@
 /*
  * Storage of the children and attributes of a DOM node; storage for
  * the two is unified to minimize footprint.
  */
 
 #ifndef nsAttrAndChildArray_h___
 #define nsAttrAndChildArray_h___
 
+#include "mozilla/Attributes.h"
+
 #include "nscore.h"
 #include "nsAttrName.h"
 #include "nsAttrValue.h"
 
 class nsINode;
 class nsIContent;
 class nsMappedAttributes;
 class nsHTMLStyleSheet;
@@ -131,18 +133,18 @@ public:
   {
     return AttrSlotCount() < ATTRCHILD_ARRAY_MAX_ATTR_COUNT ||
            !AttrSlotIsTaken(ATTRCHILD_ARRAY_MAX_ATTR_COUNT - 1);
   }
 
   PRInt64 SizeOf() const;
 
 private:
-  nsAttrAndChildArray(const nsAttrAndChildArray& aOther); // Not to be implemented
-  nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther); // Not to be implemented
+  nsAttrAndChildArray(const nsAttrAndChildArray& aOther) MOZ_DELETE;
+  nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther) MOZ_DELETE;
 
   void Clear();
 
   PRUint32 NonMappedAttrCount() const;
   PRUint32 MappedAttrCount() const;
 
   nsresult GetModifiableMapped(nsMappedAttributeElement* aContent,
                                nsHTMLStyleSheet* aSheet,
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -2826,30 +2826,29 @@ nsContentUtils::ReportToConsole(PRUint32
     rv = GetLocalizedString(aFile, aMessageName, errorText);
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCAutoString spec;
   if (aURI)
     aURI->GetSpec(spec);
 
-  nsCOMPtr<nsIScriptError2> errorObject =
+  nsCOMPtr<nsIScriptError> errorObject =
       do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = errorObject->InitWithWindowID(errorText.get(),
                                      NS_ConvertUTF8toUTF16(spec).get(), // file name
                                      aSourceLine.get(),
                                      aLineNumber, aColumnNumber,
                                      aErrorFlags, aCategory,
                                      innerWindowID);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIScriptError> logError = do_QueryInterface(errorObject);
-  return sConsoleService->LogMessage(logError);
+  return sConsoleService->LogMessage(errorObject);
 }
 
 bool
 nsContentUtils::IsChromeDoc(nsIDocument *aDocument)
 {
   if (!aDocument) {
     return false;
   }
--- a/content/base/src/nsEventSource.cpp
+++ b/content/base/src/nsEventSource.cpp
@@ -1086,41 +1086,41 @@ nsEventSource::PrintErrorOnConsole(const
   nsresult rv =
     bundleService->CreateBundle(aBundleURI, getter_AddRefs(strBundle));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIConsoleService> console(
     do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIScriptError2> errObj(
+  nsCOMPtr<nsIScriptError> errObj(
     do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Localize the error message
   nsXPIDLString message;
   if (aFormatStrings) {
     rv = strBundle->FormatStringFromName(aError, aFormatStrings,
                                          aFormatStringsLen,
                                          getter_Copies(message));
   } else {
     rv = strBundle->GetStringFromName(aError, getter_Copies(message));
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
-  errObj->InitWithWindowID(message.get(),
-                           mScriptFile.get(),
-                           nsnull,
-                           mScriptLine, 0,
-                           nsIScriptError::errorFlag,
-                           "Event Source", mInnerWindowID);
+  rv = errObj->InitWithWindowID(message.get(),
+                                mScriptFile.get(),
+                                nsnull,
+                                mScriptLine, 0,
+                                nsIScriptError::errorFlag,
+                                "Event Source", mInnerWindowID);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   // print the error message directly to the JS console
-  nsCOMPtr<nsIScriptError> logError = do_QueryInterface(errObj);
-  rv = console->LogMessage(logError);
+  rv = console->LogMessage(errObj);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 nsEventSource::ConsoleError()
 {
--- a/content/base/src/nsWebSocket.cpp
+++ b/content/base/src/nsWebSocket.cpp
@@ -122,40 +122,40 @@ nsWebSocket::PrintErrorOnConsole(const c
   nsCOMPtr<nsIStringBundle> strBundle;
   rv = bundleService->CreateBundle(aBundleURI, getter_AddRefs(strBundle));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIConsoleService> console(
     do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIScriptError2> errorObject(
+  nsCOMPtr<nsIScriptError> errorObject(
     do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Localize the error message
   nsXPIDLString message;
   if (aFormatStrings) {
     rv = strBundle->FormatStringFromName(aError, aFormatStrings,
                                          aFormatStringsLen,
                                          getter_Copies(message));
   } else {
     rv = strBundle->GetStringFromName(aError, getter_Copies(message));
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
-  errorObject->InitWithWindowID(message.get(),
-                                NS_ConvertUTF8toUTF16(mScriptFile).get(),
-                                nsnull, mScriptLine, 0,
-                                nsIScriptError::errorFlag, "Web Socket",
-                                mInnerWindowID);
+  rv = errorObject->InitWithWindowID(message.get(),
+                                     NS_ConvertUTF8toUTF16(mScriptFile).get(),
+                                     nsnull, mScriptLine, 0,
+                                     nsIScriptError::errorFlag, "Web Socket",
+                                     mInnerWindowID);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   // print the error message directly to the JS console
-  nsCOMPtr<nsIScriptError> logError(do_QueryInterface(errorObject));
-  rv = console->LogMessage(logError);
+  rv = console->LogMessage(errorObject);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 // when this is called the browser side wants no more part of it
 nsresult
 nsWebSocket::CloseConnection()
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -4503,16 +4503,41 @@ nsEventStateManager::UpdateAncestorState
     }
     Element* element = aStartNode->AsElement();
     DoStateChange(element, aState, aAddState);
     Element* labelTarget = GetLabelTarget(element);
     if (labelTarget) {
       DoStateChange(labelTarget, aState, aAddState);
     }
   }
+
+  if (aAddState) {
+    // We might be in a situation where a node was in hover both
+    // because it was hovered and because the label for it was
+    // hovered, and while we stopped hovering the node the label is
+    // still hovered.  Or we might have had two nested labels for the
+    // same node, and while one is no longer hovered the other still
+    // is.  In that situation, the label that's still hovered will be
+    // aStopBefore or some ancestor of it, and the call we just made
+    // to UpdateAncestorState with aAddState = false would have
+    // removed the hover state from the node.  But the node should
+    // still be in hover state.  To handle this situation we need to
+    // keep walking up the tree and any time we find a label mark its
+    // corresponding node as still in our state.
+    for ( ; aStartNode; aStartNode = aStartNode->GetParent()) {
+      if (!aStartNode->IsElement()) {
+        continue;
+      }
+
+      Element* labelTarget = GetLabelTarget(aStartNode->AsElement());
+      if (labelTarget && !labelTarget->State().HasState(aState)) {
+        DoStateChange(labelTarget, aState, true);
+      }
+    }
+  }
 }
 
 bool
 nsEventStateManager::SetContentState(nsIContent *aContent, nsEventStates aState)
 {
   // We manage 4 states here: ACTIVE, HOVER, DRAGOVER, URLTARGET
   // The input must be exactly one of them.
   NS_PRECONDITION(aState == NS_EVENT_STATE_ACTIVE ||
--- a/content/events/test/test_bug656379-2.html
+++ b/content/events/test/test_bug656379-2.html
@@ -4,47 +4,68 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id=656379
 -->
 <head>
   <title>Test for Bug 656379</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <style>
-    button:hover { color: green; }
+    input[type="button"]:hover { color: green; }
   </style>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=656379">Mozilla Bug 656379</a>
 <p id="display">
   <label for="button1" id="label1">Label 1</label>
-  <button id="button1">Button 1</button>
-  <label><span id="label2">Label 2</span><button id="button2">Button 2</button></label>
+  <input type="button" id="button1" value="Button 1">
+  <label>
+    <span id="label2">Label 2</span>
+    <input type="button" id="button2" value="Button 2">
+  </label>
 </p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript;version=1.8">
 
 /** Test for Bug 656379 **/
 SimpleTest.waitForExplicitFinish();
 function tests() {
   synthesizeMouseAtCenter($("label1"), { type: "mousemove" });
   yield;
   is($("button1").mozMatchesSelector(":hover"), true,
-     "Button 1 should be hovered");
+     "Button 1 should be hovered after mousemove over label1");
+  is($("label1").mozMatchesSelector(":hover"), true,
+     "Label 1 should be hovered after mousemove over label1");
   is($("button2").mozMatchesSelector(":hover"), false,
-     "Button 2 should not be hovered");
+     "Button 2 should not be hovered after mousemove over label1");
+  is($("label2").mozMatchesSelector(":hover"), false,
+     "Label 2 should not be hovered after mousemove over label1");
+  synthesizeMouseAtCenter($("button2"), { type: "mousemove" });
+  yield;
+  is($("button1").mozMatchesSelector(":hover"), false,
+     "Button 1 should not be hovered after mousemove over button2");
+  is($("label1").mozMatchesSelector(":hover"), false,
+     "Label 1 should not be hovered after mousemove over button2");
+  is($("button2").mozMatchesSelector(":hover"), true,
+     "Button 2 should be hovered after mousemove over button2");
+  is($("label2").mozMatchesSelector(":hover"), false,
+     "Label 2 should not be hovered after mousemove over label2");
   synthesizeMouseAtCenter($("label2"), { type: "mousemove" });
   yield;
   is($("button1").mozMatchesSelector(":hover"), false,
-     "Button 1 should not be hovered");
+     "Button 1 should not be hovered after mousemove over label2");
+  is($("label1").mozMatchesSelector(":hover"), false,
+     "Label 1 should not be hovered after mousemove over label2");
   is($("button2").mozMatchesSelector(":hover"), true,
-     "Button 2 should be hovered");
+     "Button 2 should be hovered after mousemove over label2");
+  is($("label2").mozMatchesSelector(":hover"), true,
+     "Label 2 should be hovered after mousemove over label2");
   SimpleTest.finish();
 }
 
 function executeTests() {
   var testYielder = tests();
   function execNext() {
     try {
       testYielder.next();
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -351,16 +351,26 @@ public:
    * increasing during playback.
    */
   void FireTimeUpdate(bool aPeriodic);
 
 protected:
   class MediaLoadListener;
 
   /**
+   * Logs a warning message to the web console to report various failures.
+   * aMsg is the localized message identifier, aParams is the parameters to
+   * be substituted into the localized message, and aParamCount is the number
+   * of parameters in aParams.
+   */
+  void ReportLoadError(const char* aMsg,
+                       const PRUnichar** aParams = nsnull,
+                       PRUint32 aParamCount = 0);
+
+  /**
    * Changes mHasPlayedOrSeeked to aValue. If mHasPlayedOrSeeked changes
    * we'll force a reflow so that the video frame gets reflowed to reflect
    * the poster hiding or showing immediately.
    */
   void SetPlayedOrSeeked(bool aValue);
 
   /**
    * Create a decoder for the given aMIMEType. Returns null if we
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -85,16 +85,18 @@
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIAppShell.h"
 #include "nsWidgetsCID.h"
 
 #include "nsIPrivateDOMEvent.h"
 #include "nsIDOMNotifyAudioAvailableEvent.h"
 #include "nsMediaFragmentURIParser.h"
 #include "nsURIHashKey.h"
+#include "nsContentUtils.h"
+#include "nsIScriptError.h"
 
 #ifdef MOZ_OGG
 #include "nsOggDecoder.h"
 #endif
 #ifdef MOZ_WAVE
 #include "nsWaveDecoder.h"
 #endif
 #ifdef MOZ_WEBM
@@ -277,16 +279,30 @@ nsHTMLMediaElement::MediaLoadListener::O
 {
   nsContentUtils::UnregisterShutdownObserver(this);
 
   // Clear mElement to break cycle so we don't leak on shutdown
   mElement = nsnull;
   return NS_OK;
 }
 
+void nsHTMLMediaElement::ReportLoadError(const char* aMsg,
+                                         const PRUnichar** aParams,
+                                         PRUint32 aParamCount)
+{
+  nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
+                                  "Media",
+                                  OwnerDoc(),
+                                  nsContentUtils::eDOM_PROPERTIES,
+                                  aMsg,
+                                  aParams,
+                                  aParamCount);
+}
+
+
 NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
 {
   nsContentUtils::UnregisterShutdownObserver(this);
 
   // The element is only needed until we've had a chance to call
   // InitializeDecoderForChannel. So make sure mElement is cleared here.
   nsRefPtr<nsHTMLMediaElement> element;
   element.swap(mElement);
@@ -303,16 +319,31 @@ NS_IMETHODIMP nsHTMLMediaElement::MediaL
   nsresult rv = aRequest->GetStatus(&status);
   NS_ENSURE_SUCCESS(rv, rv);
   if (NS_FAILED(status)) {
     if (element)
       element->NotifyLoadError();
     return status;
   }
 
+  nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(aRequest);
+  bool succeeded;
+  if (hc && NS_SUCCEEDED(hc->GetRequestSucceeded(&succeeded)) && !succeeded) {
+    element->NotifyLoadError();
+    PRUint32 responseStatus = 0;
+    hc->GetResponseStatus(&responseStatus);
+    nsAutoString code;
+    code.AppendInt(responseStatus);
+    nsAutoString src;
+    element->GetCurrentSrc(src);
+    const PRUnichar* params[] = { code.get(), src.get() };
+    element->ReportLoadError("MediaLoadHttpError", params, ArrayLength(params));
+    return NS_BINDING_ABORTED;
+  }
+
   nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
   if (channel &&
       element &&
       NS_SUCCEEDED(rv = element->InitializeDecoderForChannel(channel, getter_AddRefs(mNextListener))) &&
       mNextListener) {
     rv = mNextListener->OnStartRequest(aRequest, aContext);
   } else {
     // If InitializeDecoderForChannel() returned an error, fire a network
@@ -659,16 +690,19 @@ void nsHTMLMediaElement::SelectResource(
         return;
       }
 
       rv = LoadResource();
       if (NS_SUCCEEDED(rv)) {
         mIsRunningSelectResource = false;
         return;
       }
+    } else {
+      const PRUnichar* params[] = { src.get() };
+      ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params));
     }
     NoSupportedMediaSourceError();
   } else {
     // Otherwise, the source elements will be used.
     mIsLoadingFromSourceChildren = true;
     LoadFromSourceChildren();
   }
   mIsRunningSelectResource = false;
@@ -717,40 +751,46 @@ void nsHTMLMediaElement::LoadFromSourceC
   while (true) {
     nsIContent* child = GetNextSource();
     if (!child) {
       // Exhausted candidates, wait for more candidates to be appended to
       // the media element.
       mLoadWaitStatus = WAITING_FOR_SOURCE;
       mNetworkState = nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE;
       ChangeDelayLoadStatus(false);
+      ReportLoadError("MediaLoadExhaustedCandidates");
       return;
     }
 
     // Must have src attribute.
     nsAutoString src;
     if (!child->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
+      ReportLoadError("MediaLoadSourceMissingSrc");
       DispatchAsyncSourceError(child);
       continue;
     }
 
     // If we have a type attribute, it must be a supported type.
     nsAutoString type;
     if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type) &&
         GetCanPlay(type) == CANPLAY_NO) {
       DispatchAsyncSourceError(child);
+      const PRUnichar* params[] = { type.get(), src.get() };
+      ReportLoadError("MediaLoadUnsupportedType", params, ArrayLength(params));
       continue;
     }
     LOG(PR_LOG_DEBUG, ("%p Trying load from <source>=%s type=%s", this,
       NS_ConvertUTF16toUTF8(src).get(), NS_ConvertUTF16toUTF8(type).get()));
 
     nsCOMPtr<nsIURI> uri;
     NewURIFromString(src, getter_AddRefs(uri));
     if (!uri) {
       DispatchAsyncSourceError(child);
+      const PRUnichar* params[] = { src.get() };
+      ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params));
       continue;
     }
 
     mLoadingSrc = uri;
     NS_ASSERTION(mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING,
                  "Network state should be loading");
 
     if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) {
@@ -1946,16 +1986,21 @@ nsresult nsHTMLMediaElement::InitializeD
 {
   NS_ASSERTION(mLoadingSrc, "mLoadingSrc must already be set");
 
   nsCAutoString mimeType;
   aChannel->GetContentType(mimeType);
 
   nsRefPtr<nsMediaDecoder> decoder = CreateDecoder(mimeType);
   if (!decoder) {
+    nsAutoString src;
+    GetCurrentSrc(src);
+    NS_ConvertUTF8toUTF16 mimeUTF16(mimeType);
+    const PRUnichar* params[] = { mimeUTF16.get(), src.get() };
+    ReportLoadError("MediaLoadUnsupportedMimeType", params, ArrayLength(params));
     return NS_ERROR_FAILURE;
   }
 
   LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mimeType.get()));
 
   mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
 
   nsMediaStream* stream = nsMediaStream::Create(decoder, aChannel);
@@ -2115,16 +2160,21 @@ void nsHTMLMediaElement::ResourceLoaded(
 
 void nsHTMLMediaElement::NetworkError()
 {
   Error(nsIDOMMediaError::MEDIA_ERR_NETWORK);
 }
 
 void nsHTMLMediaElement::DecodeError()
 {
+  nsAutoString src;
+  GetCurrentSrc(src);
+  const PRUnichar* params[] = { src.get() };
+  ReportLoadError("MediaLoadDecodeError", params, ArrayLength(params));
+
   if (mDecoder) {
     RemoveMediaElementFromURITable();
     mDecoder->Shutdown();
     mDecoder = nsnull;
   }
   mLoadingSrc = nsnull;
   if (mIsLoadingFromSourceChildren) {
     mError = nsnull;
--- a/content/xml/document/src/nsXMLDocument.cpp
+++ b/content/xml/document/src/nsXMLDocument.cpp
@@ -396,34 +396,33 @@ nsXMLDocument::Load(const nsAString& aUr
     if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) {
       nsCAutoString spec;
       if (mDocumentURI)
         mDocumentURI->GetSpec(spec);
 
       nsAutoString error;
       error.AssignLiteral("Cross site loading using document.load is no "
                           "longer supported. Use XMLHttpRequest instead.");
-      nsCOMPtr<nsIScriptError2> errorObject =
+      nsCOMPtr<nsIScriptError> errorObject =
           do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
       rv = errorObject->InitWithWindowID(error.get(), NS_ConvertUTF8toUTF16(spec).get(),
                                          nsnull, 0, 0, nsIScriptError::warningFlag,
                                          "DOM",
                                          callingDoc ?
                                            callingDoc->InnerWindowID() :
                                            this->InnerWindowID());
 
       NS_ENSURE_SUCCESS(rv, rv);
 
       nsCOMPtr<nsIConsoleService> consoleService =
         do_GetService(NS_CONSOLESERVICE_CONTRACTID);
-      nsCOMPtr<nsIScriptError> logError = do_QueryInterface(errorObject);
-      if (consoleService && logError) {
-        consoleService->LogMessage(logError);
+      if (consoleService) {
+        consoleService->LogMessage(errorObject);
       }
 
       return NS_ERROR_DOM_SECURITY_ERR;
     }
   }
 
   // Partial Reset, need to restore principal for security reasons and
   // event listener manager so that load listeners etc. will
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1723,17 +1723,17 @@ PrintWarningOnConsole(JSContext *cx, con
   }
 
   nsCOMPtr<nsIConsoleService> consoleService
     (do_GetService(NS_CONSOLESERVICE_CONTRACTID));
   if (!consoleService) {
     return;
   }
 
-  nsCOMPtr<nsIScriptError2> scriptError =
+  nsCOMPtr<nsIScriptError> scriptError =
     do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
   if (!scriptError) {
     return;
   }
 
   JSStackFrame *fp, *iterator = nsnull;
   fp = ::JS_FrameIterator(cx, &iterator);
   PRUint32 lineno = 0;
@@ -1756,19 +1756,18 @@ PrintWarningOnConsole(JSContext *cx, con
                                               sourcefile.get(),
                                               EmptyString().get(),
                                               lineno,
                                               0, // column for error is not available
                                               nsIScriptError::warningFlag,
                                               "DOM:HTML",
                                               nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx));
 
-  if (NS_SUCCEEDED(rv)){
-    nsCOMPtr<nsIScriptError> logError = do_QueryInterface(scriptError);
-    consoleService->LogMessage(logError);
+  if (NS_SUCCEEDED(rv)) {
+    consoleService->LogMessage(scriptError);
   }
 }
 
 static inline JSString *
 IdToString(JSContext *cx, jsid id)
 {
   if (JSID_IS_STRING(id))
     return JSID_TO_STRING(id);
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -366,28 +366,20 @@ public:
                      "nsIScriptObjectPrincipal");
         nsCOMPtr<nsIPrincipal> systemPrincipal;
         sSecurityManager->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
         const char * category =
           scriptPrincipal->GetPrincipal() == systemPrincipal
           ? "chrome javascript"
           : "content javascript";
 
-        nsCOMPtr<nsIScriptError2> error2(do_QueryInterface(errorObject));
-        if (error2) {
-          rv = error2->InitWithWindowID(mErrorMsg.get(), mFileName.get(),
-                                        mSourceLine.get(),
-                                        mLineNr, mColumn, mFlags,
-                                        category, mInnerWindowID);
-        } else {
-          rv = errorObject->Init(mErrorMsg.get(), mFileName.get(),
-                                 mSourceLine.get(),
-                                 mLineNr, mColumn, mFlags,
-                                 category);
-        }
+        rv = errorObject->InitWithWindowID(mErrorMsg.get(), mFileName.get(),
+                                           mSourceLine.get(),
+                                           mLineNr, mColumn, mFlags,
+                                           category, mInnerWindowID);
 
         if (NS_SUCCEEDED(rv)) {
           nsCOMPtr<nsIConsoleService> consoleService =
             do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv);
           if (NS_SUCCEEDED(rv)) {
             consoleService->LogMessage(errorObject);
           }
         }
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -131,8 +131,20 @@ FullScreenDeniedNotFocusedTab=Request fo
 RemovedFullScreenElement=Exited full-screen because full-screen element was removed from document.
 FocusedWindowedPluginWhileFullScreen=Exited full-screen because windowed plugin was focused.
 HTMLMultipartXHRWarning=HTML parsing in XMLHttpRequest is not supported for multipart responses.
 HTMLSyncXHRWarning=HTML parsing in XMLHttpRequest is not supported in the synchronous mode.
 InvalidRedirectChannelWarning=Unable to redirect to %S because the channel doesn't implement nsIWritablePropertyBag2.
 ResponseTypeSyncXHRWarning=Use of XMLHttpRequest's responseType attribute is no longer supported in the synchronous mode in window context.
 WithCredentialsSyncXHRWarning=Use of XMLHttpRequest's withCredentials attribute is no longer supported in the synchronous mode in window context.
 JSONCharsetWarning=An attempt was made to declare a non-UTF-8 encoding for JSON retrieved using XMLHttpRequest. Only UTF-8 is supported for decoding JSON.
+MediaLoadExhaustedCandidates=All candidate resources failed to load. Media load paused.
+MediaLoadSourceMissingSrc=<source> element has no "src" attribute. Media resource load failed.
+# LOCALIZATION NOTE: %1$S is the Http error code the server returned (e.g. 404, 500, etc), %2$S is the URL of the media resource which failed to load.
+MediaLoadHttpError=HTTP load failed with status %1$S. Load of media resource %2$S failed.
+# LOCALIZATION NOTE: %S is the URL of the media resource which failed to load.
+MediaLoadInvalidURI=Invalid URI. Load of media resource %S failed.
+# LOCALIZATION NOTE: %1$S is the media resource's format/codec type (basically equivalent to the file type, e.g. MP4,AVI,WMV,MOV etc), %2$S is the URL of the media resource which failed to load.
+MediaLoadUnsupportedType=Specified "type" of "%1$S" is not supported. Load of media resource %2$S failed.
+# LOCALIZATION NOTE: %1$S is the MIME type HTTP header being sent by the web server, %2$S is the URL of the media resource which failed to load.
+MediaLoadUnsupportedMimeType=HTTP "Content-Type" of "%1$S" is not supported. Load of media resource %2$S failed.
+# LOCALIZATION NOTE: %S is the URL of the media resource which failed to load because of error in decoding.
+MediaLoadDecodeError=Media resource %S could not be decoded.
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1104,46 +1104,41 @@ public:
       nsRefPtr<ReportErrorRunnable> runnable =
         new ReportErrorRunnable(aWorkerPrivate, aMessage, aFilename, aLine,
                                 aLineNumber, aColumnNumber, aFlags,
                                 aErrorNumber);
       return runnable->Dispatch(aCx);
     }
 
     // Otherwise log an error to the error console.
-    nsCOMPtr<nsIScriptError2> scriptError =
+    nsCOMPtr<nsIScriptError> scriptError =
       do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
-    NS_WARN_IF_FALSE(scriptError, "Faild to create script error!");
-
-    nsCOMPtr<nsIConsoleMessage> consoleMessage;
+    NS_WARN_IF_FALSE(scriptError, "Failed to create script error!");
 
     if (scriptError) {
-      if (NS_SUCCEEDED(scriptError->InitWithWindowID(aMessage.get(),
-                                                     aFilename.get(),
-                                                     aLine.get(), aLineNumber,
-                                                     aColumnNumber, aFlags,
-                                                     "Web Worker",
-                                                     aInnerWindowId))) {
-        consoleMessage = do_QueryInterface(scriptError);
-        NS_ASSERTION(consoleMessage, "This should never fail!");
-      }
-      else {
+      if (NS_FAILED(scriptError->InitWithWindowID(aMessage.get(),
+                                                  aFilename.get(),
+                                                  aLine.get(), aLineNumber,
+                                                  aColumnNumber, aFlags,
+                                                  "Web Worker",
+                                                  aInnerWindowId))) {
         NS_WARNING("Failed to init script error!");
+        scriptError = nsnull;
       }
     }
 
     nsCOMPtr<nsIConsoleService> consoleService =
       do_GetService(NS_CONSOLESERVICE_CONTRACTID);
-    NS_WARN_IF_FALSE(consoleService, "Faild to get console service!");
+    NS_WARN_IF_FALSE(consoleService, "Failed to get console service!");
 
     bool logged = false;
 
     if (consoleService) {
-      if (consoleMessage) {
-        if (NS_SUCCEEDED(consoleService->LogMessage(consoleMessage))) {
+      if (scriptError) {
+        if (NS_SUCCEEDED(consoleService->LogMessage(scriptError))) {
           logged = true;
         }
         else {
           NS_WARNING("Failed to log script error!");
         }
       }
       else if (NS_SUCCEEDED(consoleService->LogStringMessage(aMessage.get()))) {
         logged = true;
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -615,29 +615,40 @@ nsPermissionManager::RemoveAll()
 {
   ENSURE_NOT_CHILD_PROCESS;
 
   nsresult rv = RemoveAllInternal();
   NotifyObservers(nsnull, NS_LITERAL_STRING("cleared").get());
   return rv;
 }
 
+void
+nsPermissionManager::CloseDB()
+{
+  // Null the statements, this will finalize them.
+  mStmtInsert = nsnull;
+  mStmtDelete = nsnull;
+  mStmtUpdate = nsnull;
+  if (mDBConn) {
+    mozilla::DebugOnly<nsresult> rv = mDBConn->Close();
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
+    mDBConn = nsnull;
+  }
+}
+
 nsresult
 nsPermissionManager::RemoveAllInternal()
 {
   RemoveAllFromMemory();
 
   // clear the db
   if (mDBConn) {
     nsresult rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_hosts"));
     if (NS_FAILED(rv)) {
-      mStmtInsert = nsnull;
-      mStmtDelete = nsnull;
-      mStmtUpdate = nsnull;
-      mDBConn = nsnull;
+      CloseDB();
       rv = InitDB(true);
       return rv;
     }
   }
 
   return NS_OK;
 }
 
@@ -787,22 +798,17 @@ NS_IMETHODIMP nsPermissionManager::Obser
     // The profile is about to change,
     // or is going away because the application is shutting down.
     if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
       // clear the permissions file
       RemoveAllInternal();
     } else {
       RemoveAllFromMemory();
     }
-    if (mDBConn) {
-      // Null the statements, this will finalize them.
-      mStmtInsert = nsnull;
-      mStmtDelete = nsnull;
-      mStmtUpdate = nsnull;
-    }
+    CloseDB();
   }
   else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
     // the profile has already changed; init the db from the new location
     InitDB(false);
   }
 
   return NS_OK;
 }
--- a/extensions/cookie/nsPermissionManager.h
+++ b/extensions/cookie/nsPermissionManager.h
@@ -217,16 +217,20 @@ private:
   nsresult Read();
   void     NotifyObserversWithPermission(const nsACString &aHost,
                                          const nsCString  &aType,
                                          PRUint32          aPermission,
                                          PRUint32          aExpireType,
                                          PRInt64           aExpireTime,
                                          const PRUnichar  *aData);
   void     NotifyObservers(nsIPermission *aPermission, const PRUnichar *aData);
+
+  // Finalize all statements, close the DB and null it.
+  void     CloseDB();
+
   nsresult RemoveAllInternal();
   nsresult RemoveAllFromMemory();
   nsresult NormalizeToACE(nsCString &aHost);
   nsresult GetHost(nsIURI *aURI, nsACString &aResult);
   static void UpdateDB(OperationType         aOp,
                        mozIStorageStatement* aStmt,
                        PRInt64               aID,
                        const nsACString     &aHost,
--- a/gfx/thebes/gfxQuartzNativeDrawing.h
+++ b/gfx/thebes/gfxQuartzNativeDrawing.h
@@ -33,16 +33,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _GFXQUARTZNATIVEDRAWING_H_
 #define _GFXQUARTZNATIVEDRAWING_H_
 
+#include "mozilla/Attributes.h"
+
 #include "gfxContext.h"
 #include "gfxQuartzSurface.h"
 
 class THEBES_API gfxQuartzNativeDrawing {
 public:
 
     /* Create native Quartz drawing for a rectangle bounded by
      * nativeRect.
@@ -66,18 +68,18 @@ public:
      * for drawing after that time, the result is undefined. */
     CGContextRef BeginNativeDrawing();
 
     /* Marks the end of native drawing */
     void EndNativeDrawing();
 
 private:
     // don't allow copying via construction or assignment
-    gfxQuartzNativeDrawing(const gfxQuartzNativeDrawing&);
-    const gfxQuartzNativeDrawing& operator=(const gfxQuartzNativeDrawing&);
+    gfxQuartzNativeDrawing(const gfxQuartzNativeDrawing&) MOZ_DELETE;
+    const gfxQuartzNativeDrawing& operator=(const gfxQuartzNativeDrawing&) MOZ_DELETE;
 
     // Final destination context
     nsRefPtr<gfxContext> mContext;
     // context that draws to mQuartzSurface; can be different from mContext
     // if mContext is not drawing to Quartz
     nsRefPtr<gfxContext> mSurfaceContext;
     gfxRect mNativeRect;
 
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -66,17 +66,17 @@ class nsIDOMWindow;
 
 namespace mozilla {
 
 namespace hal {
 
 class WindowIdentifier;
 
 extern PRLogModuleInfo *sHalLog;
-#define HAL_LOG(msg) PR_LOG(sHalLog, PR_LOG_DEBUG, msg)
+#define HAL_LOG(msg) PR_LOG(mozilla::hal::sHalLog, PR_LOG_DEBUG, msg)
 
 } // namespace hal
 
 namespace MOZ_HAL_NAMESPACE {
 
 /**
  * Turn the default vibrator device on/off per the pattern specified
  * by |pattern|.  Each element in the pattern is the number of
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -40,33 +40,175 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "hardware_legacy/uevent.h"
 #include "Hal.h"
 #include "mozilla/dom/battery/Constants.h"
 #include "mozilla/FileUtils.h"
 #include "nsAlgorithm.h"
 #include "nsThreadUtils.h"
+#include "mozilla/Monitor.h"
+#include "mozilla/Services.h"
+#include "mozilla/FileUtils.h"
+#include "nsThreadUtils.h"
+#include "nsIRunnable.h"
+#include "nsIThread.h"
+#include "nsIObserver.h"
+#include "nsIObserverService.h"
+#include "hardware_legacy/vibrator.h"
 #include <stdio.h>
 #include <math.h>
 #include <fcntl.h>
 #include <errno.h>
 
 using mozilla::hal::WindowIdentifier;
 
 namespace mozilla {
 namespace hal_impl {
 
-void
-Vibrate(const nsTArray<uint32>& pattern, const WindowIdentifier &)
-{}
+namespace {
+
+/**
+ * This runnable runs for the lifetime of the program, once started.  It's
+ * responsible for "playing" vibration patterns.
+ */
+class VibratorRunnable
+  : public nsIRunnable
+  , public nsIObserver
+{
+public:
+  VibratorRunnable()
+    : mMonitor("VibratorRunnable")
+    , mIndex(0)
+    , mShuttingDown(false)
+  {
+    nsCOMPtr<nsIObserverService> os = services::GetObserverService();
+    if (!os) {
+      NS_WARNING("Could not get observer service!");
+      return;
+    }
+
+    os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, /* weak ref */ true);
+  } 
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIRUNNABLE
+  NS_DECL_NSIOBSERVER
+
+  // Run on the main thread, not the vibrator thread.
+  void Vibrate(const nsTArray<uint32> &pattern);
+  void CancelVibrate();
+
+private:
+  Monitor mMonitor;
+
+  // The currently-playing pattern.
+  nsTArray<uint32> mPattern;
+
+  // The index we're at in the currently-playing pattern.  If mIndex >=
+  // mPattern.Length(), then we're not currently playing anything.
+  uint32 mIndex;
+
+  // Set to true in our shutdown observer.  When this is true, we kill the
+  // vibrator thread.
+  bool mShuttingDown;
+};
+
+NS_IMPL_ISUPPORTS2(VibratorRunnable, nsIRunnable, nsIObserver);
+
+NS_IMETHODIMP
+VibratorRunnable::Run()
+{
+  MonitorAutoLock lock(mMonitor);
+
+  // We currently assume that mMonitor.Wait(X) waits for X milliseconds.  But in
+  // reality, the kernel might not switch to this thread for some time after the
+  // wait expires.  So there's potential for some inaccuracy here.
+  //
+  // This doesn't worry me too much.  Note that we don't even start vibrating
+  // immediately when VibratorRunnable::Vibrate is called -- we go through a
+  // condvar onto another thread.  Better just to be chill about small errors in
+  // the timing here.
+
+  while (!mShuttingDown) {
+    if (mIndex < mPattern.Length()) {
+      uint32 duration = mPattern[mIndex];
+      if (mIndex % 2 == 0) {
+        vibrator_on(duration);
+      }
+      mIndex++;
+      mMonitor.Wait(PR_MillisecondsToInterval(duration));
+    }
+    else {
+      mMonitor.Wait();
+    }
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+VibratorRunnable::Observe(nsISupports *subject, const char *topic,
+                          const PRUnichar *data)
+{
+  MOZ_ASSERT(strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0);
+  MonitorAutoLock lock(mMonitor);
+  mShuttingDown = true;
+  mMonitor.Notify();
+  return NS_OK;
+}
 
 void
-CancelVibrate(const WindowIdentifier &)
-{}
+VibratorRunnable::Vibrate(const nsTArray<uint32> &pattern)
+{
+  MonitorAutoLock lock(mMonitor);
+  mPattern = pattern;
+  mIndex = 0;
+  mMonitor.Notify();
+}
+
+void
+VibratorRunnable::CancelVibrate()
+{
+  MonitorAutoLock lock(mMonitor);
+  mPattern.Clear();
+  mPattern.AppendElement(0);
+  mIndex = 0;
+  mMonitor.Notify();
+}
+
+VibratorRunnable *sVibratorRunnable = NULL;
+
+void
+EnsureVibratorThreadInitialized()
+{
+  if (sVibratorRunnable) {
+    return;
+  }
+
+  nsRefPtr<VibratorRunnable> runnable = new VibratorRunnable();
+  sVibratorRunnable = runnable;
+  nsCOMPtr<nsIThread> thread;
+  NS_NewThread(getter_AddRefs(thread), sVibratorRunnable);
+}
+
+} // anonymous namespace
+
+void
+Vibrate(const nsTArray<uint32> &pattern, const hal::WindowIdentifier &)
+{
+  EnsureVibratorThreadInitialized();
+  sVibratorRunnable->Vibrate(pattern);
+}
+
+void
+CancelVibrate(const hal::WindowIdentifier &)
+{
+  EnsureVibratorThreadInitialized();
+  sVibratorRunnable->CancelVibrate();
+}
 
 namespace {
 
 class BatteryUpdater : public nsRunnable {
 public:
   NS_IMETHOD Run()
   {
     hal::BatteryInformation info;
@@ -138,29 +280,31 @@ DisableBatteryNotifications()
 {
   sWatcher->mRunning = false;
   sWatcherThread->Shutdown();
   NS_IF_RELEASE(sWatcherThread);
   delete sWatcher;
 }
 
 void
-GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
+GetCurrentBatteryInformation(hal::BatteryInformation *aBatteryInfo)
 {
   FILE *capacityFile = fopen("/sys/class/power_supply/battery/capacity", "r");
   double capacity = dom::battery::kDefaultLevel * 100;
-  if (capacityFile)
+  if (capacityFile) {
     fscanf(capacityFile, "%lf", &capacity);
-  fclose(capacityFile);
+    fclose(capacityFile);
+  }
 
   FILE *chargingFile = fopen("/sys/class/power_supply/battery/charging_source", "r");
   int chargingSrc = 1;
-  if (chargingFile)
+  if (chargingFile) {
     fscanf(chargingFile, "%d", &chargingSrc);
-  fclose(chargingFile);
+    fclose(chargingFile);
+  }
 
   aBatteryInfo->level() = capacity / 100;
   aBatteryInfo->charging() = chargingSrc == 1;
   aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime;
 }
 
 namespace {
 
--- a/image/src/Decoder.cpp
+++ b/image/src/Decoder.cpp
@@ -125,33 +125,31 @@ Decoder::Finish()
 
   // If PostDecodeDone() has not been called, we need to sent teardown
   // notifications.
   if (!IsSizeDecode() && !mDecodeDone) {
 
     // Log data errors to the error console
     nsCOMPtr<nsIConsoleService> consoleService =
       do_GetService(NS_CONSOLESERVICE_CONTRACTID);
-    nsCOMPtr<nsIScriptError2> errorObject =
+    nsCOMPtr<nsIScriptError> errorObject =
       do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
 
     if (consoleService && errorObject && !HasDecoderError()) {
       nsAutoString msg(NS_LITERAL_STRING("Image corrupt or truncated: ") +
                        NS_ConvertASCIItoUTF16(mImage.GetURIString()));
 
-      errorObject->InitWithWindowID
-        (msg.get(),
-         NS_ConvertUTF8toUTF16(mImage.GetURIString()).get(),
-         nsnull,
-         0, 0, nsIScriptError::errorFlag,
-         "Image", mImage.InnerWindowID()
-         );
-  
-      nsCOMPtr<nsIScriptError> error = do_QueryInterface(errorObject);
-      consoleService->LogMessage(error);
+      if (NS_SUCCEEDED(errorObject->InitWithWindowID(
+                         msg.get(),
+                         NS_ConvertUTF8toUTF16(mImage.GetURIString()).get(),
+                         nsnull, 0, 0, nsIScriptError::errorFlag,
+                         "Image", mImage.InnerWindowID()
+                       ))) {
+        consoleService->LogMessage(errorObject);
+      }
     }
 
     // If we only have a data error, see if things are worth salvaging
     bool salvage = !HasDecoderError() && mImage.GetNumFrames();
 
     // If we're salvaging, say we finished decoding
     if (salvage)
       mImage.DecodingComplete();
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -35,16 +35,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef js_utility_h__
 #define js_utility_h__
 
+#include "mozilla/Assertions.h"
+
 #include <stdlib.h>
 #include <string.h>
 
 #include "jstypes.h"
 
 #ifdef __cplusplus
 
 /* The public JS engine namespace. */
@@ -66,67 +68,34 @@ using namespace mozilla;
 JS_BEGIN_EXTERN_C
 
 /*
  * Pattern used to overwrite freed memory. If you are accessing an object with
  * this pattern, you probably have a dangling pointer.
  */
 #define JS_FREE_PATTERN 0xDA
 
-/* JS_ASSERT */
+#define JS_ASSERT(expr)           MOZ_ASSERT(expr)
+#define JS_ASSERT_IF(cond, expr)  MOZ_ASSERT_IF((cond), (expr))
+#define JS_NOT_REACHED(reason)    MOZ_NOT_REACHED(reason)
+#define JS_ALWAYS_TRUE(expr)      MOZ_ALWAYS_TRUE(expr)
+#define JS_ALWAYS_FALSE(expr)     MOZ_ALWAYS_FALSE(expr)
+
 #ifdef DEBUG
-# define JS_ASSERT(expr)                                                      \
-    ((expr) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
-# define JS_ASSERT_IF(cond, expr)                                             \
-    ((!(cond) || (expr)) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
-# define JS_NOT_REACHED(reason)                                               \
-    JS_Assert(reason, __FILE__, __LINE__)
-# define JS_ALWAYS_TRUE(expr) JS_ASSERT(expr)
-# define JS_ALWAYS_FALSE(expr) JS_ASSERT(!(expr))
 # ifdef JS_THREADSAFE
 #  define JS_THREADSAFE_ASSERT(expr) JS_ASSERT(expr)
 # else
 #  define JS_THREADSAFE_ASSERT(expr) ((void) 0)
 # endif
 #else
-# define JS_ASSERT(expr)         ((void) 0)
-# define JS_ASSERT_IF(cond,expr) ((void) 0)
-# define JS_NOT_REACHED(reason)
-# define JS_ALWAYS_TRUE(expr)    ((void) (expr))
-# define JS_ALWAYS_FALSE(expr)    ((void) (expr))
 # define JS_THREADSAFE_ASSERT(expr) ((void) 0)
 #endif
 
-/*
- * JS_STATIC_ASSERT
- *
- * A compile-time assert. "cond" must be a constant expression. The macro can
- * be used only in places where an "extern" declaration is allowed.
- */
-#ifdef __SUNPRO_CC
-/*
- * Sun Studio C++ compiler has a bug
- * "sizeof expression not accepted as size of array parameter"
- * It happens when js_static_assert() function is declared inside functions.
- * The bug number is 6688515. It is not public yet.
- * Therefore, for Sun Studio, declare js_static_assert as an array instead.
- */
-# define JS_STATIC_ASSERT(cond) extern char js_static_assert[(cond) ? 1 : -1]
-#else
-# ifdef __COUNTER__
-#  define JS_STATIC_ASSERT_GLUE1(x,y) x##y
-#  define JS_STATIC_ASSERT_GLUE(x,y) JS_STATIC_ASSERT_GLUE1(x,y)
-#  define JS_STATIC_ASSERT(cond)                                            \
-        typedef int JS_STATIC_ASSERT_GLUE(js_static_assert, __COUNTER__)[(cond) ? 1 : -1]
-# else
-#  define JS_STATIC_ASSERT(cond) extern void js_static_assert(int arg[(cond) ? 1 : -1])
-# endif
-#endif
-
-#define JS_STATIC_ASSERT_IF(cond, expr) JS_STATIC_ASSERT(!(cond) || (expr))
+#define JS_STATIC_ASSERT(cond)           MOZ_STATIC_ASSERT(cond, "JS_STATIC_ASSERT")
+#define JS_STATIC_ASSERT_IF(cond, expr)  MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF")
 
 /*
  * Abort the process in a non-graceful manner. This will cause a core file,
  * call to the debugger or other moral equivalent as well as causing the
  * entire process to stop.
  */
 extern JS_PUBLIC_API(void) JS_Abort(void);
 
--- a/js/public/Vector.h
+++ b/js/public/Vector.h
@@ -36,16 +36,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jsvector_h_
 #define jsvector_h_
 
+#include "mozilla/Attributes.h"
+
 #include "TemplateLib.h"
 #include "Utility.h"
 
 /* Silence dire "bugs in previous versions of MSVC have been fixed" warnings */
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable:4345)
 #endif
@@ -269,18 +271,18 @@ class Vector : private AllocPolicy
 
     AlignedStorage<sInlineBytes> storage;
 
 #ifdef DEBUG
     friend class ReentrancyGuard;
     bool entered;
 #endif
 
-    Vector(const Vector &);
-    Vector &operator=(const Vector &);
+    Vector(const Vector &) MOZ_DELETE;
+    Vector &operator=(const Vector &) MOZ_DELETE;
 
     /* private accessors */
 
     bool usingInlineStorage() const {
         return mBegin == (T *)storage.addr();
     }
 
     T *beginNoCheck() const {
--- a/js/src/config/system-headers
+++ b/js/src/config/system-headers
@@ -526,16 +526,17 @@ netinet/in_systm.h
 netinet/tcp.h
 new
 newexe.h
 new.h
 nl_types.h
 NodeInfo.h
 nss.h
 nssilock.h
+nsswitch.h
 objbase.h
 objidl.h
 Objsafe.h
 ojiapitests.h
 ole2.h
 oleidl.h
 OpenGL/OpenGL.h
 OpenTptInternet.h
@@ -745,16 +746,17 @@ sys/stack.h
 sys/statfs.h
 sys/stat.h
 sys/statvfs.h
 sys/syscall.h
 sys/sysctl.h
 sys/sysinfo.h
 sys/sysmp.h
 sys/syssgi.h
+sys/system_properties.h
 sys/systeminfo.h
 sys/timeb.h
 sys/time.h
 sys/times.h
 sys/ttycom.h
 sys/types.h
 sys/ucontext.h
 sys/uio.h
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -36,16 +36,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef LifoAlloc_h__
 #define LifoAlloc_h__
 
+#include "mozilla/Attributes.h"
+
 /*
  * This data structure supports stacky LIFO allocation (mark/release and
  * LifoAllocScope). It does not maintain one contiguous segment; instead, it
  * maintains a bunch of linked memory segments. In order to prevent malloc/free
  * thrashing, unused segments are deallocated when garbage collection occurs.
  */
 
 #include "jsutil.h"
@@ -176,18 +178,18 @@ class LifoAlloc
 {
     typedef detail::BumpChunk BumpChunk;
 
     BumpChunk   *first;
     BumpChunk   *latest;
     size_t      markCount;
     size_t      defaultChunkSize_;
 
-    void operator=(const LifoAlloc &);
-    LifoAlloc(const LifoAlloc &);
+    void operator=(const LifoAlloc &) MOZ_DELETE;
+    LifoAlloc(const LifoAlloc &) MOZ_DELETE;
 
     /* 
      * Return a BumpChunk that can perform an allocation of at least size |n|
      * and add it to the chain appropriately.
      *
      * Side effect: if retval is non-null, |first| and |latest| are initialized
      * appropriately.
      */
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -35,16 +35,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jscompartment_h___
 #define jscompartment_h___
 
+#include "mozilla/Attributes.h"
+
 #include "jsclist.h"
 #include "jscntxt.h"
 #include "jsfun.h"
 #include "jsgc.h"
 #include "jsgcstats.h"
 #include "jsobj.h"
 #include "jsscope.h"
 #include "vm/GlobalObject.h"
@@ -464,19 +466,18 @@ class AutoCompartment
   public:
     AutoCompartment(JSContext *cx, JSObject *target);
     ~AutoCompartment();
 
     bool enter();
     void leave();
 
   private:
-    // Prohibit copying.
-    AutoCompartment(const AutoCompartment &);
-    AutoCompartment & operator=(const AutoCompartment &);
+    AutoCompartment(const AutoCompartment &) MOZ_DELETE;
+    AutoCompartment & operator=(const AutoCompartment &) MOZ_DELETE;
 };
 
 /*
  * Use this to change the behavior of an AutoCompartment slightly on error. If
  * the exception happens to be an Error object, copy it to the origin compartment
  * instead of wrapping it.
  */
 class ErrorCopier
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -301,16 +301,17 @@ extern JS_FRIEND_DATA(js::Class) DeclEnv
 extern JS_FRIEND_DATA(js::Class) FunctionClass;
 extern JS_FRIEND_DATA(js::Class) FunctionProxyClass;
 extern JS_FRIEND_DATA(js::Class) NamespaceClass;
 extern JS_FRIEND_DATA(js::Class) OuterWindowProxyClass;
 extern JS_FRIEND_DATA(js::Class) ObjectProxyClass;
 extern JS_FRIEND_DATA(js::Class) QNameClass;
 extern JS_FRIEND_DATA(js::Class) ScriptClass;
 extern JS_FRIEND_DATA(js::Class) XMLClass;
+extern JS_FRIEND_DATA(js::Class) ObjectClass;
 
 inline js::Class *
 GetObjectClass(const JSObject *obj)
 {
     return reinterpret_cast<const shadow::Object*>(obj)->shape->base->clasp;
 }
 
 inline JSClass *
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -2194,27 +2194,29 @@ js_CloneFunctionObject(JSContext *cx, JS
 
     JSObject *cloneobj = NewObjectWithClassProto(cx, &FunctionClass, NULL, SkipScopeParent(parent), kind);
     if (!cloneobj)
         return NULL;
     JSFunction *clone = static_cast<JSFunction *>(cloneobj);
 
     clone->nargs = fun->nargs;
     clone->flags = fun->flags & ~JSFUN_EXTENDED;
-    clone->u = fun->toFunction()->u;
+    if (fun->isInterpreted()) {
+        clone->initScript(fun->script());
+        clone->initEnvironment(parent);
+    } else {
+        clone->u.n = fun->u.n;
+    }
     clone->atom = fun->atom;
 
     if (kind == JSFunction::ExtendedFinalizeKind) {
         clone->flags |= JSFUN_EXTENDED;
         clone->initializeExtended();
     }
 
-    if (clone->isInterpreted())
-        clone->setEnvironment(parent);
-
     if (cx->compartment == fun->compartment()) {
         /*
          * We can use the same type as the original function provided that (a)
          * its prototype is correct, and (b) its type is not a singleton. The
          * first case will hold in all compileAndGo code, and the second case
          * will have been caught by CloneFunctionObject coming from function
          * definitions or read barriers, so will not get here.
          */
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -541,20 +541,16 @@ mjit::Compiler::performCompilation(JITSc
 
 #ifdef JS_METHODJIT_SPEW
     prof.stop();
     JaegerSpew(JSpew_Prof, "compilation took %d us\n", prof.time_us());
 #endif
 
     JaegerSpew(JSpew_Scripts, "successfully compiled (code \"%p\") (size \"%u\")\n",
                (*jitp)->code.m_code.executableAddress(), unsigned((*jitp)->code.m_size));
-
-    if (!*jitp)
-        return Compile_Abort;
-
     return Compile_Okay;
 }
 
 #undef CHECK_STATUS
 
 mjit::Compiler::ActiveFrame::ActiveFrame(JSContext *cx)
     : parent(NULL), parentPC(NULL), script(NULL), jumpMap(NULL),
       inlineIndex(UINT32_MAX), varTypes(NULL), needReturnValue(false),
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -2646,17 +2646,17 @@ ConvertArgs(JSContext *cx, uintN argc, j
             b, c, (char)c, i, u, j);
     ToStringHelper obj2string(cx, obj2);
     ToStringHelper valueString(cx, v);
     JSAutoByteString strBytes;
     if (str)
         strBytes.encode(cx, str);
     JSString *tmpstr = JS_DecompileFunction(cx, fun, 4);
     JSAutoByteString func;
-    if (!tmpstr || !func.encode(cx, tmpstr));
+    if (!tmpstr || !func.encode(cx, tmpstr))
         ReportException(cx);
     fprintf(gOutFile,
             "d %g, I %g, S %s, W %s, obj %s, fun %s\n"
             "v %s, re %g, im %g\n",
             d, I, !!strBytes ? strBytes.ptr() : "", EscapeWideString(w),
             obj2string.getBytes(),
             fun ? (!!func ? func.ptr() : "error decompiling fun") : "",
             valueString.getBytes(), re, im);
--- a/js/src/tests/manifest.py
+++ b/js/src/tests/manifest.py
@@ -5,39 +5,42 @@
 import os, re, sys
 from subprocess import *
 
 from tests import TestCase
 
 
 def split_path_into_dirs(path):
     dirs = [path]
-   
+
     while True:
         path, tail = os.path.split(path)
         if not tail:
             break
         dirs.append(path)
     return dirs
 
 class XULInfo:
     def __init__(self, abi, os, isdebug):
         self.abi = abi
         self.os = os
         self.isdebug = isdebug
+        self.browserIsRemote = False
 
     def as_js(self):
         """Return JS that when executed sets up variables so that JS expression
         predicates on XUL build info evaluate properly."""
 
-        return 'var xulRuntime = { OS: "%s", XPCOMABI: "%s", shell: true }; var isDebugBuild=%s; var Android=%s;' % (
+        return ('var xulRuntime = { OS: "%s", XPCOMABI: "%s", shell: true };' +
+                'var isDebugBuild=%s; var Android=%s; var browserIsRemote=%s') % (
             self.os,
             self.abi,
             str(self.isdebug).lower(),
-            str(self.os == "Android").lower())
+            str(self.os == "Android").lower(),
+            str(self.browserIsRemote).lower())
 
     @classmethod
     def create(cls, jsdir):
         """Create a XULInfo based on the current platform's characteristics."""
 
         # Our strategy is to find the autoconf.mk generated for the build and
         # read the values from there.
 
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -37,16 +37,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef Debugger_h__
 #define Debugger_h__
 
+#include "mozilla/Attributes.h"
+
 #include "jsapi.h"
 #include "jsclist.h"
 #include "jscntxt.h"
 #include "jscompartment.h"
 #include "jsgc.h"
 #include "jsweakmap.h"
 #include "jswrapper.h"
 
@@ -343,19 +345,18 @@ class Debugger {
     /*
      * Return the Debugger.Script object for |script|, or create a new one if
      * needed. The context |cx| must be in the debugger compartment; |script|
      * must be a script in a debuggee compartment.
      */
     JSObject *wrapScript(JSContext *cx, JSScript *script);
 
   private:
-    /* Prohibit copying. */
-    Debugger(const Debugger &);
-    Debugger & operator=(const Debugger &);
+    Debugger(const Debugger &) MOZ_DELETE;
+    Debugger & operator=(const Debugger &) MOZ_DELETE;
 };
 
 class BreakpointSite {
     friend class Breakpoint;
     friend struct ::JSCompartment;
     friend struct ::JSScript;
     friend class Debugger;
 
--- a/js/xpconnect/idl/nsIScriptError.idl
+++ b/js/xpconnect/idl/nsIScriptError.idl
@@ -38,17 +38,17 @@
 /*
  * nsIConsoleMessage subclass for representing JavaScript errors and warnings.
  */
 
 
 #include "nsISupports.idl"
 #include "nsIConsoleMessage.idl"
 
-[scriptable, uuid(537ff844-c325-4047-92f5-e1c292d108bc)]
+[scriptable, uuid(c6dd877a-87b6-47cc-968d-90f4514ec65f)]
 interface nsIScriptError : nsIConsoleMessage
 {
     /** pseudo-flag for default case */
     const unsigned long errorFlag = 0x0;
 
     /** message is warning */
     const unsigned long warningFlag = 0x1;
 
@@ -85,52 +85,45 @@ interface nsIScriptError : nsIConsoleMes
        The time (in milliseconds from the Epoch) that the script error instance
        was initialised, and thus the time when the error occurred.
        Currently used to display date and time of the message in Error console.
        The timestamp is initialized as JS_now/1000 so that it can be
        compared to Date.now in Javascript.
      */
     readonly attribute long long timeStamp;
 
+    /* Get the window id this was initialized with.  Zero will be
+       returned if init() was used instead of initWithWindowID(). */
+    readonly attribute unsigned long long outerWindowID;
+
+    /* Get the inner window id this was initialized with.  Zero will be
+       returned if init() was used instead of initWithWindowID(). */
+    readonly attribute unsigned long long innerWindowID;
+
     void init(in wstring message,
               in wstring sourceName,
               in wstring sourceLine,
               in PRUint32 lineNumber,
               in PRUint32 columnNumber,
               in PRUint32 flags,
               in string category);
 
-    AUTF8String toString();
-};
-
-/**
- * An interface that nsIScriptError objects can implement to allow
- * them to be initialized with a window id.
- */
-[scriptable, uuid(444c5e66-a85d-4a3b-83ce-4c71882b09a3)]
-interface nsIScriptError2 : nsISupports {
-    /* Get the window id this was initialized with.  Zero will be
-       returned if init() was used instead of initWithWindowID(). */
-    readonly attribute unsigned long long outerWindowID;
-
-    /* Get the inner window id this was initialized with.  Zero will be
-       returned if init() was used instead of initWithWindowID(). */
-    readonly attribute unsigned long long innerWindowID;
-
     /* This should be called instead of nsIScriptError.init to
        initialize with a window id.  The window id should be for the
        inner window associated with this error. */
     void initWithWindowID(in wstring message,
                           in wstring sourceName,
                           in wstring sourceLine,
                           in PRUint32 lineNumber,
                           in PRUint32 columnNumber,
                           in PRUint32 flags,
                           in string category,
                           in unsigned long long innerWindowID);
+
+    AUTF8String toString();
 };
 
 %{ C++
 #define NS_SCRIPTERROR_CLASSNAME "Script Error"
 
 #define NS_SCRIPTERROR_CID \
 { 0xe38e53b9, 0x5bb0, 0x456a, { 0xb5, 0x53, 0x57, 0x93, 0x70, 0xcb, 0x15, 0x67 }}
 
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -36,16 +36,18 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "mozilla/Attributes.h"
+
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG
 #endif
 
 #include <stdarg.h>
 
 #include "prlog.h"
 #ifdef ANDROID
@@ -314,34 +316,34 @@ public:
 
 private:
     JSContext* mContext;
     intN       mContextThread;
     nsIThreadJSContextStack* mContextStack;
     char*      mBuf;
 
     // prevent copying and assignment
-    JSCLContextHelper(const JSCLContextHelper &); // not implemented
-    const JSCLContextHelper& operator=(const JSCLContextHelper &); // not implemented
+    JSCLContextHelper(const JSCLContextHelper &) MOZ_DELETE;
+    const JSCLContextHelper& operator=(const JSCLContextHelper &) MOZ_DELETE;
 };
 
 
 class JSCLAutoErrorReporterSetter
 {
 public:
     JSCLAutoErrorReporterSetter(JSContext* cx, JSErrorReporter reporter)
         {mContext = cx; mOldReporter = JS_SetErrorReporter(cx, reporter);}
     ~JSCLAutoErrorReporterSetter()
         {JS_SetErrorReporter(mContext, mOldReporter);}
 private:
     JSContext* mContext;
     JSErrorReporter mOldReporter;
-    // prevent copying and assignment
-    JSCLAutoErrorReporterSetter(const JSCLAutoErrorReporterSetter &); // not implemented
-    const JSCLAutoErrorReporterSetter& operator=(const JSCLAutoErrorReporterSetter &); // not implemented
+
+    JSCLAutoErrorReporterSetter(const JSCLAutoErrorReporterSetter &) MOZ_DELETE;
+    const JSCLAutoErrorReporterSetter& operator=(const JSCLAutoErrorReporterSetter &) MOZ_DELETE;
 };
 
 static nsresult
 ReportOnCaller(JSContext *callerContext,
                const char *format, ...) {
     if (!callerContext) {
         return NS_ERROR_FAILURE;
     }
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -2687,17 +2687,17 @@ nsXPCComponents_Utils::LookupMethod(cons
 /* void reportError (); */
 NS_IMETHODIMP
 nsXPCComponents_Utils::ReportError(const JS::Value &error, JSContext *cx)
 {
     // This function shall never fail! Silently eat any failure conditions.
 
     nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
 
-    nsCOMPtr<nsIScriptError2> scripterr(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
+    nsCOMPtr<nsIScriptError> scripterr(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
 
     if (!scripterr || !console)
         return NS_OK;
 
     JSAutoRequest ar(cx);
 
     const PRUint64 innerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);
 
@@ -2710,18 +2710,17 @@ nsXPCComponents_Utils::ReportError(const
         PRUint32 column = err->uctokenptr - err->uclinebuf;
 
         nsresult rv = scripterr->InitWithWindowID(
                 static_cast<const PRUnichar*>(err->ucmessage), fileUni.get(),
                 static_cast<const PRUnichar*>(err->uclinebuf), err->lineno,
                 column, err->flags, "XPConnect JavaScript", innerWindowID);
         NS_ENSURE_SUCCESS(rv, NS_OK);
 
-        nsCOMPtr<nsIScriptError> logError = do_QueryInterface(scripterr);
-        console->LogMessage(logError);
+        console->LogMessage(scripterr);
         return NS_OK;
     }
 
     // It's not a JS Error object, so we synthesize as best we're able.
     JSString *msgstr = JS_ValueToString(cx, error);
     if (!msgstr) {
         return NS_OK;
     }
@@ -2743,18 +2742,17 @@ nsXPCComponents_Utils::ReportError(const
         return NS_OK;
 
     nsresult rv = scripterr->InitWithWindowID(
             reinterpret_cast<const PRUnichar *>(msgchars),
             NS_ConvertUTF8toUTF16(fileName).get(),
             nsnull, lineNo, 0, 0, "XPConnect JavaScript", innerWindowID);
     NS_ENSURE_SUCCESS(rv, NS_OK);
 
-    nsCOMPtr<nsIScriptError> logError = do_QueryInterface(scripterr);
-    console->LogMessage(logError);
+    console->LogMessage(scripterr);
     return NS_OK;
 }
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 const char kScriptSecurityManagerContractID[] = NS_SCRIPTSECURITYMANAGER_CONTRACTID;
 
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -1128,24 +1128,22 @@ nsXPCWrappedJSClass::CheckForException(X
                                 if (location) {
                                     // Get line number w/o checking; 0 is ok.
                                     location->GetLineNumber(&lineNumber);
 
                                     // get a filename.
                                     rv = location->GetFilename(getter_Copies(sourceName));
                                 }
 
-                                nsCOMPtr<nsIScriptError2> scriptError2 =
-                                    do_QueryInterface(scriptError);
-                                rv = scriptError2->InitWithWindowID(newMessage.get(),
-                                                                    NS_ConvertASCIItoUTF16(sourceName).get(),
-                                                                    nsnull,
-                                                                    lineNumber, 0, 0,
-                                                                    "XPConnect JavaScript",
-                                                                    nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx));
+                                rv = scriptError->InitWithWindowID(newMessage.get(),
+                                                                   NS_ConvertASCIItoUTF16(sourceName).get(),
+                                                                   nsnull,
+                                                                   lineNumber, 0, 0,
+                                                                   "XPConnect JavaScript",
+                                                                   nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx));
                                 if (NS_FAILED(rv))
                                     scriptError = nsnull;
                             }
                         }
                     }
                     if (nsnull != scriptError)
                         consoleService->LogMessage(scriptError);
                 }
--- a/js/xpconnect/src/nsScriptError.cpp
+++ b/js/xpconnect/src/nsScriptError.cpp
@@ -41,18 +41,17 @@
  * nsIScriptError implementation.  Defined here, lacking a JS-specific
  * place to put XPCOM things.
  */
 
 #include "xpcprivate.h"
 #include "nsGlobalWindow.h"
 #include "nsPIDOMWindow.h"
 
-NS_IMPL_THREADSAFE_ISUPPORTS3(nsScriptError, nsIConsoleMessage, nsIScriptError,
-                              nsIScriptError2)
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsScriptError, nsIConsoleMessage, nsIScriptError)
 
 nsScriptError::nsScriptError()
     :  mMessage(),
        mSourceName(),
        mLineNumber(0),
        mSourceLine(),
        mColumnNumber(0),
        mFlags(0),
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -41,16 +41,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* All the XPConnect private declarations - only include locally. */
 
 #ifndef xpcprivate_h___
 #define xpcprivate_h___
 
+#include "mozilla/Attributes.h"
+
 #include <string.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <math.h>
 #include "xpcpublic.h"
 #include "jsapi.h"
 #include "jsdhash.h"
 #include "jsprf.h"
@@ -3931,29 +3933,27 @@ xpc_DumpJSObject(JSObject* obj);
 
 extern JSBool
 xpc_InstallJSDebuggerKeywordHandler(JSRuntime* rt);
 
 /***************************************************************************/
 
 // Definition of nsScriptError, defined here because we lack a place to put
 // XPCOM objects associated with the JavaScript engine.
-class nsScriptError : public nsIScriptError,
-                      public nsIScriptError2 {
+class nsScriptError : public nsIScriptError {
 public:
     nsScriptError();
 
     virtual ~nsScriptError();
 
   // TODO - do something reasonable on getting null from these babies.
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSICONSOLEMESSAGE
     NS_DECL_NSISCRIPTERROR
-    NS_DECL_NSISCRIPTERROR2
 
 private:
     nsString mMessage;
     nsString mSourceName;
     PRUint32 mLineNumber;
     nsString mSourceLine;
     PRUint32 mColumnNumber;
     PRUint32 mFlags;
@@ -4021,18 +4021,18 @@ private:
     JSExceptionState* mState;
     bool mErrorReporterSet;
     bool mEvaluated;
     jsword mContextHasThread;
     JSAutoEnterCompartment mEnterCompartment;
     MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
 
     // No copying or assignment allowed
-    AutoScriptEvaluate(const AutoScriptEvaluate &);
-    AutoScriptEvaluate & operator =(const AutoScriptEvaluate &);
+    AutoScriptEvaluate(const AutoScriptEvaluate &) MOZ_DELETE;
+    AutoScriptEvaluate & operator =(const AutoScriptEvaluate &) MOZ_DELETE;
 };
 
 /***************************************************************************/
 class NS_STACK_CLASS AutoResolveName
 {
 public:
     AutoResolveName(XPCCallContext& ccx, jsid name
                     MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM)
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3522,17 +3522,17 @@ nsCSSFrameConstructor::FindHTMLData(Elem
     SIMPLE_TAG_CHAIN(embed, nsCSSFrameConstructor::FindObjectData),
     COMPLEX_TAG_CREATE(fieldset,
                        &nsCSSFrameConstructor::ConstructFieldSetFrame),
     { &nsGkAtoms::legend,
       FCDATA_DECL(FCDATA_ALLOW_BLOCK_STYLES, NS_NewLegendFrame) },
     SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame),
     SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame),
     COMPLEX_TAG_CREATE(button, &nsCSSFrameConstructor::ConstructButtonFrame),
-    SIMPLE_TAG_CREATE(canvas, NS_NewHTMLCanvasFrame),
+    SIMPLE_TAG_CHAIN(canvas, nsCSSFrameConstructor::FindCanvasData),
 #if defined(MOZ_MEDIA)
     SIMPLE_TAG_CREATE(video, NS_NewHTMLVideoFrame),
     SIMPLE_TAG_CREATE(audio, NS_NewHTMLVideoFrame),
 #endif
     SIMPLE_TAG_CREATE(progress, NS_NewProgressFrame)
   };
 
   return FindDataByTag(aTag, aElement, aStyleContext, sHTMLData,
@@ -3633,16 +3633,30 @@ nsCSSFrameConstructor::FindObjectData(El
                       NS_NewSubDocumentFrame)
     // Nothing for TYPE_NULL so we'll construct frames by display there
   };
 
   return FindDataByInt((PRInt32)type, aElement, aStyleContext,
                        sObjectData, ArrayLength(sObjectData));
 }
 
+/* static */
+const nsCSSFrameConstructor::FrameConstructionData*
+nsCSSFrameConstructor::FindCanvasData(Element* aElement,
+                                      nsStyleContext* aStyleContext)
+{
+  if (!aElement->OwnerDoc()->IsScriptEnabled()) {
+    return nsnull;
+  }
+
+  static const FrameConstructionData sCanvasData =
+    SIMPLE_FCDATA(NS_NewHTMLCanvasFrame);
+  return &sCanvasData;
+}
+
 nsresult
 nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aItem,
                                                       nsFrameConstructorState& aState,
                                                       nsIFrame* aParentFrame,
                                                       nsFrameItems& aFrameItems)
 {
   const FrameConstructionData* data = aItem.mFCData;
   NS_ASSERTION(data, "Must have frame construction data");
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -38,16 +38,18 @@
 /*
  * construction of a frame tree that is nearly isomorphic to the content
  * tree and updating of that tree in response to dynamic changes
  */
 
 #ifndef nsCSSFrameConstructor_h___
 #define nsCSSFrameConstructor_h___
 
+#include "mozilla/Attributes.h"
+
 #include "nsCOMPtr.h"
 #include "nsILayoutHistoryState.h"
 #include "nsIXBLService.h"
 #include "nsQuoteList.h"
 #include "nsCounterManager.h"
 #include "nsHashKeys.h"
 #include "nsThreadUtils.h"
 #include "nsPageContentFrame.h"
@@ -97,20 +99,19 @@ public:
   static nsIXBLService * GetXBLService();
   static void ReleaseGlobals() { NS_IF_RELEASE(gXBLService); }
 
   // get the alternate text for a content node
   static void GetAlternateTextFor(nsIContent*    aContent,
                                   nsIAtom*       aTag,  // content object's tag
                                   nsXPIDLString& aAltText);
 
-private: 
-  // These are not supported and are not implemented! 
-  nsCSSFrameConstructor(const nsCSSFrameConstructor& aCopy); 
-  nsCSSFrameConstructor& operator=(const nsCSSFrameConstructor& aCopy); 
+private:
+  nsCSSFrameConstructor(const nsCSSFrameConstructor& aCopy) MOZ_DELETE;
+  nsCSSFrameConstructor& operator=(const nsCSSFrameConstructor& aCopy) MOZ_DELETE;
 
 public:
   // XXXbz this method needs to actually return errors!
   nsresult ConstructRootFrame(nsIFrame** aNewFrame);
 
   nsresult ReconstructDocElementHierarchy();
 
   // Create frames for content nodes that are marked as needing frames. This
@@ -1196,16 +1197,18 @@ private:
   static const FrameConstructionData*
     FindImgData(Element* aElement, nsStyleContext* aStyleContext);
   static const FrameConstructionData*
     FindImgControlData(Element* aElement, nsStyleContext* aStyleContext);
   static const FrameConstructionData*
     FindInputData(Element* aElement, nsStyleContext* aStyleContext);
   static const FrameConstructionData*
     FindObjectData(Element* aElement, nsStyleContext* aStyleContext);
+  static const FrameConstructionData*
+    FindCanvasData(Element* aElement, nsStyleContext* aStyleContext);
 
   /* Construct a frame from the given FrameConstructionItem.  This function
      will handle adding the frame to frame lists, processing children, setting
      the frame as the primary frame for the item's content, and so forth.
 
      @param aItem the FrameConstructionItem to use.
      @param aState the frame construction state to use.
      @param aParentFrame the frame to set as the parent of the
--- a/layout/base/nsStyleChangeList.h
+++ b/layout/base/nsStyleChangeList.h
@@ -38,16 +38,18 @@
 /*
  * a list of the recomputation that needs to be done in response to a
  * style change
  */
 
 #ifndef nsStyleChangeList_h___
 #define nsStyleChangeList_h___
 
+#include "mozilla/Attributes.h"
+
 #include "nsError.h"
 #include "nsChangeHint.h"
 
 class nsIFrame;
 class nsIContent;
 
 // XXX would all platforms support putting this inside the list?
 struct nsStyleChangeData {
@@ -90,13 +92,13 @@ protected:
   bool                operator==(const nsStyleChangeList& aOther) const;
 
   nsStyleChangeData*  mArray;
   PRInt32             mArraySize;
   PRInt32             mCount;
   nsStyleChangeData   mBuffer[kStyleChangeBufferSize];
 
 private:
-  nsStyleChangeList(const nsStyleChangeList&); // not implemented
+  nsStyleChangeList(const nsStyleChangeList&) MOZ_DELETE;
 };
 
 
 #endif /* nsStyleChangeList_h___ */
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -37,16 +37,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* base class of all rendering objects */
 
+#include "mozilla/Attributes.h"
 #include "mozilla/Util.h"
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsFrameList.h"
 #include "nsPlaceholderFrame.h"
 #include "nsLineLayout.h"
 #include "nsIContent.h"
@@ -8069,17 +8070,17 @@ struct DR_FrameTypeInfo
       }
    }
 
   nsIAtom*    mType;
   char        mNameAbbrev[16];
   char        mName[32];
   nsTArray<DR_Rule*> mRules;
 private:
-  DR_FrameTypeInfo& operator=(const DR_FrameTypeInfo&); // NOT USED
+  DR_FrameTypeInfo& operator=(const DR_FrameTypeInfo&) MOZ_DELETE;
 };
 
 DR_FrameTypeInfo::DR_FrameTypeInfo(nsIAtom* aFrameType, 
                                    const char* aFrameNameAbbrev, 
                                    const char* aFrameName)
 {
   mType = aFrameType;
   PL_strncpyz(mNameAbbrev, aFrameNameAbbrev, sizeof(mNameAbbrev));
--- a/layout/generic/nsFrameSelection.h
+++ b/layout/generic/nsFrameSelection.h
@@ -33,16 +33,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsFrameSelection_h___
 #define nsFrameSelection_h___
 
+#include "mozilla/Attributes.h"
+
 #include "nsIFrame.h"
 #include "nsIContent.h"
 #include "nsISelectionController.h"
 #include "nsITableLayout.h"
 #include "nsITableCellLayout.h"
 #include "nsIDOMElement.h"
 #include "nsGUIEvent.h"
 #include "nsIRange.h"
@@ -205,17 +207,17 @@ class nsTypedSelection;
 class nsIScrollableFrame;
 
 /**
  * Methods which are marked with *unsafe* should be handled with special care.
  * They may cause nsFrameSelection to be deleted, if strong pointer isn't used,
  * or they may cause other objects to be deleted.
  */
 
-class nsFrameSelection : public nsISupports {
+class nsFrameSelection MOZ_FINAL : public nsISupports {
 public:
   enum HINT { HINTLEFT = 0, HINTRIGHT = 1};  //end of this line or beginning of next
   /*interfaces for addref and release and queryinterface*/
   
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsFrameSelection)
 
   /** Init will initialize the frame selector with the necessary pres shell to 
--- a/layout/mathml/mathfont.properties
+++ b/layout/mathml/mathfont.properties
@@ -114,18 +114,18 @@ mathvariant.monospace = A\ud835\ude70B\u
 
 operator.\u0021.postfix = lspace:1 rspace:0 # !
 operator.\u0021\u0021.postfix = lspace:1 rspace:0 # !!
 operator.\u0021\u003D.infix = lspace:4 rspace:4 # !=
 operator.\u0025.infix = lspace:3 rspace:3 # percent sign
 operator.\u0026.postfix = lspace:0 rspace:0 # &amp;
 operator.\u0026\u0026.infix = lspace:4 rspace:4 # &amp;&amp;
 operator.\u0027.postfix = lspace:0 rspace:0 accent # '
-operator.\u0028.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # (
-operator.\u0029.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # )
+operator.\u0028.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical mirrorable # (
+operator.\u0029.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical mirrorable # )
 operator.\u002A.infix = lspace:3 rspace:3 # *
 operator.\u002A\u002A.infix = lspace:1 rspace:1 # **
 operator.\u002A\u003D.infix = lspace:4 rspace:4 # *=
 operator.\u002B.infix = lspace:4 rspace:4 # +
 operator.\u002B.prefix = lspace:0 rspace:1 # +
 operator.\u002B\u002B.postfix = lspace:0 rspace:0 # ++
 operator.\u002B\u003D.infix = lspace:4 rspace:4 # +=
 operator.\u002C.infix = lspace:0 rspace:3 separator # ,
@@ -147,35 +147,35 @@ operator.\u003C.infix = lspace:5 rspace:
 operator.\u003C\u003D.infix = lspace:5 rspace:5 # &lt;=
 operator.\u003C\u003E.infix = lspace:1 rspace:1 # &lt;>
 operator.\u003D.infix = lspace:5 rspace:5 # =
 operator.\u003D\u003D.infix = lspace:4 rspace:4 # ==
 operator.\u003E.infix = lspace:5 rspace:5 # >
 operator.\u003E\u003D.infix = lspace:5 rspace:5 # >=
 operator.\u003F.infix = lspace:1 rspace:1 # ?
 operator.\u0040.infix = lspace:1 rspace:1 # @
-operator.\u005B.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # [
+operator.\u005B.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical mirrorable # [
 operator.\u005C.infix = lspace:0 rspace:0 # reverse solidus
-operator.\u005D.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # ]
+operator.\u005D.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical mirrorable # ]
 operator.\u005E.postfix = lspace:0 rspace:0 stretchy accent direction:horizontal # &Hat; circumflex accent
 operator.\u005E.infix = lspace:1 rspace:1 direction:horizontal # ^
 operator.\u005F.postfix = lspace:0 rspace:0 stretchy accent direction:horizontal # _ low line
 operator.\u005F.infix = lspace:1 rspace:1 stretchy direction:horizontal # _ low line
 operator.\u0060.postfix = lspace:0 rspace:0 accent # &DiacriticalGrave;
-operator.\u007B.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # {
+operator.\u007B.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical mirrorable # {
 operator.\u007C.infix = lspace:2 rspace:2 stretchy fence symmetric direction:vertical # &VerticalLine; |
 operator.\u007C.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # |
 operator.\u007C.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # |
 operator.\u007C\u007C.infix = lspace:2 rspace:2 stretchy fence symmetric direction:vertical # ||
 operator.\u007C\u007C.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # multiple character operator: ||
 operator.\u007C\u007C.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # multiple character operator: ||
 operator.\u007C\u007C\u007C.infix = lspace:2 rspace:2 stretchy fence symmetric direction:vertical # multiple character operator: |||
 operator.\u007C\u007C\u007C.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # multiple character operator: |||
 operator.\u007C\u007C\u007C.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # multiple character operator: |||
-operator.\u007D.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # }
+operator.\u007D.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical mirrorable # }
 operator.\u007E.postfix = lspace:0 rspace:0 stretchy accent direction:horizontal # ~ tilde
 operator.\u00A8.postfix = lspace:0 rspace:0 accent # &DoubleDot;
 operator.\u00AC.prefix = lspace:2 rspace:1 # not sign
 operator.\u00AF.postfix = lspace:0 rspace:0 stretchy accent direction:horizontal # &OverBar;
 operator.\u00B0.postfix = lspace:0 rspace:0 # degree sign
 operator.\u00B1.infix = lspace:4 rspace:4 # &PlusMinus;
 operator.\u00B1.prefix = lspace:0 rspace:1 # &PlusMinus;
 operator.\u00B4.postfix = lspace:0 rspace:0 accent # &DiacriticalAcute;
@@ -336,49 +336,49 @@ operator.\u2208.infix = lspace:5 rspace:
 operator.\u2209.infix = lspace:5 rspace:5 # &NotElement;
 operator.\u220A.infix = lspace:5 rspace:5 # small element of
 operator.\u220B.infix = lspace:5 rspace:5 # &SuchThat; &ReverseElement;
 operator.\u220C.infix = lspace:5 rspace:5 # &NotReverseElement;
 operator.\u220D.infix = lspace:5 rspace:5 # small contains as member
 operator.\u220E.infix = lspace:3 rspace:3 # end of proof
 operator.\u220F.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical # &Product;
 operator.\u2210.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical # &Coproduct;
-operator.\u2211.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical # &Sum;
+operator.\u2211.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical mirrorable # &Sum;
 operator.\u2212.infix = lspace:4 rspace:4 # official Unicode minus sign
 operator.\u2212.prefix = lspace:0 rspace:1 # official Unicode minus sign
 operator.\u2213.infix = lspace:4 rspace:4 # &MinusPlus;
 operator.\u2213.prefix = lspace:0 rspace:1 # &MinusPlus;
 operator.\u2214.infix = lspace:4 rspace:4 # dot plus
 operator.\u2215.infix = lspace:4 rspace:4 stretchy direction:vertical # division slash
 operator.\u2216.infix = lspace:4 rspace:4 direction:vertical # set minus
 operator.\u2217.infix = lspace:4 rspace:4 # asterisk operator
 operator.\u2218.infix = lspace:4 rspace:4 # &SmallCircle;
 operator.\u2219.infix = lspace:4 rspace:4 # bullet operator
-operator.\u221A.prefix = lspace:1 rspace:1 stretchy direction:vertical # &Sqrt;
+operator.\u221A.prefix = lspace:1 rspace:1 stretchy direction:vertical mirrorable # &Sqrt;
 operator.\u221B.prefix = lspace:1 rspace:1 # cube root
 operator.\u221C.prefix = lspace:1 rspace:1 # fourth root
 operator.\u221D.infix = lspace:5 rspace:5 # &Proportional;
 operator.\u221F.infix = lspace:5 rspace:5 # right angle
 operator.\u2220.prefix = lspace:0 rspace:0 # angle
 operator.\u2221.prefix = lspace:0 rspace:0 # measured angle
 operator.\u2222.prefix = lspace:0 rspace:0 # spherical angle
 operator.\u2223.infix = lspace:5 rspace:5 direction:vertical # divides
 operator.\u2224.infix = lspace:5 rspace:5 # &NotVerticalBar;
 operator.\u2225.infix = lspace:5 rspace:5 direction:vertical # parallel to
 operator.\u2226.infix = lspace:5 rspace:5 # &NotDoubleVerticalBar;
 operator.\u2227.infix = lspace:4 rspace:4 # &wedge;
 operator.\u2228.infix = lspace:4 rspace:4 # &vee;
 operator.\u2229.infix = lspace:4 rspace:4 # &cap;
 operator.\u222A.infix = lspace:4 rspace:4 # &cup;
-operator.\u222B.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # &Integral;
-operator.\u222C.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # double integral
-operator.\u222D.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # triple integral
-operator.\u222E.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # &ContourIntegral;
-operator.\u222F.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # &DoubleContourIntegral;
-operator.\u2230.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # volume integral
+operator.\u222B.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral mirrorable # &Integral;
+operator.\u222C.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral mirrorable # double integral
+operator.\u222D.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral mirrorable # triple integral
+operator.\u222E.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral mirrorable # &ContourIntegral;
+operator.\u222F.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral mirrorable # &DoubleContourIntegral;
+operator.\u2230.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral mirrorable # volume integral
 operator.\u2231.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # clockwise integral
 operator.\u2232.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # &ClockwiseContourIntegral;
 operator.\u2233.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # &CounterClockwiseContourIntegral;
 operator.\u2234.infix = lspace:5 rspace:5 # &Therefore;
 operator.\u2235.infix = lspace:5 rspace:5 # &Because;
 operator.\u2236.infix = lspace:5 rspace:5 # ratio
 operator.\u2237.infix = lspace:5 rspace:5 # &Colon; &Proportion;
 operator.\u2238.infix = lspace:4 rspace:4 # dot minus
@@ -933,34 +933,34 @@ operator.\u2A02.prefix = lspace:1 rspace
 operator.\u2A03.prefix = lspace:1 rspace:2 largeop movablelimits symmetric # n-ary union operator with dot
 operator.\u2A04.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical # &biguplus;
 operator.\u2A05.prefix = lspace:1 rspace:2 largeop movablelimits symmetric # n-ary square intersection operator
 operator.\u2A06.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical # &bigsqcup;
 operator.\u2A07.prefix = lspace:1 rspace:2 largeop movablelimits symmetric # two logical and operator
 operator.\u2A08.prefix = lspace:1 rspace:2 largeop movablelimits symmetric # two logical or operator
 operator.\u2A09.prefix = lspace:1 rspace:2 largeop movablelimits symmetric # n-ary times operator
 operator.\u2A0A.prefix = lspace:1 rspace:2 largeop movablelimits symmetric # modulo two sum
-operator.\u2A0B.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # summation with integral
-operator.\u2A0C.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # quadruple integral operator
-operator.\u2A0D.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # finite part integral
-operator.\u2A0E.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral with double stroke
-operator.\u2A0F.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral average with slash
-operator.\u2A10.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral # circulation function
+operator.\u2A0B.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # summation with integral
+operator.\u2A0C.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral mirrorable # quadruple integral operator
+operator.\u2A0D.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # finite part integral
+operator.\u2A0E.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral with double stroke
+operator.\u2A0F.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral average with slash
+operator.\u2A10.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral mirrorable # circulation function
 operator.\u2A11.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral # anticlockwise integration
-operator.\u2A12.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral # line integration with rectangular path around pole
-operator.\u2A13.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral # line integration with semicircular path around pole
-operator.\u2A14.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral # line integration not including the pole
-operator.\u2A15.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral around a point operator
-operator.\u2A16.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # quaternion integral operator
+operator.\u2A12.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral mirrorable # line integration with rectangular path around pole
+operator.\u2A13.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral mirrorable # line integration with semicircular path around pole
+operator.\u2A14.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral mirrorable # line integration not including the pole
+operator.\u2A15.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral around a point operator
+operator.\u2A16.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # quaternion integral operator
 operator.\u2A17.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral with leftwards arrow with hook
-operator.\u2A18.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral with times sign
-operator.\u2A19.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral with intersection
-operator.\u2A1A.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral with union
-operator.\u2A1B.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral with overbar
-operator.\u2A1C.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral with underbar
+operator.\u2A18.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral with times sign
+operator.\u2A19.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral with intersection
+operator.\u2A1A.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral with union
+operator.\u2A1B.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral with overbar
+operator.\u2A1C.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral with underbar
 operator.\u2A1D.infix = lspace:3 rspace:3 # join
 operator.\u2A1E.infix = lspace:3 rspace:3 # large left triangle operator
 operator.\u2A1F.infix = lspace:3 rspace:3 # z notation schema composition
 operator.\u2A20.infix = lspace:3 rspace:3 # z notation schema piping
 operator.\u2A21.infix = lspace:3 rspace:3 # z notation schema projection
 operator.\u2A22.infix = lspace:4 rspace:4 # plus sign with small circle above
 operator.\u2A23.infix = lspace:4 rspace:4 # plus sign with circumflex accent above
 operator.\u2A24.infix = lspace:4 rspace:4 # plus sign with tilde above
--- a/layout/mathml/mathml.css
+++ b/layout/mathml/mathml.css
@@ -462,8 +462,22 @@ semantics > :not(:first-child) {
 /* all other cases can be described using regular CSS, so we do it this way because it's
    more efficient and less code */
 mroot > :not(:first-child) { -moz-script-level:+2; }
 
 msub > :not(:first-child),
 msup > :not(:first-child),
 msubsup > :not(:first-child),
 mmultiscripts > :not(:first-child) { -moz-script-level:+1; }
+
+/*****************************************/
+/* Controlling directionality            */
+/*****************************************/
+
+math[dir="rtl"], mstyle[dir="rtl"], mrow[dir="rtl"],
+mi[dir="rtl"], mn[dir="rtl"], mo[dir="rtl"], mtext[dir="rtl"], ms[dir="rtl"] {
+    direction: rtl;
+}
+
+math[dir="ltr"], mstyle[dir="ltr"], mrow[dir="ltr"],
+mi[dir="ltr"], mn[dir="ltr"], mo[dir="ltr"], mtext[dir="ltr"], ms[dir="ltr"] {
+    direction: ltr;
+}
--- a/layout/mathml/nsIMathMLFrame.h
+++ b/layout/mathml/nsIMathMLFrame.h
@@ -250,25 +250,25 @@ struct nsEmbellishData {
 
   // stretchy direction that the nsMathMLChar owned by the core <mo> supports
   nsStretchDirection direction;
 
   // spacing that may come from <mo> depending on its 'form'. Since
   // the 'form' may also depend on the position of the outermost
   // embellished ancestor, the set up of these values may require
   // looking up the position of our ancestors.
-  nscoord leftSpace;
-  nscoord rightSpace;
+  nscoord leadingSpace;
+  nscoord trailingSpace;
 
   nsEmbellishData() {
     flags = 0;
     coreFrame = nsnull;
     direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
-    leftSpace = 0;
-    rightSpace = 0;
+    leadingSpace = 0;
+    trailingSpace = 0;
   }
 };
 
 // struct used by a container frame to modulate its presentation.
 // By convention, the data that we keep in this struct can change depending
 // on any of our ancestors and/or descendants. If a data can be resolved
 // solely from the embellished hierarchy, and it remains immutable once
 // resolved, we put it in |nsEmbellishData|. If it can be affected by other
@@ -325,16 +325,19 @@ struct nsPresentationData {
 // This bit is set if the frame has the explicit attribute
 // displaystyle="true" or "false". It is only relevant to <mstyle> and <mtable>
 // because they are the only tags where the attribute is allowed by the spec.
 #define NS_MATHML_EXPLICIT_DISPLAYSTYLE               0x00000020U
 
 // This bit is set if the frame is "space-like", as defined by the spec.
 #define NS_MATHML_SPACE_LIKE                          0x00000040U
 
+// This bit is set if the directionality of the frame is right-to-left
+#define NS_MATHML_RTL                                 0x00000080U
+
 // This bit is set when the frame cannot be formatted due to an
 // error (e.g., invalid markup such as a <msup> without an overscript).
 // When set, a visual feedback will be provided to the user.
 #define NS_MATHML_ERROR                               0x80000000U
 
 // a bit used for debug
 #define NS_MATHML_STRETCH_DONE                        0x20000000U
 
@@ -359,16 +362,19 @@ struct nsPresentationData {
   (NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY == ((_flags) & NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY))
 
 #define NS_MATHML_HAS_EXPLICIT_DISPLAYSTYLE(_flags) \
   (NS_MATHML_EXPLICIT_DISPLAYSTYLE == ((_flags) & NS_MATHML_EXPLICIT_DISPLAYSTYLE))
 
 #define NS_MATHML_IS_SPACE_LIKE(_flags) \
   (NS_MATHML_SPACE_LIKE == ((_flags) & NS_MATHML_SPACE_LIKE))
 
+#define NS_MATHML_IS_RTL(_flags) \
+  (NS_MATHML_RTL == ((_flags) & NS_MATHML_RTL))
+
 #define NS_MATHML_HAS_ERROR(_flags) \
   (NS_MATHML_ERROR == ((_flags) & NS_MATHML_ERROR))
 
 #define NS_MATHML_STRETCH_WAS_DONE(_flags) \
   (NS_MATHML_STRETCH_DONE == ((_flags) & NS_MATHML_STRETCH_DONE))
 
 #define NS_MATHML_PAINT_BOUNDING_METRICS(_flags) \
   (NS_MATHML_SHOW_BOUNDING_METRICS == ((_flags) & NS_MATHML_SHOW_BOUNDING_METRICS))
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -1698,24 +1698,26 @@ nsMathMLChar::StretchInternal(nsPresCont
 }
 
 nsresult
 nsMathMLChar::Stretch(nsPresContext*           aPresContext,
                       nsRenderingContext&     aRenderingContext,
                       nsStretchDirection       aStretchDirection,
                       const nsBoundingMetrics& aContainerSize,
                       nsBoundingMetrics&       aDesiredStretchSize,
-                      PRUint32                 aStretchHint)
+                      PRUint32                 aStretchHint,
+                      bool                     aRTL)
 {
   NS_ASSERTION(!(aStretchHint &
                  ~(NS_STRETCH_VARIABLE_MASK | NS_STRETCH_LARGEOP |
                    NS_STRETCH_INTEGRAL)),
                "Unexpected stretch flags");
 
   mDrawNormal = true;
+  mMirrored = aRTL && nsMathMLOperators::IsMirrorableOperator(mData);
   mScaleY = mScaleX = 1.0;
   mDirection = aStretchDirection;
   nsresult rv =
     StretchInternal(aPresContext, aRenderingContext, mDirection,
                     aContainerSize, aDesiredStretchSize, aStretchHint);
 
   // Record the metrics
   mBoundingMetrics = aDesiredStretchSize;
@@ -1791,20 +1793,21 @@ nsMathMLChar::ComposeChildren(nsPresCont
   }
   nscoord dx = 0, dy = 0;
   for (i = 0, child = mSibling; child; child = child->mSibling, i++) {
     // child chars should just inherit our values - which may change between calls...
     child->mData = mData;
     child->mDirection = mDirection;
     child->mStyleContext = mStyleContext;
     child->mGlyphTable = aGlyphTable; // the child is associated to this table
+    child->mMirrored = mMirrored;
     // there goes the Stretch() ...
     nsBoundingMetrics childSize;
     nsresult rv = child->Stretch(aPresContext, aRenderingContext, mDirection,
-                                 splitSize, childSize, aStretchHint);
+                                 splitSize, childSize, aStretchHint, mMirrored);
     // check if something went wrong or the child couldn't fit in the alloted space
     if (NS_FAILED(rv) || (NS_STRETCH_DIRECTION_UNSUPPORTED == child->mDirection)) {
       delete mSibling; // don't leave a dangling list behind ...
       mSibling = nsnull;
       return NS_ERROR_FAILURE;
     }
     child->SetRect(nsRect(dx, dy, childSize.width, childSize.ascent+childSize.descent));
     if (0 == i)
@@ -2023,18 +2026,23 @@ nsMathMLChar::Display(nsDisplayListBuild
         nsDisplayMathMLCharForeground(aBuilder, aForFrame, this,
                                       aSelectedRect && !aSelectedRect->IsEmpty()));
 }
 
 void
 nsMathMLChar::ApplyTransforms(nsRenderingContext& aRenderingContext, nsRect &r)
 {
   // apply the transforms
-  aRenderingContext.Translate(r.TopLeft());
-  aRenderingContext.Scale(mScaleX, mScaleY);
+  if (mMirrored) {
+    aRenderingContext.Translate(r.TopRight());
+    aRenderingContext.Scale(-mScaleX, mScaleY);
+  } else {
+    aRenderingContext.Translate(r.TopLeft());
+    aRenderingContext.Scale(mScaleX, mScaleY);
+  }
 
   // update the bounding rectangle.
   r.x = r.y = 0;
   r.width /= mScaleX;
   r.height /= mScaleY;
 }
 
 void
--- a/layout/mathml/nsMathMLChar.h
+++ b/layout/mathml/nsMathMLChar.h
@@ -107,16 +107,17 @@ public:
   nsMathMLChar(nsMathMLChar* aParent = nsnull) {
     MOZ_COUNT_CTOR(nsMathMLChar);
     mStyleContext = nsnull;
     mSibling = nsnull;
     mParent = aParent;
     mUnscaledAscent = 0;
     mScaleX = mScaleY = 1.0;
     mDrawNormal = true;
+    mMirrored = false;
   }
 
   ~nsMathMLChar() { // not a virtual destructor: this class is not intended to be subclassed
     MOZ_COUNT_DTOR(nsMathMLChar);
     // there is only one style context owned by the "root" char
     // and it may be used by child chars as well
     if (!mParent && mStyleContext) { // only the "root" need to release it
       mStyleContext->Release();
@@ -141,17 +142,18 @@ public:
   // @param aContainerSize - IN - suggested size for the stretched char
   // @param aDesiredStretchSize - OUT - the size that the char wants
   nsresult
   Stretch(nsPresContext*           aPresContext,
           nsRenderingContext&     aRenderingContext,
           nsStretchDirection       aStretchDirection,
           const nsBoundingMetrics& aContainerSize,
           nsBoundingMetrics&       aDesiredStretchSize,
-          PRUint32                 aStretchHint = NS_STRETCH_NORMAL);
+          PRUint32                 aStretchHint,
+          bool                     aRTL);
 
   void
   SetData(nsPresContext* aPresContext,
           nsString&       aData);
 
   void
   GetData(nsString& aData) {
     aData = mData;
@@ -253,16 +255,18 @@ private:
   // from the family in the nsStyleContext.
   nsString           mFamily;
   // mUnscaledAscent is the actual ascent of the char.
   nscoord            mUnscaledAscent;
   // mScaleX, mScaleY are the factors by which we scale the char.
   float              mScaleX, mScaleY;
   // mDrawNormal indicates whether we use special glyphs or not.
   bool               mDrawNormal;
+  // mMirrored indicates whether the character is mirrored. 
+  bool               mMirrored;
 
   class StretchEnumContext;
   friend class StretchEnumContext;
 
   // helper methods
   nsresult
   StretchInternal(nsPresContext*           aPresContext,
                   nsRenderingContext&     aRenderingContext,
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -440,21 +440,23 @@ nsMathMLContainerFrame::Stretch(nsRender
         // (need to test coreFrame since <mfrac> resets other things)
         if (parentData.coreFrame != mEmbellishData.coreFrame) {
           // (we fetch values from the core since they may use units that depend
           // on style data, and style changes could have occurred in the core since
           // our last visit there)
           nsEmbellishData coreData;
           GetEmbellishDataFrom(mEmbellishData.coreFrame, coreData);
 
-          mBoundingMetrics.width += coreData.leftSpace + coreData.rightSpace;
+          mBoundingMetrics.width +=
+            coreData.leadingSpace + coreData.trailingSpace;
           aDesiredStretchSize.width = mBoundingMetrics.width;
           aDesiredStretchSize.mBoundingMetrics.width = mBoundingMetrics.width;
 
-          nscoord dx = coreData.leftSpace;
+          nscoord dx = (NS_MATHML_IS_RTL(mPresentationData.flags) ?
+                        coreData.trailingSpace : coreData.leadingSpace);
           if (dx != 0) {
             mBoundingMetrics.leftBearing += dx;
             mBoundingMetrics.rightBearing += dx;
             aDesiredStretchSize.mBoundingMetrics.leftBearing += dx;
             aDesiredStretchSize.mBoundingMetrics.rightBearing += dx;
 
             nsIFrame* childFrame = mFrames.FirstChild();
             while (childFrame) {
@@ -1188,38 +1190,44 @@ static nscoord GetThinSpace(const nsStyl
 {
   return NSToCoordRound(float(aStyleFont->mFont.size)*float(3) / float(18));
 }
 
 class nsMathMLContainerFrame::RowChildFrameIterator {
 public:
   explicit RowChildFrameIterator(nsMathMLContainerFrame* aParentFrame) :
     mParentFrame(aParentFrame),
-    mChildFrame(aParentFrame->mFrames.FirstChild()),
     mX(0),
     mCarrySpace(0),
-    mFromFrameType(eMathMLFrameType_UNKNOWN)
+    mFromFrameType(eMathMLFrameType_UNKNOWN),
+    mRTL(NS_MATHML_IS_RTL(aParentFrame->mPresentationData.flags))
   {
+    if (!mRTL) {
+      mChildFrame = aParentFrame->mFrames.FirstChild();
+    } else {
+      mChildFrame = aParentFrame->mFrames.LastChild();
+    }
+
     if (!mChildFrame)
       return;
 
     InitMetricsForChild();
-    // Remove left correction in <msqrt> because the sqrt glyph itself is
-    // there first.
-    if (mParentFrame->GetContent()->Tag() == nsGkAtoms::msqrt_) {
-      mX = 0;
-    }
   }
 
   RowChildFrameIterator& operator++()
   {
     // add child size + italic correction
     mX += mSize.mBoundingMetrics.width + mItalicCorrection;
 
-    mChildFrame = mChildFrame->GetNextSibling();
+    if (!mRTL) {
+      mChildFrame = mChildFrame->GetNextSibling();
+    } else {
+      mChildFrame = mChildFrame->GetPrevSibling();
+    }
+
     if (!mChildFrame)
       return *this;
 
     eMathMLFrameType prevFrameType = mChildFrameType;
     InitMetricsForChild();
 
     // add inter frame spacing
     const nsStyleFont* font = mParentFrame->GetStyleFont();
@@ -1246,26 +1254,39 @@ private:
   nsHTMLReflowMetrics mSize;
   nscoord mX;
 
   nscoord mItalicCorrection;
   eMathMLFrameType mChildFrameType;
   PRInt32 mCarrySpace;
   eMathMLFrameType mFromFrameType;
 
+  bool mRTL;
+
   void InitMetricsForChild()
   {
     GetReflowAndBoundingMetricsFor(mChildFrame, mSize, mSize.mBoundingMetrics,
                                    &mChildFrameType);
-    nscoord leftCorrection;
-    GetItalicCorrection(mSize.mBoundingMetrics, leftCorrection,
-                        mItalicCorrection);
+    nscoord leftCorrection, rightCorrection;
+    GetItalicCorrection(mSize.mBoundingMetrics,
+                        leftCorrection, rightCorrection);
+    if (!mChildFrame->GetPrevSibling() &&
+        mParentFrame->GetContent()->Tag() == nsGkAtoms::msqrt_) {
+      // Remove leading correction in <msqrt> because the sqrt glyph itself is
+      // there first.
+      if (!mRTL) {
+        leftCorrection = 0;
+      } else {
+        rightCorrection = 0;
+      }
+    }
     // add left correction -- this fixes the problem of the italic 'f'
     // e.g., <mo>q</mo> <mi>f</mi> <mo>I</mo> 
     mX += leftCorrection;
+    mItalicCorrection = rightCorrection;
   }
 };
 
 /* virtual */ nsresult
 nsMathMLContainerFrame::Place(nsRenderingContext& aRenderingContext,
                               bool                 aPlaceOrigin,
                               nsHTMLReflowMetrics& aDesiredSize)
 {
@@ -1504,18 +1525,18 @@ nsMathMLContainerFrame::TransmitAutomati
   }
 
   if (childFrame || !embellishedOpFound) {
     // The element is not embellished operator
     mPresentationData.baseFrame = nsnull;
     mEmbellishData.flags = 0;
     mEmbellishData.coreFrame = nsnull;
     mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
-    mEmbellishData.leftSpace = 0;
-    mEmbellishData.rightSpace = 0;
+    mEmbellishData.leadingSpace = 0;
+    mEmbellishData.trailingSpace = 0;
   }
 
   if (childFrame || embellishedOpFound) {
     // The element is not space-like
     mPresentationData.flags &= ~NS_MATHML_SPACE_LIKE;
   }
 
   return NS_OK;
--- a/layout/mathml/nsMathMLContainerFrame.h
+++ b/layout/mathml/nsMathMLContainerFrame.h
@@ -188,16 +188,24 @@ public:
   //        to re-layout its children using ReLayoutChildren(mParent);
   //        Therefore, there is an overhead here in that our siblings are re-laid
   //        too (e.g., this happens with <mstyle>, <munder>, <mover>, <munderover>). 
   NS_IMETHOD
   AttributeChanged(PRInt32         aNameSpaceID,
                    nsIAtom*        aAttribute,
                    PRInt32         aModType);
 
+  // helper function to apply mirroring to a horizontal coordinate, if needed.
+  nscoord
+  MirrorIfRTL(nscoord aParentWidth, nscoord aChildWidth, nscoord aChildLeading)
+  {
+    return (NS_MATHML_IS_RTL(mPresentationData.flags) ?
+            aParentWidth - aChildWidth - aChildLeading : aChildLeading);
+  }
+
   // --------------------------------------------------------------------------
   // Additional methods 
 
 protected:
   /* Place :
    * This method is used to measure or position child frames and other
    * elements.  It may be called any number of times with aPlaceOrigin
    * false to measure, and the final call of the Reflow process before
--- a/layout/mathml/nsMathMLFrame.cpp
+++ b/layout/mathml/nsMathMLFrame.cpp
@@ -16,16 +16,17 @@
  *
  * The Initial Developer of the Original Code is
  * The University Of Queensland.
  * Portions created by the Initial Developer are Copyright (C) 1999
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Roger B. Sidje <rbs@maths.uq.edu.au>
+ *   Frederic Wang <fred.wang@free.fr>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -83,48 +84,86 @@ nsMathMLFrame::FindAttrDisplaystyle(nsIC
   case 1:
     aPresentationData.flags |= NS_MATHML_DISPLAYSTYLE;
     aPresentationData.flags |= NS_MATHML_EXPLICIT_DISPLAYSTYLE;
     break;
   }
   // no reset if the attr isn't found. so be sure to call it on inherited flags
 }
 
+// snippet of code used by the tags where the dir attribute is allowed.
+/* static */ void
+nsMathMLFrame::FindAttrDirectionality(nsIContent*         aContent,
+                                      nsPresentationData& aPresentationData)
+{
+  NS_ASSERTION(aContent->Tag() == nsGkAtoms::math ||
+               aContent->Tag() == nsGkAtoms::mrow_ ||
+               aContent->Tag() == nsGkAtoms::mstyle_ ||
+               aContent->Tag() == nsGkAtoms::mi_ ||
+               aContent->Tag() == nsGkAtoms::mn_ ||
+               aContent->Tag() == nsGkAtoms::mo_ ||
+               aContent->Tag() == nsGkAtoms::mtext_ ||
+               aContent->Tag() == nsGkAtoms::ms_, "bad caller");
+
+  static nsIContent::AttrValuesArray strings[] =
+    {&nsGkAtoms::ltr, &nsGkAtoms::rtl, nsnull};
+
+  // see if the explicit dir attribute is there
+  switch (aContent->FindAttrValueIn(kNameSpaceID_None,
+                                    nsGkAtoms::dir, strings, eCaseMatters))
+    {
+    case 0:
+      aPresentationData.flags &= ~NS_MATHML_RTL;
+      break;
+    case 1:
+      aPresentationData.flags |= NS_MATHML_RTL;
+      break;
+    }
+  // no reset if the attr isn't found. so be sure to call it on inherited flags
+}
+
 NS_IMETHODIMP
 nsMathMLFrame::InheritAutomaticData(nsIFrame* aParent) 
 {
   mEmbellishData.flags = 0;
   mEmbellishData.coreFrame = nsnull;
   mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
-  mEmbellishData.leftSpace = 0;
-  mEmbellishData.rightSpace = 0;
+  mEmbellishData.leadingSpace = 0;
+  mEmbellishData.trailingSpace = 0;
 
   mPresentationData.flags = 0;
   mPresentationData.baseFrame = nsnull;
   mPresentationData.mstyle = nsnull;
 
   // by default, just inherit the display of our parent
   nsPresentationData parentData;
   GetPresentationDataFrom(aParent, parentData);
   mPresentationData.mstyle = parentData.mstyle;
   if (NS_MATHML_IS_DISPLAYSTYLE(parentData.flags)) {
     mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE;
   }
+  if (NS_MATHML_IS_RTL(parentData.flags)) {
+    mPresentationData.flags |= NS_MATHML_RTL;
+  }
 
 #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
   mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS;
 #endif
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLFrame::UpdatePresentationData(PRUint32        aFlagsValues,
                                       PRUint32        aWhichFlags)
 {
+  NS_ASSERTION(NS_MATHML_IS_DISPLAYSTYLE(aWhichFlags) ||
+               NS_MATHML_IS_COMPRESSED(aWhichFlags),
+               "aWhichFlags should only be displaystyle or compression flag"); 
+
   // update flags that are relevant to this call
   if (NS_MATHML_IS_DISPLAYSTYLE(aWhichFlags)) {
     // updating the displaystyle flag is allowed
     if (NS_MATHML_IS_DISPLAYSTYLE(aFlagsValues)) {
       mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE;
     }
     else {
       mPresentationData.flags &= ~NS_MATHML_DISPLAYSTYLE;
@@ -167,18 +206,18 @@ nsMathMLFrame::ResolveMathMLCharStyle(ns
 /* static */ void
 nsMathMLFrame::GetEmbellishDataFrom(nsIFrame*        aFrame,
                                     nsEmbellishData& aEmbellishData)
 {
   // initialize OUT params
   aEmbellishData.flags = 0;
   aEmbellishData.coreFrame = nsnull;
   aEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
-  aEmbellishData.leftSpace = 0;
-  aEmbellishData.rightSpace = 0;
+  aEmbellishData.leadingSpace = 0;
+  aEmbellishData.trailingSpace = 0;
 
   if (aFrame && aFrame->IsFrameOfType(nsIFrame::eMathML)) {
     nsIMathMLFrame* mathMLFrame = do_QueryFrame(aFrame);
     if (mathMLFrame) {
       mathMLFrame->GetEmbellishData(aEmbellishData);
     }
   }
 }
@@ -216,16 +255,17 @@ nsMathMLFrame::GetPresentationDataFrom(n
       break;
 
     if (content->Tag() == nsGkAtoms::math) {
       const nsStyleDisplay* display = frame->GetStyleDisplay();
       if (display->mDisplay == NS_STYLE_DISPLAY_BLOCK) {
         aPresentationData.flags |= NS_MATHML_DISPLAYSTYLE;
       }
       FindAttrDisplaystyle(content, aPresentationData);
+      FindAttrDirectionality(content, aPresentationData);
       aPresentationData.mstyle = frame->GetFirstContinuation();
       break;
     }
     frame = frame->GetParent();
   }
   NS_WARN_IF_FALSE(frame && frame->GetContent(),
                    "bad MathML markup - could not find the top <math> element");
 }
--- a/layout/mathml/nsMathMLFrame.h
+++ b/layout/mathml/nsMathMLFrame.h
@@ -16,16 +16,17 @@
  *
  * The Initial Developer of the Original Code is
  * The University Of Queensland.
  * Portions created by the Initial Developer are Copyright (C) 1999
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Roger B. Sidje <rbs@maths.uq.edu.au>
+ *   Frederic Wang <fred.wang@free.fr>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -163,16 +164,21 @@ public:
                           nsPresentationData& aPresentationData,
                           bool                aClimbTree = true);
 
   // helper used by <mstyle> and <mtable> to see if they have a displaystyle attribute 
   static void
   FindAttrDisplaystyle(nsIContent*         aContent,
                        nsPresentationData& aPresentationData);
 
+  // helper used to see if an element has a dir attribute 
+  static void
+  FindAttrDirectionality(nsIContent*         aContent,
+                         nsPresentationData& aPresentationData);
+
   // helper to check if a content has an attribute. If content is nsnull or if
   // the attribute is not there, check if the attribute is on the mstyle hierarchy
   // @return true     --if attribute exists
   //         false --if attribute doesn't exist
   static bool
   GetAttribute(nsIContent* aContent,
                nsIFrame*   aMathMLmstyleFrame,          
                nsIAtom*    aAttributeAtom,
--- a/layout/mathml/nsMathMLOperators.cpp
+++ b/layout/mathml/nsMathMLOperators.cpp
@@ -49,26 +49,26 @@
 #include "nsCRT.h"
 
 #include "nsMathMLOperators.h"
 
 // operator dictionary entry
 struct OperatorData {
   OperatorData(void)
     : mFlags(0),
-      mLeftSpace(0.0f),
-      mRightSpace(0.0f)
+      mLeadingSpace(0.0f),
+      mTrailingSpace(0.0f)
   {
   }
 
   // member data
   nsString        mStr;
   nsOperatorFlags mFlags;
-  float           mLeftSpace;   // unit is em
-  float           mRightSpace;  // unit is em
+  float           mLeadingSpace;   // unit is em
+  float           mTrailingSpace;  // unit is em
 };
 
 static PRInt32         gTableRefCount = 0;
 static PRUint32        gOperatorCount = 0;
 static OperatorData*   gOperatorArray = nsnull;
 static nsHashtable*    gOperatorTable = nsnull;
 static bool            gInitialized   = false;
 static nsTArray<nsString>*      gInvariantCharArray    = nsnull;
@@ -112,16 +112,18 @@ SetBooleanProperty(OperatorData* aOperat
   else if (aName.EqualsLiteral("separator"))
     aOperatorData->mFlags |=  NS_MATHML_OPERATOR_SEPARATOR;
   else if (aName.EqualsLiteral("movablelimits"))
     aOperatorData->mFlags |= NS_MATHML_OPERATOR_MOVABLELIMITS;
   else if (aName.EqualsLiteral("symmetric"))
     aOperatorData->mFlags |= NS_MATHML_OPERATOR_SYMMETRIC;
   else if (aName.EqualsLiteral("integral"))
     aOperatorData->mFlags |= NS_MATHML_OPERATOR_INTEGRAL;
+  else if (aName.EqualsLiteral("mirrorable"))
+    aOperatorData->mFlags |= NS_MATHML_OPERATOR_MIRRORABLE;
 }
 
 static void
 SetProperty(OperatorData* aOperatorData,
             nsString      aName,
             nsString      aValue)
 {
   if (aName.IsEmpty() || aValue.IsEmpty())
@@ -134,32 +136,32 @@ SetProperty(OperatorData* aOperatorData,
 
   if (aName.EqualsLiteral("direction")) {
     if (aValue.EqualsLiteral("vertical"))
       aOperatorData->mFlags |= NS_MATHML_OPERATOR_DIRECTION_VERTICAL;
     else if (aValue.EqualsLiteral("horizontal"))
       aOperatorData->mFlags |= NS_MATHML_OPERATOR_DIRECTION_HORIZONTAL;
     else return; // invalid value
   } else {
-    bool isLeftSpace;
+    bool isLeadingSpace;
     if (aName.EqualsLiteral("lspace"))
-      isLeftSpace = true;
+      isLeadingSpace = true;
     else if (aName.EqualsLiteral("rspace"))
-      isLeftSpace = false;
+      isLeadingSpace = false;
     else return;  // input is not applicable
 
     // aValue is assumed to be a digit from 0 to 7
     PRInt32 error = 0;
     float space = aValue.ToFloat(&error) / 18.0;
     if (error) return;
 
-    if (isLeftSpace)
-      aOperatorData->mLeftSpace = space;
+    if (isLeadingSpace)
+      aOperatorData->mLeadingSpace = space;
     else
-      aOperatorData->mRightSpace = space;
+      aOperatorData->mTrailingSpace = space;
   }
 }
 
 static bool
 SetOperator(OperatorData*   aOperatorData,
             nsOperatorFlags aForm,
             const nsCString& aOperator,
             nsString&        aAttributes)
@@ -404,24 +406,24 @@ GetOperatorData(const nsString& aOperato
   nsStringKey hkey(key);
   return (OperatorData*)gOperatorTable->Get(&hkey);
 }
 
 bool
 nsMathMLOperators::LookupOperator(const nsString&       aOperator,
                                   const nsOperatorFlags aForm,
                                   nsOperatorFlags*      aFlags,
-                                  float*                aLeftSpace,
-                                  float*                aRightSpace)
+                                  float*                aLeadingSpace,
+                                  float*                aTrailingSpace)
 {
   if (!gInitialized) {
     InitGlobals();
   }
   if (gOperatorTable) {
-    NS_ASSERTION(aFlags && aLeftSpace && aRightSpace, "bad usage");
+    NS_ASSERTION(aFlags && aLeadingSpace && aTrailingSpace, "bad usage");
     NS_ASSERTION(aForm > 0 && aForm < 4, "*** invalid call ***");
 
     // The MathML REC says:
     // If the operator does not occur in the dictionary with the specified form,
     // the renderer should use one of the forms which is available there, in the
     // order of preference: infix, postfix, prefix.
 
     OperatorData* found;
@@ -436,67 +438,67 @@ nsMathMLOperators::LookupOperator(const 
           if (form != NS_MATHML_OPERATOR_FORM_PREFIX) {
             found = GetOperatorData(aOperator, NS_MATHML_OPERATOR_FORM_PREFIX);
           }
         }
       }
     }
     if (found) {
       NS_ASSERTION(found->mStr.Equals(aOperator), "bad setup");
-      *aLeftSpace = found->mLeftSpace;
-      *aRightSpace = found->mRightSpace;
+      *aLeadingSpace = found->mLeadingSpace;
+      *aTrailingSpace = found->mTrailingSpace;
       *aFlags &= ~NS_MATHML_OPERATOR_FORM; // clear the form bits
       *aFlags |= found->mFlags; // just add bits without overwriting
       return true;
     }
   }
   return false;
 }
 
 void
 nsMathMLOperators::LookupOperators(const nsString&       aOperator,
                                    nsOperatorFlags*      aFlags,
-                                   float*                aLeftSpace,
-                                   float*                aRightSpace)
+                                   float*                aLeadingSpace,
+                                   float*                aTrailingSpace)
 {
   if (!gInitialized) {
     InitGlobals();
   }
 
   aFlags[NS_MATHML_OPERATOR_FORM_INFIX] = 0;
-  aLeftSpace[NS_MATHML_OPERATOR_FORM_INFIX] = 0.0f;
-  aRightSpace[NS_MATHML_OPERATOR_FORM_INFIX] = 0.0f;
+  aLeadingSpace[NS_MATHML_OPERATOR_FORM_INFIX] = 0.0f;
+  aTrailingSpace[NS_MATHML_OPERATOR_FORM_INFIX] = 0.0f;
 
   aFlags[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0;
-  aLeftSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0.0f;
-  aRightSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0.0f;
+  aLeadingSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0.0f;
+  aTrailingSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0.0f;
 
   aFlags[NS_MATHML_OPERATOR_FORM_PREFIX] = 0;
-  aLeftSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = 0.0f;
-  aRightSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = 0.0f;
+  aLeadingSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = 0.0f;
+  aTrailingSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = 0.0f;
 
   if (gOperatorTable) {
     OperatorData* found;
     found = GetOperatorData(aOperator, NS_MATHML_OPERATOR_FORM_INFIX);
     if (found) {
       aFlags[NS_MATHML_OPERATOR_FORM_INFIX] = found->mFlags;
-      aLeftSpace[NS_MATHML_OPERATOR_FORM_INFIX] = found->mLeftSpace;
-      aRightSpace[NS_MATHML_OPERATOR_FORM_INFIX] = found->mRightSpace;
+      aLeadingSpace[NS_MATHML_OPERATOR_FORM_INFIX] = found->mLeadingSpace;
+      aTrailingSpace[NS_MATHML_OPERATOR_FORM_INFIX] = found->mTrailingSpace;
     }
     found = GetOperatorData(aOperator, NS_MATHML_OPERATOR_FORM_POSTFIX);
     if (found) {
       aFlags[NS_MATHML_OPERATOR_FORM_POSTFIX] = found->mFlags;
-      aLeftSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = found->mLeftSpace;
-      aRightSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = found->mRightSpace;
+      aLeadingSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = found->mLeadingSpace;
+      aTrailingSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = found->mTrailingSpace;
     }
     found = GetOperatorData(aOperator, NS_MATHML_OPERATOR_FORM_PREFIX);
     if (found) {
       aFlags[NS_MATHML_OPERATOR_FORM_PREFIX] = found->mFlags;
-      aLeftSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = found->mLeftSpace;
-      aRightSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = found->mRightSpace;
+      aLeadingSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = found->mLeadingSpace;
+      aTrailingSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = found->mTrailingSpace;
     }
   }
 }
 
 bool
 nsMathMLOperators::IsMutableOperator(const nsString& aOperator)
 {
   if (!gInitialized) {
@@ -510,16 +512,30 @@ nsMathMLOperators::IsMutableOperator(con
   nsOperatorFlags allFlags =
     flags[NS_MATHML_OPERATOR_FORM_INFIX] |
     flags[NS_MATHML_OPERATOR_FORM_POSTFIX] |
     flags[NS_MATHML_OPERATOR_FORM_PREFIX];
   return NS_MATHML_OPERATOR_IS_STRETCHY(allFlags) ||
          NS_MATHML_OPERATOR_IS_LARGEOP(allFlags);
 }
 
+/* static */ bool
+nsMathMLOperators::IsMirrorableOperator(const nsString& aOperator)
+{
+  // LookupOperator will search infix, postfix and prefix forms of aOperator and
+  // return the first form found. It is assumed that all these forms have same
+  // mirrorability.
+  nsOperatorFlags flags = 0;
+  float dummy;
+  nsMathMLOperators::LookupOperator(aOperator,
+                                    NS_MATHML_OPERATOR_FORM_INFIX,
+                                    &flags, &dummy, &dummy);
+  return NS_MATHML_OPERATOR_IS_MIRRORABLE(flags);
+}
+
 /* static */ nsStretchDirection
 nsMathMLOperators::GetStretchyDirection(const nsString& aOperator)
 {
   // LookupOperator will search infix, postfix and prefix forms of aOperator and
   // return the first form found. It is assumed that all these forms have same
   // direction.
   nsOperatorFlags flags = 0;
   float dummy;
--- a/layout/mathml/nsMathMLOperators.h
+++ b/layout/mathml/nsMathMLOperators.h
@@ -76,22 +76,23 @@ enum {
   NS_MATHML_OPERATOR_STRETCHY           = 1<<4,
   NS_MATHML_OPERATOR_FENCE              = 1<<5,
   NS_MATHML_OPERATOR_ACCENT             = 1<<6,
   NS_MATHML_OPERATOR_LARGEOP            = 1<<7,
   NS_MATHML_OPERATOR_SEPARATOR          = 1<<8,
   NS_MATHML_OPERATOR_MOVABLELIMITS      = 1<<9,
   NS_MATHML_OPERATOR_SYMMETRIC          = 1<<10,
   NS_MATHML_OPERATOR_INTEGRAL           = 1<<11,
+  NS_MATHML_OPERATOR_MIRRORABLE         = 1<<12,
 
   // Additional bits not stored in the dictionary
-  NS_MATHML_OPERATOR_MINSIZE_ABSOLUTE   = 1<<12,
-  NS_MATHML_OPERATOR_MAXSIZE_ABSOLUTE   = 1<<13,
-  NS_MATHML_OPERATOR_LEFTSPACE_ATTR     = 1<<14,
-  NS_MATHML_OPERATOR_RIGHTSPACE_ATTR    = 1<<15
+  NS_MATHML_OPERATOR_MINSIZE_ABSOLUTE   = 1<<13,
+  NS_MATHML_OPERATOR_MAXSIZE_ABSOLUTE   = 1<<14,
+  NS_MATHML_OPERATOR_LSPACE_ATTR     = 1<<15,
+  NS_MATHML_OPERATOR_RSPACE_ATTR    = 1<<16
 };
 
 #define NS_MATHML_OPERATOR_SIZE_INFINITY NS_IEEEPositiveInfinity()
 
 // Style invariant characters (chars have their own intrinsic predefined style)
 enum eMATHVARIANT {
   eMATHVARIANT_NONE = -1,
   eMATHVARIANT_normal = 0,
@@ -124,36 +125,41 @@ public:
   // If the operator is not found under the supplied form but is found under a 
   // different form, the method returns true as well. The caller can test the
   // output parameter aFlags to know exactly under which form the operator was
   // found in the Operator Dictionary.
   static bool
   LookupOperator(const nsString&       aOperator,
                  const nsOperatorFlags aForm,
                  nsOperatorFlags*      aFlags,
-                 float*                aLeftSpace,
-                 float*                aRightSpace);
+                 float*                aLeadingSpace,
+                 float*                aTrailingSpace);
 
    // LookupOperators:
    // Helper to return all the forms under which an operator is listed in the
    // Operator Dictionary. The caller must pass arrays of size 4, and use 
-   // aFlags[NS_MATHML_OPERATOR_FORM_{INFIX|POSTFIX|PREFIX}], aLeftSpace[], etc,
-   // to access the attributes of the operator under a particular form. If the
-   // operator wasn't found under a form, its entry aFlags[form] is set to zero.
+   // aFlags[NS_MATHML_OPERATOR_FORM_{INFIX|POSTFIX|PREFIX}],
+   // aLeadingSpace[], etc, to access the attributes of the operator under a
+   // particular form. If the operator wasn't found under a form, its entry
+   // aFlags[form] is set to zero.
    static void
    LookupOperators(const nsString&       aOperator,
                    nsOperatorFlags*      aFlags,
-                   float*                aLeftSpace,
-                   float*                aRightSpace);
+                   float*                aLeadingSpace,
+                   float*                aTrailingSpace);
 
   // IsMutableOperator:
   // Return true if the operator exists and is stretchy or largeop
   static bool
   IsMutableOperator(const nsString& aOperator);
 
+  // Helper functions used by the nsMathMLChar class.
+  static bool
+  IsMirrorableOperator(const nsString& aOperator);
+
   // Helper function used by the nsMathMLChar class.
   static nsStretchDirection GetStretchyDirection(const nsString& aOperator);
 
   // Return the variant type of one Unicode Mathematical Alphanumeric Symbol
   // character (which may be represented by a surrogate pair), or return
   // eMATHVARIANT_NONE if aChar is not such a character.
   static eMATHVARIANT LookupInvariantChar(const nsAString& aChar);
 
@@ -224,21 +230,24 @@ public:
   (NS_MATHML_OPERATOR_MOVABLELIMITS == ((_flags) & NS_MATHML_OPERATOR_MOVABLELIMITS))
 
 #define NS_MATHML_OPERATOR_IS_SYMMETRIC(_flags) \
   (NS_MATHML_OPERATOR_SYMMETRIC == ((_flags) & NS_MATHML_OPERATOR_SYMMETRIC))
 
 #define NS_MATHML_OPERATOR_IS_INTEGRAL(_flags) \
   (NS_MATHML_OPERATOR_INTEGRAL == ((_flags) & NS_MATHML_OPERATOR_INTEGRAL))
 
+#define NS_MATHML_OPERATOR_IS_MIRRORABLE(_flags) \
+  (NS_MATHML_OPERATOR_MIRRORABLE == ((_flags) & NS_MATHML_OPERATOR_MIRRORABLE))
+
 #define NS_MATHML_OPERATOR_MINSIZE_IS_ABSOLUTE(_flags) \
   (NS_MATHML_OPERATOR_MINSIZE_ABSOLUTE == ((_flags) & NS_MATHML_OPERATOR_MINSIZE_ABSOLUTE))
 
 #define NS_MATHML_OPERATOR_MAXSIZE_IS_ABSOLUTE(_flags) \
   (NS_MATHML_OPERATOR_MAXSIZE_ABSOLUTE == ((_flags) & NS_MATHML_OPERATOR_MAXSIZE_ABSOLUTE))
 
-#define NS_MATHML_OPERATOR_HAS_LEFTSPACE_ATTR(_flags) \
-  (NS_MATHML_OPERATOR_LEFTSPACE_ATTR == ((_flags) & NS_MATHML_OPERATOR_LEFTSPACE_ATTR))
+#define NS_MATHML_OPERATOR_HAS_LSPACE_ATTR(_flags) \
+  (NS_MATHML_OPERATOR_LSPACE_ATTR == ((_flags) & NS_MATHML_OPERATOR_LSPACE_ATTR))
 
-#define NS_MATHML_OPERATOR_HAS_RIGHTSPACE_ATTR(_flags) \
-  (NS_MATHML_OPERATOR_RIGHTSPACE_ATTR == ((_flags) & NS_MATHML_OPERATOR_RIGHTSPACE_ATTR))
+#define NS_MATHML_OPERATOR_HAS_RSPACE_ATTR(_flags) \
+  (NS_MATHML_OPERATOR_RSPACE_ATTR == ((_flags) & NS_MATHML_OPERATOR_RSPACE_ATTR))
 
 #endif /* nsMathMLOperators_h___ */
--- a/layout/mathml/nsMathMLTokenFrame.cpp
+++ b/layout/mathml/nsMathMLTokenFrame.cpp
@@ -17,16 +17,17 @@
  * The Initial Developer of the Original Code is
  * The University of Queensland.
  * Portions created by the Initial Developer are Copyright (C) 1999
  * the Initial Developer. All Rights Reserved.
  * 
  * Contributor(s): 
  *   Roger B. Sidje <rbs@maths.uq.edu.au>
  *   Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
+ *   Frederic Wang <fred.wang@free.fr>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -59,16 +60,21 @@ nsMathMLTokenFrame::~nsMathMLTokenFrame(
 }
 
 NS_IMETHODIMP
 nsMathMLTokenFrame::InheritAutomaticData(nsIFrame* aParent)
 {
   // let the base class get the default from our parent
   nsMathMLContainerFrame::InheritAutomaticData(aParent);
 
+  if (mContent->Tag() != nsGkAtoms::mspace_) {
+    // see if the directionality attribute is there
+    nsMathMLFrame::FindAttrDirectionality(mContent, mPresentationData);
+  }
+
   ProcessTextData();
 
   return NS_OK;
 }
 
 eMathMLFrameType
 nsMathMLTokenFrame::GetMathMLFrameType()
 {
--- a/layout/mathml/nsMathMLmencloseFrame.cpp
+++ b/layout/mathml/nsMathMLmencloseFrame.cpp
@@ -236,17 +236,18 @@ nsMathMLmencloseFrame::BuildDisplayList(
   mencloseRect.x = mencloseRect.y = 0;
 
   if (IsToDraw(NOTATION_RADICAL)) {
     rv = mMathMLChar[mRadicalCharIndex].Display(aBuilder, this, aLists);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsRect rect;
     mMathMLChar[mRadicalCharIndex].GetRect(rect);
-    rect.MoveBy(rect.width, 0);
+    rect.MoveBy(NS_MATHML_IS_RTL(mPresentationData.flags) ?
+                -mContentWidth : rect.width, 0);
     rect.SizeTo(mContentWidth, mRuleThickness);
     rv = DisplayBar(aBuilder, this, rect, aLists);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (IsToDraw(NOTATION_LONGDIV)) {
     rv = mMathMLChar[mLongDivCharIndex].Display(aBuilder, this, aLists);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -491,17 +492,17 @@ nsMathMLmencloseFrame::PlaceInternal(nsR
       nsBoundingMetrics contSize = bmBase;
       contSize.ascent = mRuleThickness;
       contSize.descent = bmBase.ascent + bmBase.descent + psi;
 
       // height(longdiv) should be >= height(base) + psi + mRuleThickness
       mMathMLChar[mLongDivCharIndex].Stretch(PresContext(), aRenderingContext,
                                              NS_STRETCH_DIRECTION_VERTICAL,
                                              contSize, bmLongdivChar,
-                                             NS_STRETCH_LARGER);
+                                             NS_STRETCH_LARGER, false);
       mMathMLChar[mLongDivCharIndex].GetBoundingMetrics(bmLongdivChar);
 
       // Update horizontal parameters
       dx_left = NS_MAX(dx_left, bmLongdivChar.width);
 
       // Update vertical parameters
       longdivAscent = bmBase.ascent + psi + mRuleThickness;
       longdivDescent = NS_MAX(bmBase.descent,
@@ -513,38 +514,42 @@ nsMathMLmencloseFrame::PlaceInternal(nsR
       mBoundingMetrics.descent = NS_MAX(mBoundingMetrics.descent,
                                         longdivDescent);
     }
   }
 
   ///////////////
   // radical notation:
   if (IsToDraw(NOTATION_RADICAL)) {
+    nscoord *dx_leading =
+      NS_MATHML_IS_RTL(mPresentationData.flags) ? &dx_right : &dx_left;
+    
     if (aWidthOnly) {
       nscoord radical_width = mMathMLChar[mRadicalCharIndex].
         GetMaxWidth(PresContext(), aRenderingContext);
       
       // Update horizontal parameters
-      dx_left = NS_MAX(dx_left, radical_width);
+      *dx_leading = NS_MAX(*dx_leading, radical_width);
     } else {
       // Stretch the radical symbol to the appropriate height if it is not
       // big enough.
       nsBoundingMetrics contSize = bmBase;
       contSize.ascent = mRuleThickness;
       contSize.descent = bmBase.ascent + bmBase.descent + psi;
 
       // height(radical) should be >= height(base) + psi + mRuleThickness
       mMathMLChar[mRadicalCharIndex].Stretch(PresContext(), aRenderingContext,
                                              NS_STRETCH_DIRECTION_VERTICAL,
                                              contSize, bmRadicalChar,
-                                             NS_STRETCH_LARGER);
+                                             NS_STRETCH_LARGER,
+                                             NS_MATHML_IS_RTL(mPresentationData.flags));
       mMathMLChar[mRadicalCharIndex].GetBoundingMetrics(bmRadicalChar);
 
       // Update horizontal parameters
-      dx_left = NS_MAX(dx_left, bmRadicalChar.width);
+      *dx_leading = NS_MAX(*dx_leading, bmRadicalChar.width);
 
       // Update vertical parameters
       radicalAscent = bmBase.ascent + psi + mRuleThickness;
       radicalDescent = NS_MAX(bmBase.descent,
                               (bmRadicalChar.ascent + bmRadicalChar.descent -
                                radicalAscent));
 
       mBoundingMetrics.ascent = NS_MAX(mBoundingMetrics.ascent,
@@ -648,24 +653,27 @@ nsMathMLmencloseFrame::PlaceInternal(nsR
       mMathMLChar[mLongDivCharIndex].SetRect(nsRect(dx_left -
                                                     bmLongdivChar.width,
                                                     aDesiredSize.ascent -
                                                     longdivAscent,
                                                     bmLongdivChar.width,
                                                     bmLongdivChar.ascent +
                                                     bmLongdivChar.descent));
 
-    if (IsToDraw(NOTATION_RADICAL))
-      mMathMLChar[mRadicalCharIndex].SetRect(nsRect(dx_left -
-                                                    bmRadicalChar.width,
+    if (IsToDraw(NOTATION_RADICAL)) {
+      nscoord dx = NS_MATHML_IS_RTL(mPresentationData.flags) ?
+        dx_left + bmBase.width : dx_left - bmRadicalChar.width;
+
+      mMathMLChar[mRadicalCharIndex].SetRect(nsRect(dx,
                                                     aDesiredSize.ascent -
                                                     radicalAscent,
                                                     bmRadicalChar.width,
                                                     bmRadicalChar.ascent +
                                                     bmRadicalChar.descent));
+    }
 
     mContentWidth = bmBase.width;
 
     //////////////////
     // Finish reflowing child frames
     PositionRowChildFrames(dx_left, aDesiredSize.ascent);
   }
 
--- a/layout/mathml/nsMathMLmfencedFrame.cpp
+++ b/layout/mathml/nsMathMLmfencedFrame.cpp
@@ -352,74 +352,94 @@ nsMathMLmfencedFrame::Reflow(nsPresConte
   // adjust the origin of children.
 
   // we need to center around the axis
   nscoord delta = NS_MAX(containerSize.ascent - axisHeight, 
                          containerSize.descent + axisHeight);
   containerSize.ascent = delta + axisHeight;
   containerSize.descent = delta - axisHeight;
 
+  bool isRTL = NS_MATHML_IS_RTL(mPresentationData.flags);
+
   /////////////////
   // opening fence ...
   ReflowChar(aPresContext, *aReflowState.rendContext, mOpenChar,
              NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, 
-             axisHeight, leading, em, containerSize, ascent, descent);
+             axisHeight, leading, em, containerSize, ascent, descent, isRTL);
   /////////////////
   // separators ...
   for (i = 0; i < mSeparatorsCount; i++) {
     ReflowChar(aPresContext, *aReflowState.rendContext, &mSeparatorsChar[i],
                NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel,
-               axisHeight, leading, em, containerSize, ascent, descent);
+               axisHeight, leading, em, containerSize, ascent, descent, isRTL);
   }
   /////////////////
   // closing fence ...
   ReflowChar(aPresContext, *aReflowState.rendContext, mCloseChar,
              NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel,
-             axisHeight, leading, em, containerSize, ascent, descent);
+             axisHeight, leading, em, containerSize, ascent, descent, isRTL);
 
   //////////////////
   // Adjust the origins of each child.
   // and update our bounding metrics
 
   i = 0;
   nscoord dx = 0;
   nsBoundingMetrics bm;
   bool firstTime = true;
-  if (mOpenChar) {
-    PlaceChar(mOpenChar, ascent, bm, dx);
+  nsMathMLChar *leftChar, *rightChar;
+  if (isRTL) {
+    leftChar = mCloseChar;
+    rightChar = mOpenChar;
+  } else {
+    leftChar = mOpenChar;
+    rightChar = mCloseChar;
+  }
+
+  if (leftChar) {
+    PlaceChar(leftChar, ascent, bm, dx);
     aDesiredSize.mBoundingMetrics = bm;
     firstTime = false;
   }
 
-  childFrame = firstChild;
+  if (isRTL) {
+    childFrame = this->GetLastChild(nsIFrame::kPrincipalList);
+  } else {
+    childFrame = firstChild;
+  }
   while (childFrame) {
     nsHTMLReflowMetrics childSize;
     GetReflowAndBoundingMetricsFor(childFrame, childSize, bm);
     if (firstTime) {
       firstTime = false;
       aDesiredSize.mBoundingMetrics  = bm;
     }
     else  
       aDesiredSize.mBoundingMetrics += bm;
 
     FinishReflowChild(childFrame, aPresContext, nsnull, childSize, 
                       dx, ascent - childSize.ascent, 0);
     dx += childSize.width;
 
     if (i < mSeparatorsCount) {
-      PlaceChar(&mSeparatorsChar[i], ascent, bm, dx);
+      PlaceChar(&mSeparatorsChar[isRTL ? mSeparatorsCount - 1 - i : i],
+                ascent, bm, dx);
       aDesiredSize.mBoundingMetrics += bm;
     }
     i++;
 
-    childFrame = childFrame->GetNextSibling();
+    if (isRTL) {
+      childFrame = childFrame->GetPrevSibling();
+    } else {
+      childFrame = childFrame->GetNextSibling();
+    }
   }
 
-  if (mCloseChar) {
-    PlaceChar(mCloseChar, ascent, bm, dx);
+  if (rightChar) {
+    PlaceChar(rightChar, ascent, bm, dx);
     if (firstTime)
       aDesiredSize.mBoundingMetrics  = bm;
     else  
       aDesiredSize.mBoundingMetrics += bm;
   }
 
   aDesiredSize.width = aDesiredSize.mBoundingMetrics.width;
   aDesiredSize.height = ascent + descent;
@@ -475,28 +495,30 @@ nsMathMLmfencedFrame::ReflowChar(nsPresC
                                  nsMathMLChar*        aMathMLChar,
                                  nsOperatorFlags      aForm,
                                  PRInt32              aScriptLevel,
                                  nscoord              axisHeight,
                                  nscoord              leading,
                                  nscoord              em,
                                  nsBoundingMetrics&   aContainerSize,
                                  nscoord&             aAscent,
-                                 nscoord&             aDescent)
+                                 nscoord&             aDescent,
+                                 bool                 aRTL)
 {
   if (aMathMLChar && 0 < aMathMLChar->Length()) {
     nscoord leftSpace;
     nscoord rightSpace;
     GetCharSpacing(aMathMLChar, aForm, aScriptLevel, em, leftSpace, rightSpace);
 
     // stretch the char to the appropriate height if it is not big enough.
     nsBoundingMetrics charSize;
     nsresult res = aMathMLChar->Stretch(aPresContext, aRenderingContext,
                                         NS_STRETCH_DIRECTION_VERTICAL,
-                                        aContainerSize, charSize);
+                                        aContainerSize, charSize,
+                                        NS_STRETCH_NORMAL, aRTL);
 
     if (NS_STRETCH_DIRECTION_UNSUPPORTED != aMathMLChar->GetStretchDirection()) {
       // has changed... so center the char around the axis
       nscoord height = charSize.ascent + charSize.descent;
       charSize.ascent = height/2 + axisHeight;
       charSize.descent = height - charSize.ascent;
     }
     else {
--- a/layout/mathml/nsMathMLmfencedFrame.h
+++ b/layout/mathml/nsMathMLmfencedFrame.h
@@ -100,17 +100,18 @@ public:
              nsMathMLChar*        aMathMLChar,
              nsOperatorFlags      aForm,
              PRInt32              aScriptLevel,
              nscoord              axisHeight,
              nscoord              leading,
              nscoord              em,
              nsBoundingMetrics&   aContainerSize,
              nscoord&             aAscent,
-             nscoord&             aDescent);
+             nscoord&             aDescent,
+             bool                 aRTL);
 
   static void
   PlaceChar(nsMathMLChar*      aMathMLChar,
             nscoord            aDesiredSize,
             nsBoundingMetrics& bm,
             nscoord&           dx);
 
 protected:
--- a/layout/mathml/nsMathMLmfracFrame.cpp
+++ b/layout/mathml/nsMathMLmfracFrame.cpp
@@ -267,18 +267,22 @@ nsMathMLmfracFrame::PlaceInternal(nsRend
   if (!mIsBevelled) {
     mLineRect.height = mLineThickness;
     
     // by default, leave at least one-pixel padding at either end, or use
     // lspace & rspace that may come from <mo> if we are an embellished
     // container (we fetch values from the core since they may use units that
     // depend on style data, and style changes could have occurred in the
     // core since our last visit there)
-    nscoord leftSpace = NS_MAX(onePixel, coreData.leftSpace);
-    nscoord rightSpace = NS_MAX(onePixel, coreData.rightSpace);
+    nscoord leftSpace = NS_MAX(onePixel,
+                               NS_MATHML_IS_RTL(mPresentationData.flags) ?
+                               coreData.trailingSpace : coreData.leadingSpace);
+    nscoord rightSpace = NS_MAX(onePixel,
+                                NS_MATHML_IS_RTL(mPresentationData.flags) ?
+                                coreData.leadingSpace : coreData.trailingSpace);
 
     //////////////////
     // Get shifts
     nscoord numShift = 0;
     nscoord denShift = 0;
 
     // Rule 15b, App. G, TeXbook
     nscoord numShift1, numShift2, numShift3;
@@ -417,18 +421,18 @@ nsMathMLmfracFrame::PlaceInternal(nsRend
     nscoord em = fm->EmHeight();
     nscoord slashMaxWidthConstant = 2 * em;
 
     // For large line thicknesses the minimum slash height is limited to the
     // largest expected height of a fraction
     nscoord slashMinHeight = slashRatio *
       NS_MIN(2 * mLineThickness, slashMaxWidthConstant);
 
-    nscoord leftSpace = NS_MAX(padding, coreData.leftSpace);
-    nscoord rightSpace = NS_MAX(padding, coreData.rightSpace);
+    nscoord leadingSpace = NS_MAX(padding, coreData.leadingSpace);
+    nscoord trailingSpace = NS_MAX(padding, coreData.trailingSpace);
     nscoord delta;
     
     //           ___________
     //          |           |    /
     //         {|-NUMERATOR-|   /
     //         {|___________|  S
     //         {               L
     // numShift{               A
@@ -479,45 +483,58 @@ nsMathMLmfracFrame::PlaceInternal(nsRend
     } else {
       mLineRect.width = mLineThickness +
         NS_MIN(slashMaxWidthConstant,
                (mBoundingMetrics.ascent + mBoundingMetrics.descent) /
                slashRatio);
     }
 
     // Set horizontal bounding metrics
-    mBoundingMetrics.leftBearing = leftSpace + bmNum.leftBearing;
-    mBoundingMetrics.rightBearing =
-      leftSpace + bmNum.width + mLineRect.width + bmDen.rightBearing;
+    if (NS_MATHML_IS_RTL(mPresentationData.flags)) {
+      mBoundingMetrics.leftBearing = trailingSpace + bmDen.leftBearing;
+      mBoundingMetrics.rightBearing = trailingSpace + bmDen.width + mLineRect.width + bmNum.rightBearing;
+    } else {
+      mBoundingMetrics.leftBearing = leadingSpace + bmNum.leftBearing;
+      mBoundingMetrics.rightBearing = leadingSpace + bmNum.width + mLineRect.width + bmDen.rightBearing;
+    }
     mBoundingMetrics.width =
-      leftSpace + bmNum.width + mLineRect.width + bmDen.width + rightSpace;
+      leadingSpace + bmNum.width + mLineRect.width + bmDen.width +
+      trailingSpace;
 
     // Set aDesiredSize
     aDesiredSize.ascent = mBoundingMetrics.ascent + padding;
     aDesiredSize.height =
       mBoundingMetrics.ascent + mBoundingMetrics.descent + 2 * padding;
     aDesiredSize.width = mBoundingMetrics.width;
     aDesiredSize.mBoundingMetrics = mBoundingMetrics;
 
     mReference.x = 0;
     mReference.y = aDesiredSize.ascent;
     
     if (aPlaceOrigin) {
-      FinishReflowChild(frameNum, presContext, nsnull, sizeNum,
-                        leftSpace,
-                        aDesiredSize.ascent - numShift - sizeNum.ascent, 0);
+      nscoord dx, dy;
+
+      // place numerator
+      dx = MirrorIfRTL(aDesiredSize.width, sizeNum.width,
+                       leadingSpace);
+      dy = aDesiredSize.ascent - numShift - sizeNum.ascent;
+      FinishReflowChild(frameNum, presContext, nsnull, sizeNum, dx, dy, 0);
 
-      mLineRect.SetRect(leftSpace + bmNum.width,
-                        aDesiredSize.ascent - mBoundingMetrics.ascent,
-                        mLineRect.width,
-                        aDesiredSize.height - 2 * padding);
+      // place the fraction bar
+      dx = MirrorIfRTL(aDesiredSize.width, mLineRect.width,
+                       leadingSpace + bmNum.width);
+      dy = aDesiredSize.ascent - mBoundingMetrics.ascent;
+      mLineRect.SetRect(dx, dy,
+                        mLineRect.width, aDesiredSize.height - 2 * padding);
 
-      FinishReflowChild(frameDen, presContext, nsnull, sizeDen,
-                        leftSpace + bmNum.width + mLineRect.width,
-                        aDesiredSize.ascent + denShift - sizeDen.ascent, 0);
+      // place denominator
+      dx = MirrorIfRTL(aDesiredSize.width, sizeDen.width,
+                       leadingSpace + bmNum.width + mLineRect.width);
+      dy = aDesiredSize.ascent + denShift - sizeDen.ascent;
+      FinishReflowChild(frameDen, presContext, nsnull, sizeDen, dx, dy, 0);
     }
 
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -544,59 +561,71 @@ nsMathMLmfracFrame::UpdatePresentationDa
     UpdatePresentationDataFromChildAt(aFirstIndex, aLastIndex,
                                       aFlagsValues, aFlagsToUpdate);
 }
 
 class nsDisplayMathMLSlash : public nsDisplayItem {
 public:
   nsDisplayMathMLSlash(nsDisplayListBuilder* aBuilder,
                        nsIFrame* aFrame, const nsRect& aRect,
-                       nscoord aThickness)
-    : nsDisplayItem(aBuilder, aFrame), mRect(aRect), mThickness(aThickness) {
+                       nscoord aThickness, bool aRTL)
+    : nsDisplayItem(aBuilder, aFrame), mRect(aRect), mThickness(aThickness),
+      mRTL(aRTL) {
     MOZ_COUNT_CTOR(nsDisplayMathMLSlash);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayMathMLSlash() {
     MOZ_COUNT_DTOR(nsDisplayMathMLSlash);
   }
 #endif
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
   NS_DISPLAY_DECL_NAME("MathMLSlash", TYPE_MATHML_SLASH)
 
 private:
   nsRect    mRect;
   nscoord   mThickness;
+  bool      mRTL;
 };
 
 void nsDisplayMathMLSlash::Paint(nsDisplayListBuilder* aBuilder,
                                  nsRenderingContext* aCtx)
 {
   // get the gfxRect
   nsPresContext* presContext = mFrame->PresContext();
   gfxRect rect = presContext->AppUnitsToGfxUnits(mRect + ToReferenceFrame());
   
   // paint with the current text color
   aCtx->SetColor(mFrame->GetVisitedDependentColor(eCSSProperty_color));
  
   // draw the slash as a parallelogram 
   gfxContext *gfxCtx = aCtx->ThebesContext();
   gfxPoint delta = gfxPoint(presContext->AppUnitsToGfxUnits(mThickness), 0);
   gfxCtx->NewPath();
-  gfxCtx->MoveTo(rect.BottomLeft());
-  gfxCtx->LineTo(rect.BottomLeft() + delta);
-  gfxCtx->LineTo(rect.TopRight());
-  gfxCtx->LineTo(rect.TopRight() - delta);
+
+  if (mRTL) {
+    gfxCtx->MoveTo(rect.TopLeft());
+    gfxCtx->LineTo(rect.TopLeft() + delta);
+    gfxCtx->LineTo(rect.BottomRight());
+    gfxCtx->LineTo(rect.BottomRight() - delta);
+  } else {
+    gfxCtx->MoveTo(rect.BottomLeft());
+    gfxCtx->LineTo(rect.BottomLeft() + delta);
+    gfxCtx->LineTo(rect.TopRight());
+    gfxCtx->LineTo(rect.TopRight() - delta);
+  }
+
   gfxCtx->ClosePath();
   gfxCtx->Fill();
 }
 
 nsresult
 nsMathMLmfracFrame::DisplaySlash(nsDisplayListBuilder* aBuilder,
                                  nsIFrame* aFrame, const nsRect& aRect,
                                  nscoord aThickness,
                                  const nsDisplayListSet& aLists) {
   if (!aFrame->GetStyleVisibility()->IsVisible() || aRect.IsEmpty())
     return NS_OK;
-  
+
   return aLists.Content()->AppendNewToTop(new (aBuilder)
-      nsDisplayMathMLSlash(aBuilder, aFrame, aRect, aThickness));
+      nsDisplayMathMLSlash(aBuilder, aFrame, aRect, aThickness,
+                           NS_MATHML_IS_RTL(mPresentationData.flags)));
 }
--- a/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
+++ b/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
@@ -412,17 +412,21 @@ nsMathMLmmultiscriptsFrame::Place(nsRend
 
     count = 0;
     childFrame = mprescriptsFrame;
     do {
       if (!childFrame) { // end of prescripts,
         // place the base ...
         childFrame = baseFrame;
         dy = aDesiredSize.ascent - baseSize.ascent;
-        FinishReflowChild (baseFrame, PresContext(), nsnull, baseSize, dx, dy, 0);
+        FinishReflowChild (baseFrame, PresContext(), nsnull, baseSize,
+                           MirrorIfRTL(aDesiredSize.width,
+                                       baseSize.width,
+                                       dx),
+                           dy, 0);
         dx += bmBase.width + italicCorrection;
       }
       else if (mprescriptsFrame != childFrame) {
         // process each sup/sub pair
         if (0 == count) {
           subScriptFrame = childFrame;
           count = 1;
         }
@@ -435,23 +439,31 @@ nsMathMLmmultiscriptsFrame::Place(nsRend
           GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript);
           GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript);
 
           // center w.r.t. largest width
           width = NS_MAX(subScriptSize.width, supScriptSize.width);
 
           dy = aDesiredSize.ascent - subScriptSize.ascent +
             maxSubScriptShift;
-          FinishReflowChild (subScriptFrame, PresContext(), nsnull, subScriptSize,
-                             dx + (width-subScriptSize.width)/2, dy, 0);
+          FinishReflowChild (subScriptFrame, PresContext(), nsnull,
+                             subScriptSize,
+                             MirrorIfRTL(aDesiredSize.width,
+                                         subScriptSize.width,
+                                         dx + (width-subScriptSize.width)/2),
+                             dy, 0);
 
           dy = aDesiredSize.ascent - supScriptSize.ascent -
             maxSupScriptShift;
-          FinishReflowChild (supScriptFrame, PresContext(), nsnull, supScriptSize,
-                             dx + (width-supScriptSize.width)/2, dy, 0);
+          FinishReflowChild (supScriptFrame, PresContext(), nsnull,
+                             supScriptSize,
+                             MirrorIfRTL(aDesiredSize.width,
+                                         supScriptSize.width,
+                                         dx + (width-supScriptSize.width)/2),
+                             dy, 0);
 
           dx += width + scriptSpace;
         }
       }
       childFrame = childFrame->GetNextSibling();
     } while (mprescriptsFrame != childFrame);
   }
 
--- a/layout/mathml/nsMathMLmoFrame.cpp
+++ b/layout/mathml/nsMathMLmoFrame.cpp
@@ -261,18 +261,18 @@ nsMathMLmoFrame::ProcessOperatorData()
   if (!mEmbellishData.coreFrame) {
     // i.e., we haven't been here before, the default form is infix
     form = NS_MATHML_OPERATOR_FORM_INFIX;
 
     // reset everything so that we don't keep outdated values around
     // in case of dynamic changes
     mEmbellishData.flags = 0;
     mEmbellishData.coreFrame = nsnull;
-    mEmbellishData.leftSpace = 0;
-    mEmbellishData.rightSpace = 0;
+    mEmbellishData.leadingSpace = 0;
+    mEmbellishData.trailingSpace = 0;
     if (mMathMLChar.Length() != 1)
       mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;  
     // else... retain the native direction obtained in ProcessTextData()
 
     if (!mFrames.FirstChild()) {
       return;
     }
 
@@ -385,86 +385,86 @@ nsMathMLmoFrame::ProcessOperatorData()
     if (found && (lspace || rspace)) {
       // cache the default values of lspace & rspace that we get from the dictionary.
       // since these values are relative to the 'em' unit, convert to twips now
       nscoord em;
       nsRefPtr<nsFontMetrics> fm;
       nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
       GetEmHeight(fm, em);
 
-      mEmbellishData.leftSpace = NSToCoordRound(lspace * em);
-      mEmbellishData.rightSpace = NSToCoordRound(rspace * em);
+      mEmbellishData.leadingSpace = NSToCoordRound(lspace * em);
+      mEmbellishData.trailingSpace = NSToCoordRound(rspace * em);
 
       // tuning if we don't want too much extra space when we are a script.
       // (with its fonts, TeX sets lspace=0 & rspace=0 as soon as scriptlevel>0.
       // Our fonts can be anything, so...)
       if (GetStyleFont()->mScriptLevel > 0) {
         if (NS_MATHML_OPERATOR_EMBELLISH_IS_ISOLATED(mFlags)) {
           // could be an isolated accent or script, e.g., x^{+}, just zero out
-          mEmbellishData.leftSpace = 0;
-          mEmbellishData.rightSpace  = 0;
+          mEmbellishData.leadingSpace = 0;
+          mEmbellishData.trailingSpace  = 0;
         }
         else if (!NS_MATHML_OPERATOR_HAS_EMBELLISH_ANCESTOR(mFlags)) {
-          mEmbellishData.leftSpace /= 2;
-          mEmbellishData.rightSpace  /= 2;
+          mEmbellishData.leadingSpace /= 2;
+          mEmbellishData.trailingSpace  /= 2;
         }
       }
     }
   }
 
   // If we are an accent without explicit lspace="." or rspace=".",
-  // we will ignore our default left/right space
+  // we will ignore our default leading/trailing space
 
   // lspace = number h-unit | namedspace
-  nscoord leftSpace = mEmbellishData.leftSpace;
+  nscoord leadingSpace = mEmbellishData.leadingSpace;
   GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::lspace_,
                value);
   if (!value.IsEmpty()) {
     nsCSSValue cssValue;
     if (ParseNumericValue(value, cssValue) ||
         ParseNamedSpaceValue(mPresentationData.mstyle, value, cssValue))
     {
       if ((eCSSUnit_Number == cssValue.GetUnit()) && !cssValue.GetFloatValue())
-        leftSpace = 0;
+        leadingSpace = 0;
       else if (cssValue.IsLengthUnit())
-        leftSpace = CalcLength(presContext, mStyleContext, cssValue);
-      mFlags |= NS_MATHML_OPERATOR_LEFTSPACE_ATTR;
+        leadingSpace = CalcLength(presContext, mStyleContext, cssValue);
+      mFlags |= NS_MATHML_OPERATOR_LSPACE_ATTR;
     }
   }
 
   // rspace = number h-unit | namedspace
-  nscoord rightSpace = mEmbellishData.rightSpace;
+  nscoord trailingSpace = mEmbellishData.trailingSpace;
   GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::rspace_,
                value);
   if (!value.IsEmpty()) {
     nsCSSValue cssValue;
     if (ParseNumericValue(value, cssValue) ||
         ParseNamedSpaceValue(mPresentationData.mstyle, value, cssValue))
     {
       if ((eCSSUnit_Number == cssValue.GetUnit()) && !cssValue.GetFloatValue())
-        rightSpace = 0;
+        trailingSpace = 0;
       else if (cssValue.IsLengthUnit())
-        rightSpace = CalcLength(presContext, mStyleContext, cssValue);
-      mFlags |= NS_MATHML_OPERATOR_RIGHTSPACE_ATTR;
+        trailingSpace = CalcLength(presContext, mStyleContext, cssValue);
+      mFlags |= NS_MATHML_OPERATOR_RSPACE_ATTR;
     }
   }
 
   // little extra tuning to round lspace & rspace to at least a pixel so that
   // operators don't look as if they are colliding with their operands
-  if (leftSpace || rightSpace) {
+  if (leadingSpace || trailingSpace) {
     nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
-    if (leftSpace && leftSpace < onePixel)
-      leftSpace = onePixel;
-    if (rightSpace && rightSpace < onePixel)
-      rightSpace = onePixel;
+    if (leadingSpace && leadingSpace < onePixel)
+      leadingSpace = onePixel;
+    if (trailingSpace && trailingSpace < onePixel)
+      trailingSpace = onePixel;
   }
 
   // the values that we get from our attributes override the dictionary
-  mEmbellishData.leftSpace = leftSpace;
-  mEmbellishData.rightSpace = rightSpace;
+  mEmbellishData.leadingSpace = leadingSpace;
+  mEmbellishData.trailingSpace = trailingSpace;
 
   // Now see if there are user-defined attributes that override the dictionary.
   // XXX If an attribute can be forced to be true when it is false in the
   // dictionary, then the following code has to change...
 
   // For each attribute overriden by the user, turn off its bit flag.
   // symmetric|movablelimits|separator|largeop|accent|fence|stretchy|form
   // special: accent and movablelimits are handled above,
@@ -755,17 +755,20 @@ nsMathMLmoFrame::Stretch(nsRenderingCont
           container.descent = aContainerSize.descent;
           container.ascent = height - container.descent;
         }
       }
     }
 
     // let the MathMLChar stretch itself...
     nsresult res = mMathMLChar.Stretch(PresContext(), aRenderingContext,
-                                       aStretchDirection, container, charSize, stretchHint);
+                                       aStretchDirection, container, charSize,
+                                       stretchHint,
+                                       NS_MATHML_IS_RTL(mPresentationData.
+                                                        flags));
     if (NS_FAILED(res)) {
       // gracefully handle cases where stretching the char failed (i.e., GetBoundingMetrics failed)
       // clear our 'form' to behave as if the operator wasn't in the dictionary
       mFlags &= ~NS_MATHML_OPERATOR_FORM;
       useMathMLChar = false;
     }
   }
 
@@ -866,46 +869,49 @@ nsMathMLmoFrame::Stretch(nsRenderingCont
   // Before we leave... there is a last item in the check-list:
   // If our parent is not embellished, it means we are the outermost embellished
   // container and so we put the spacing, otherwise we don't include the spacing,
   // the outermost embellished container will take care of it.
 
   if (!NS_MATHML_OPERATOR_HAS_EMBELLISH_ANCESTOR(mFlags)) {
 
     // Account the spacing if we are not an accent with explicit attributes
-    nscoord leftSpace = mEmbellishData.leftSpace;
-    if (isAccent && !NS_MATHML_OPERATOR_HAS_LEFTSPACE_ATTR(mFlags)) {
-      leftSpace = 0;
+    nscoord leadingSpace = mEmbellishData.leadingSpace;
+    if (isAccent && !NS_MATHML_OPERATOR_HAS_LSPACE_ATTR(mFlags)) {
+      leadingSpace = 0;
     }
-    nscoord rightSpace = mEmbellishData.rightSpace;
-    if (isAccent && !NS_MATHML_OPERATOR_HAS_RIGHTSPACE_ATTR(mFlags)) {
-      rightSpace = 0;
+    nscoord trailingSpace = mEmbellishData.trailingSpace;
+    if (isAccent && !NS_MATHML_OPERATOR_HAS_RSPACE_ATTR(mFlags)) {
+      trailingSpace = 0;
     }
 
-    mBoundingMetrics.width += leftSpace + rightSpace;
+    mBoundingMetrics.width += leadingSpace + trailingSpace;
     aDesiredStretchSize.width = mBoundingMetrics.width;
     aDesiredStretchSize.mBoundingMetrics.width = mBoundingMetrics.width;
 
-    if (leftSpace) {
+    nscoord dx = (NS_MATHML_IS_RTL(mPresentationData.flags) ?
+                  trailingSpace : leadingSpace);
+    if (dx) {
       // adjust the offsets
-      mBoundingMetrics.leftBearing += leftSpace;
-      mBoundingMetrics.rightBearing += leftSpace;
-      aDesiredStretchSize.mBoundingMetrics.leftBearing += leftSpace;
-      aDesiredStretchSize.mBoundingMetrics.rightBearing += leftSpace;
+      mBoundingMetrics.leftBearing += dx;
+      mBoundingMetrics.rightBearing += dx;
+      aDesiredStretchSize.mBoundingMetrics.leftBearing += dx;
+      aDesiredStretchSize.mBoundingMetrics.rightBearing += dx;
 
       if (useMathMLChar) {
         nsRect rect;
         mMathMLChar.GetRect(rect);
-        mMathMLChar.SetRect(nsRect(rect.x + leftSpace, rect.y, rect.width, rect.height));
+        mMathMLChar.SetRect(nsRect(rect.x + dx, rect.y,
+                                   rect.width, rect.height));
       }
       else {
         nsIFrame* childFrame = firstChild;
         while (childFrame) {
-          childFrame->SetPosition(childFrame->GetPosition()
-				  + nsPoint(leftSpace, 0));
+          childFrame->SetPosition(childFrame->GetPosition() +
+                                  nsPoint(dx, 0));
           childFrame = childFrame->GetNextSibling();
         }
       }
     }
   }
 
   // Finished with these:
   ClearSavedChildMetrics();
@@ -1006,20 +1012,20 @@ nsMathMLmoFrame::GetIntrinsicWidth(nsRen
       GetMaxWidth(PresContext(), *aRenderingContext,
                   stretchHint, mMaxSize,
                   NS_MATHML_OPERATOR_MAXSIZE_IS_ABSOLUTE(mFlags));
   }
   else {
     width = nsMathMLTokenFrame::GetIntrinsicWidth(aRenderingContext);
   }
 
-  // leftSpace and rightSpace are actually applied to the outermost
+  // leadingSpace and trailingSpace are actually applied to the outermost
   // embellished container but for determining total intrinsic width it should
   // be safe to include it for the core here instead.
-  width += mEmbellishData.leftSpace + mEmbellishData.rightSpace;
+  width += mEmbellishData.leadingSpace + mEmbellishData.trailingSpace;
 
   return width;
 }
 
 NS_IMETHODIMP
 nsMathMLmoFrame::AttributeChanged(PRInt32         aNameSpaceID,
                                   nsIAtom*        aAttribute,
                                   PRInt32         aModType)
--- a/layout/mathml/nsMathMLmpaddedFrame.cpp
+++ b/layout/mathml/nsMathMLmpaddedFrame.cpp
@@ -128,20 +128,21 @@ nsMathMLmpaddedFrame::ProcessAttributes(
   // depth
   mDepthSign = NS_MATHML_SIGN_INVALID;
   GetAttribute(mContent, nsnull, nsGkAtoms::depth_, value);
   if (!value.IsEmpty()) {
     ParseAttribute(value, mDepthSign, mDepth, mDepthPseudoUnit);
   }
 
   // lspace
-  mLeftSpaceSign = NS_MATHML_SIGN_INVALID;
+  mLeadingSpaceSign = NS_MATHML_SIGN_INVALID;
   GetAttribute(mContent, nsnull, nsGkAtoms::lspace_, value);
   if (!value.IsEmpty()) {
-    ParseAttribute(value, mLeftSpaceSign, mLeftSpace, mLeftSpacePseudoUnit);
+    ParseAttribute(value, mLeadingSpaceSign, mLeadingSpace,
+                   mLeadingSpacePseudoUnit);
   }
 
   // voffset
   mVerticalOffsetSign = NS_MATHML_SIGN_INVALID;
   GetAttribute(mContent, nsnull, nsGkAtoms::voffset_, value);
   if (!value.IsEmpty()) {
     ParseAttribute(value, mVerticalOffsetSign, mVerticalOffset, 
                    mVerticalOffsetPseudoUnit);
@@ -375,40 +376,46 @@ nsMathMLmpaddedFrame::Place(nsRenderingC
     nsMathMLContainerFrame::Place(aRenderingContext, false, aDesiredSize);
   if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
     DidReflowChildren(GetFirstPrincipalChild());
     return rv;
   }
 
   nscoord height = mBoundingMetrics.ascent;
   nscoord depth  = mBoundingMetrics.descent;
-  // In MathML2 (http://www.w3.org/TR/MathML2/chapter3.html#presm.mpadded),
-  // lspace is "the amount of space between the left edge of a bounding box
-  // and the start of the rendering of its contents' bounding box" and the
-  // default is zero.
+  // The REC says:
+  //
+  // "The lspace attribute ('leading' space) specifies the horizontal location
+  // of the positioning point of the child content with respect to the
+  // positioning point of the mpadded element. By default they coincide, and
+  // therefore absolute values for lspace have the same effect as relative
+  // values."
   //
-  // In MathML3 draft
-  // http://www.w3.org/TR/2007/WD-MathML3-20070427/chapter3.html#id.3.3.6.2,
-  // lspace is "the amount of space between the left edge of the bounding box
-  // and the positioning poin [sic] of the mpadded element" and the default is
-  // "same as content".
+  // "MathML renderers should ensure that, except for the effects of the
+  // attributes, the relative spacing between the contents of the mpadded
+  // element and surrounding MathML elements would not be modified by replacing
+  // an mpadded element with an mrow element with the same content, even if
+  // linebreaking occurs within the mpadded element."
   //
-  // In both cases, "MathML renderers should ensure that, except for the
-  // effects of the attributes, relative spacing between the contents of
-  // mpadded and surrounding MathML elements is not modified by replacing an
-  // mpadded element with an mrow element with the same content."
+  // (http://www.w3.org/TR/MathML/chapter3.html#presm.mpadded)
+  // 
+  // "In those discussions, the terms leading and trailing are used to specify
+  // a side of an object when which side to use depends on the directionality;
+  // ie. leading means left in LTR but right in RTL."
+  // (http://www.w3.org/TR/MathML/chapter3.html#presm.bidi.math)
   nscoord lspace = 0;
-  // In MATHML3, "width" will be the bounding box width and "advancewidth" will
+  // In MathML3, "width" will be the bounding box width and "advancewidth" will
   // refer "to the horizontal distance between the positioning point of the
   // mpadded and the positioning point for the following content".  MathML2
   // doesn't make the distinction.
   nscoord width  = mBoundingMetrics.width;
   nscoord voffset = 0;
 
   PRInt32 pseudoUnit;
+  nscoord initialWidth = width;
 
   // update width
   pseudoUnit = (mWidthPseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF)
              ? NS_MATHML_PSEUDO_UNIT_WIDTH : mWidthPseudoUnit;
   UpdateValue(mWidthSign, pseudoUnit, mWidth,
               mBoundingMetrics, width);
   width = NS_MAX(0, width);
 
@@ -422,48 +429,53 @@ nsMathMLmpaddedFrame::Place(nsRenderingC
   // update "depth" (this is the descent in the terminology of the REC)
   pseudoUnit = (mDepthPseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF)
              ? NS_MATHML_PSEUDO_UNIT_DEPTH : mDepthPseudoUnit;
   UpdateValue(mDepthSign, pseudoUnit, mDepth,
               mBoundingMetrics, depth);
   depth = NS_MAX(0, depth);
 
   // update lspace
-  if (mLeftSpacePseudoUnit != NS_MATHML_PSEUDO_UNIT_ITSELF) {
-    pseudoUnit = mLeftSpacePseudoUnit;
-    UpdateValue(mLeftSpaceSign, pseudoUnit, mLeftSpace,
+  if (mLeadingSpacePseudoUnit != NS_MATHML_PSEUDO_UNIT_ITSELF) {
+    pseudoUnit = mLeadingSpacePseudoUnit;
+    UpdateValue(mLeadingSpaceSign, pseudoUnit, mLeadingSpace,
                 mBoundingMetrics, lspace);
   }
 
   // update voffset
   if (mVerticalOffsetPseudoUnit != NS_MATHML_PSEUDO_UNIT_ITSELF) {
     pseudoUnit = mVerticalOffsetPseudoUnit;
     UpdateValue(mVerticalOffsetSign, pseudoUnit, mVerticalOffset,
                 mBoundingMetrics, voffset);
   }
   // do the padding now that we have everything
   // The idea here is to maintain the invariant that <mpadded>...</mpadded> (i.e.,
   // with no attributes) looks the same as <mrow>...</mrow>. But when there are
   // attributes, tweak our metrics and move children to achieve the desired visual
   // effects.
 
-  if (mLeftSpaceSign != NS_MATHML_SIGN_INVALID) { // there was padding on the left
-    // dismiss the left italic correction now (so that our parent won't correct us)
+  if ((NS_MATHML_IS_RTL(mPresentationData.flags) ?
+       mWidthSign : mLeadingSpaceSign) != NS_MATHML_SIGN_INVALID) {
+    // there was padding on the left. dismiss the left italic correction now
+    // (so that our parent won't correct us)
     mBoundingMetrics.leftBearing = 0;
   }
 
-  if (mWidthSign != NS_MATHML_SIGN_INVALID) { // there was padding on the right
-    // dismiss the right italic correction now (so that our parent won't correct us)
+  if ((NS_MATHML_IS_RTL(mPresentationData.flags) ?
+       mLeadingSpaceSign : mWidthSign) != NS_MATHML_SIGN_INVALID) {
+    // there was padding on the right. dismiss the right italic correction now
+    // (so that our parent won't correct us)
     mBoundingMetrics.width = width;
     mBoundingMetrics.rightBearing = mBoundingMetrics.width;
   }
 
   nscoord dy = height - mBoundingMetrics.ascent;
-  nscoord dx = lspace;
-
+  nscoord dx = NS_MATHML_IS_RTL(mPresentationData.flags) ?
+    width - initialWidth - lspace : lspace;
+    
   aDesiredSize.ascent += dy;
   aDesiredSize.width = mBoundingMetrics.width;
   aDesiredSize.height += dy + depth - mBoundingMetrics.descent;
   mBoundingMetrics.ascent = height;
   mBoundingMetrics.descent = depth;
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
 
   mReference.x = 0;
--- a/layout/mathml/nsMathMLmpaddedFrame.h
+++ b/layout/mathml/nsMathMLmpaddedFrame.h
@@ -78,29 +78,29 @@ protected:
   virtual ~nsMathMLmpaddedFrame();
   
   virtual PRIntn GetSkipSides() const { return 0; }
 
 private:
   nsCSSValue mWidth;
   nsCSSValue mHeight;
   nsCSSValue mDepth;
-  nsCSSValue mLeftSpace;
+  nsCSSValue mLeadingSpace;
   nsCSSValue mVerticalOffset;
 
   PRInt32    mWidthSign;
   PRInt32    mHeightSign;
   PRInt32    mDepthSign;
-  PRInt32    mLeftSpaceSign;
+  PRInt32    mLeadingSpaceSign;
   PRInt32    mVerticalOffsetSign;
 
   PRInt32    mWidthPseudoUnit;
   PRInt32    mHeightPseudoUnit;
   PRInt32    mDepthPseudoUnit;
-  PRInt32    mLeftSpacePseudoUnit;
+  PRInt32    mLeadingSpacePseudoUnit;
   PRInt32    mVerticalOffsetPseudoUnit;
 
   // helpers to process the attributes
   void
   ProcessAttributes();
 
   static bool
   ParseAttribute(nsString&   aString,
--- a/layout/mathml/nsMathMLmrootFrame.cpp
+++ b/layout/mathml/nsMathMLmrootFrame.cpp
@@ -306,17 +306,18 @@ nsMathMLmrootFrame::Reflow(nsPresContext
   contSize.descent = bmBase.ascent + bmBase.descent + psi;
   contSize.ascent = ruleThickness;
 
   // height(radical) should be >= height(base) + psi + ruleThickness
   nsBoundingMetrics radicalSize;
   mSqrChar.Stretch(aPresContext, renderingContext,
                    NS_STRETCH_DIRECTION_VERTICAL, 
                    contSize, radicalSize,
-                   NS_STRETCH_LARGER);
+                   NS_STRETCH_LARGER,
+                   NS_MATHML_IS_RTL(mPresentationData.flags));
   // radicalSize have changed at this point, and should match with
   // the bounding metrics of the char
   mSqrChar.GetBoundingMetrics(bmSqr);
 
   // Update the desired size for the container (like msqrt, index is not yet included)
   // the baseline will be that of the base.
   mBoundingMetrics.ascent = bmBase.ascent + psi + ruleThickness;
   mBoundingMetrics.descent = 
@@ -351,45 +352,51 @@ nsMathMLmrootFrame::Reflow(nsPresContext
     nscoord descent = aDesiredSize.height - aDesiredSize.ascent;
     aDesiredSize.ascent = mBoundingMetrics.ascent + leading;
     aDesiredSize.height = aDesiredSize.ascent + descent;
   }
 
   nscoord dxIndex, dxSqr;
   GetRadicalXOffsets(bmIndex.width, bmSqr.width, fm, &dxIndex, &dxSqr);
 
-  // place the index
-  nscoord dx = dxIndex;
-  nscoord dy = aDesiredSize.ascent - (indexRaisedAscent + indexSize.ascent - bmIndex.ascent);
-  FinishReflowChild(indexFrame, aPresContext, nsnull, indexSize, dx, dy, 0);
-
-  // place the radical symbol and the radical bar
-  dx = dxSqr;
-  dy = indexClearance + leading; // leave a leading at the top
-  mSqrChar.SetRect(nsRect(dx, dy, bmSqr.width, bmSqr.ascent + bmSqr.descent));
-  dx += bmSqr.width;
-  mBarRect.SetRect(dx, dy, bmBase.width, ruleThickness);
-
-  // place the base
-  dy = aDesiredSize.ascent - baseSize.ascent;
-  FinishReflowChild(baseFrame, aPresContext, nsnull, baseSize, dx, dy, 0);
-
-  mReference.x = 0;
-  mReference.y = aDesiredSize.ascent;
-
-  mBoundingMetrics.width = dx + bmBase.width;
+  mBoundingMetrics.width = dxSqr + bmSqr.width + bmBase.width;
   mBoundingMetrics.leftBearing = 
     NS_MIN(dxIndex + bmIndex.leftBearing, dxSqr + bmSqr.leftBearing);
-  mBoundingMetrics.rightBearing = dx +
+  mBoundingMetrics.rightBearing = dxSqr + bmSqr.width +
     NS_MAX(bmBase.width, bmBase.rightBearing);
 
   aDesiredSize.width = mBoundingMetrics.width;
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
   GatherAndStoreOverflow(&aDesiredSize);
 
+  // place the index
+  nscoord dx = dxIndex;
+  nscoord dy = aDesiredSize.ascent - (indexRaisedAscent + indexSize.ascent - bmIndex.ascent);
+  FinishReflowChild(indexFrame, aPresContext, nsnull, indexSize,
+                    MirrorIfRTL(aDesiredSize.width, indexSize.width, dx),
+                    dy, 0);
+
+  // place the radical symbol and the radical bar
+  dx = dxSqr;
+  dy = indexClearance + leading; // leave a leading at the top
+  mSqrChar.SetRect(nsRect(MirrorIfRTL(aDesiredSize.width, bmSqr.width, dx),
+                          dy, bmSqr.width, bmSqr.ascent + bmSqr.descent));
+  dx += bmSqr.width;
+  mBarRect.SetRect(MirrorIfRTL(aDesiredSize.width, bmBase.width, dx),
+                   dy, bmBase.width, ruleThickness);
+
+  // place the base
+  dy = aDesiredSize.ascent - baseSize.ascent;
+  FinishReflowChild(baseFrame, aPresContext, nsnull, baseSize,
+                    MirrorIfRTL(aDesiredSize.width, baseSize.width, dx),
+                    dy, 0);
+
+  mReference.x = 0;
+  mReference.y = aDesiredSize.ascent;
+
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 /* virtual */ nscoord
 nsMathMLmrootFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext)
 {
--- a/layout/mathml/nsMathMLmrowFrame.cpp
+++ b/layout/mathml/nsMathMLmrowFrame.cpp
@@ -17,16 +17,17 @@
  * The Initial Developer of the Original Code is
  * The University Of Queensland.
  * Portions created by the Initial Developer are Copyright (C) 1999
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Roger B. Sidje <rbs@maths.uq.edu.au>
  *   David J. Fiddes <D.J.Fiddes@hw.ac.uk>
+ *   Frederic Wang <fred.wang@free.fr>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -64,16 +65,21 @@ nsMathMLmrowFrame::~nsMathMLmrowFrame()
 NS_IMETHODIMP
 nsMathMLmrowFrame::InheritAutomaticData(nsIFrame* aParent)
 {
   // let the base class get the default from our parent
   nsMathMLContainerFrame::InheritAutomaticData(aParent);
 
   mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY;
 
+  if (mContent->Tag() == nsGkAtoms::mrow_) {
+    // see if the directionality attribute is there
+    nsMathMLFrame::FindAttrDirectionality(mContent, mPresentationData);
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLmrowFrame::AttributeChanged(PRInt32  aNameSpaceID,
                                     nsIAtom* aAttribute,
                                     PRInt32  aModType)
 {
--- a/layout/mathml/nsMathMLmstyleFrame.cpp
+++ b/layout/mathml/nsMathMLmstyleFrame.cpp
@@ -17,16 +17,17 @@
  * The Initial Developer of the Original Code is
  * The University Of Queensland.
  * Portions created by the Initial Developer are Copyright (C) 1999
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Roger B. Sidje <rbs@maths.uq.edu.au>
  *   David J. Fiddes <D.J.Fiddes@hw.ac.uk>
+ *   Frederic Wang <fred.wang@free.fr>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -71,16 +72,19 @@ nsMathMLmstyleFrame::InheritAutomaticDat
 
   // sync with our current state
   mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY;
   mPresentationData.mstyle = this;
 
   // see if the displaystyle attribute is there
   nsMathMLFrame::FindAttrDisplaystyle(mContent, mPresentationData);
 
+  // see if the directionality attribute is there
+  nsMathMLFrame::FindAttrDirectionality(mContent, mPresentationData);
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLmstyleFrame::TransmitAutomaticData()
 {
   return TransmitAutomaticDataForMrowLikeElement();
 }
--- a/layout/mathml/nsMathMLmsubFrame.cpp
+++ b/layout/mathml/nsMathMLmsubFrame.cpp
@@ -198,18 +198,20 @@ nsMathMLmsubFrame::PlaceSubScript (nsPre
   aDesiredSize.width = boundingMetrics.width;
   aDesiredSize.mBoundingMetrics = boundingMetrics;
 
   aFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
 
   if (aPlaceOrigin) {
     nscoord dx, dy;
     // now place the base ...
-    dx = 0; dy = aDesiredSize.ascent - baseSize.ascent;
+    dx = aFrame->MirrorIfRTL(aDesiredSize.width, baseSize.width, 0);
+    dy = aDesiredSize.ascent - baseSize.ascent;
     FinishReflowChild (baseFrame, aPresContext, nsnull, baseSize, dx, dy, 0);
     // ... and subscript
-    dx = bmBase.width; 
+    dx = aFrame->MirrorIfRTL(aDesiredSize.width, subScriptSize.width,
+                             bmBase.width);
     dy = aDesiredSize.ascent - (subScriptSize.ascent - actualSubScriptShift);
     FinishReflowChild (subScriptFrame, aPresContext, nsnull, subScriptSize, dx, dy, 0);
   }
 
   return NS_OK;
 }
--- a/layout/mathml/nsMathMLmsubsupFrame.cpp
+++ b/layout/mathml/nsMathMLmsubsupFrame.cpp
@@ -331,25 +331,28 @@ nsMathMLmsubsupFrame::PlaceSubSupScript(
   aDesiredSize.width = boundingMetrics.width;
   aDesiredSize.mBoundingMetrics = boundingMetrics;
 
   aFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
 
   if (aPlaceOrigin) {
     nscoord dx, dy;
     // now place the base ...
-    dx = 0; dy = aDesiredSize.ascent - baseSize.ascent;
+    dx = aFrame->MirrorIfRTL(aDesiredSize.width, baseSize.width, 0);
+    dy = aDesiredSize.ascent - baseSize.ascent;
     FinishReflowChild(baseFrame, aPresContext, nsnull,
                       baseSize, dx, dy, 0);
     // ... and subscript
-    dx = bmBase.width;
+    dx = aFrame->MirrorIfRTL(aDesiredSize.width, subScriptSize.width,
+                             bmBase.width);
     dy = aDesiredSize.ascent - (subScriptSize.ascent - subScriptShift);
     FinishReflowChild(subScriptFrame, aPresContext, nsnull,
                       subScriptSize, dx, dy, 0);
     // ... and the superscript
-    dx = bmBase.width + italicCorrection;
+    dx = aFrame->MirrorIfRTL(aDesiredSize.width, supScriptSize.width,
+                             bmBase.width + italicCorrection);
     dy = aDesiredSize.ascent - (supScriptSize.ascent + supScriptShift);
     FinishReflowChild(supScriptFrame, aPresContext, nsnull,
                       supScriptSize, dx, dy, 0);
   }
 
   return NS_OK;
 }
--- a/layout/mathml/nsMathMLmsupFrame.cpp
+++ b/layout/mathml/nsMathMLmsupFrame.cpp
@@ -236,18 +236,20 @@ nsMathMLmsupFrame::PlaceSuperScript(nsPr
   aDesiredSize.width = boundingMetrics.width;
   aDesiredSize.mBoundingMetrics = boundingMetrics;
 
   aFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
 
   if (aPlaceOrigin) {
     nscoord dx, dy;
     // now place the base ...
-    dx = 0; dy = aDesiredSize.ascent - baseSize.ascent;
+    dx = aFrame->MirrorIfRTL(aDesiredSize.width, baseSize.width, 0);
+    dy = aDesiredSize.ascent - baseSize.ascent;
     FinishReflowChild (baseFrame, aPresContext, nsnull, baseSize, dx, dy, 0);
     // ... and supscript
-    dx = bmBase.width + italicCorrection;
+    dx = aFrame->MirrorIfRTL(aDesiredSize.width, supScriptSize.width,
+                             bmBase.width + italicCorrection);
     dy = aDesiredSize.ascent - (supScriptSize.ascent + actualSupScriptShift);
     FinishReflowChild (supScriptFrame, aPresContext, nsnull, supScriptSize, dx, dy, 0);
   }
 
   return NS_OK;
 }
--- a/layout/printing/nsPrintData.h
+++ b/layout/printing/nsPrintData.h
@@ -29,19 +29,22 @@
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
+
 #ifndef nsPrintData_h___
 #define nsPrintData_h___
 
+#include "mozilla/Attributes.h"
+
 // Interfaces
 #include "nsIDOMWindow.h"
 #include "nsDeviceContext.h"
 #include "nsIPrintProgressParams.h"
 #include "nsIPrintOptions.h"
 #include "nsTArray.h"
 #include "nsCOMArray.h"
 #include "nsAutoPtr.h"
@@ -118,15 +121,15 @@ public:
   float                       mOrigDCScale;
 
   nsCOMPtr<nsIPrintSettings>  mPrintSettings;
   nsPrintPreviewListener*     mPPEventListeners;
 
   PRUnichar*            mBrandName; //  needed as a substitute name for a document
 
 private:
-  nsPrintData(); //not implemented
-  nsPrintData& operator=(const nsPrintData& aOther); // not implemented
+  nsPrintData() MOZ_DELETE;
+  nsPrintData& operator=(const nsPrintData& aOther) MOZ_DELETE;
 
 };
 
 #endif /* nsPrintData_h___ */
 
--- a/layout/printing/nsPrintEngine.h
+++ b/layout/printing/nsPrintEngine.h
@@ -32,16 +32,18 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef nsPrintEngine_h___
 #define nsPrintEngine_h___
 
+#include "mozilla/Attributes.h"
+
 #include "nsCOMPtr.h"
 
 #include "nsPrintObject.h"
 #include "nsPrintData.h"
 #include "nsFrameList.h"
 
 // Interfaces
 #include "nsIDocument.h"
@@ -293,13 +295,12 @@ protected:
   nsPrintData*            mPrtPreview;
   nsPrintData*            mOldPrtPreview;
 
   nsCOMPtr<nsIDocument>   mDocument;
 
   FILE* mDebugFile;
 
 private:
-  nsPrintEngine& operator=(const nsPrintEngine& aOther); // not implemented
-
+  nsPrintEngine& operator=(const nsPrintEngine& aOther) MOZ_DELETE;
 };
 
 #endif /* nsPrintEngine_h___ */
--- a/layout/printing/nsPrintObject.h
+++ b/layout/printing/nsPrintObject.h
@@ -32,16 +32,18 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef nsPrintObject_h___
 #define nsPrintObject_h___
 
+#include "mozilla/Attributes.h"
+
 // Interfaces
 #include "nsCOMPtr.h"
 #include "nsIContent.h"
 #include "nsIPresShell.h"
 #include "nsStyleSet.h"
 #include "nsIViewManager.h"
 #include "nsIDocShell.h"
 #include "nsIDocument.h"
@@ -89,16 +91,15 @@ public:
   bool             mSharedPresShell;
   bool             mInvisible;        // Indicates PO is set to not visible by CSS
   bool             mPrintPreview;
   bool             mDidCreateDocShell;
   float            mShrinkRatio;
   float            mZoomRatio;
 
 private:
-  nsPrintObject& operator=(const nsPrintObject& aOther); // not implemented
-
+  nsPrintObject& operator=(const nsPrintObject& aOther) MOZ_DELETE;
 };
 
 
 
 #endif /* nsPrintObject_h___ */
 
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-1-ref.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+    <p>
+      math:
+      <math>
+        <mspace width="25px" height="25px" mathbackground="blue"/>
+        <mspace width="25px" height="25px" mathbackground="green"/>
+        <mspace width="25px" height="25px" mathbackground="red"/>
+      </math>
+    </p>
+
+    <p>
+      mrow:
+      <math>
+        <mrow>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </mrow>
+      </math>
+    </p>
+
+    <p>
+      mstyle:
+      <math>
+        <mstyle>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </mstyle>
+      </math>
+    </p>
+
+    <p>
+      mpadded lspace="25px" width="150px":
+      <math>
+        <mspace width="1px" height="25px" mathbackground="black"/>
+        <mpadded lspace="50px" width="150px">
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </mpadded>
+        <mspace width="1px" height="25px" mathbackground="black"/>
+      </math>
+    </p>
+
+    <p>
+      mfenced open="A" close="D" separators="BC":
+      <math>
+        <mfenced open="D" close="A" separators="CB">
+          <mtext>c</mtext>
+          <mtext>b</mtext>
+          <mtext>a</mtext>
+        </mfenced>
+      </math>
+    </p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-1.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+    <p>
+      math:
+      <math dir="rtl">
+        <mspace width="25px" height="25px" mathbackground="red"/>
+        <mspace width="25px" height="25px" mathbackground="green"/>
+        <mspace width="25px" height="25px" mathbackground="blue"/>
+      </math>
+    </p>
+
+    <p>
+      mrow:
+      <math>
+        <mrow dir="rtl">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </mrow>
+      </math>
+    </p>
+
+    <p>
+      mstyle:
+      <math>
+        <mstyle dir="rtl">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </mstyle>
+      </math>
+    </p>
+
+    <p>
+      mpadded lspace="25px" width="150px":
+      <math dir="rtl">
+        <mspace width="1px" height="25px" mathbackground="black"/>
+        <mpadded lspace="25px" width="150px">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </mpadded>
+        <mspace width="1px" height="25px" mathbackground="black"/>
+      </math>
+    </p>
+
+    <p>
+      mfenced open="A" close="D" separators="BC":
+      <math dir="rtl">
+        <mfenced open="A" close="D" separators="BC">
+          <mtext>a</mtext>
+          <mtext>b</mtext>
+          <mtext>c</mtext>
+        </mfenced>
+      </math>
+    </p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-2-ref.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+    <p>
+      mfrac (numalign=left):
+      <math>
+        <mfrac numalign="left">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="75px" height="25px" mathbackground="green"/>
+        </mfrac>
+      </math>
+    </p>
+
+    <p>
+      mfrac (numalign=right):
+      <math>
+        <mfrac numalign="right">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="75px" height="25px" mathbackground="green"/>
+        </mfrac>
+      </math>
+    </p>
+
+    <p>
+      menclose:
+      <math>
+        <menclose>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="left":
+      <math>
+        <menclose notation="left">
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="right":
+      <math>
+        <menclose notation="right">
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="updiagonalstrike":
+      <math>
+        <menclose notation="updiagonalstrike">
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="downdiagonalstrike":
+      <math>
+        <menclose notation="downdiagonalstrike">
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </menclose>
+      </math>
+    </p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-2.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+    <p>
+      mfrac (numalign=left):
+      <math dir="rtl">
+        <mfrac numalign="left">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="75px" height="25px" mathbackground="green"/>
+        </mfrac>
+      </math>
+    </p>
+
+    <p>
+      mfrac (numalign=right):
+      <math dir="rtl">
+        <mfrac numalign="right">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="75px" height="25px" mathbackground="green"/>
+        </mfrac>
+      </math>
+    </p>
+
+    <p>
+      menclose:
+      <math dir="rtl">
+        <menclose>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="left":
+      <math dir="rtl">
+        <menclose notation="left">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="right":
+      <math dir="rtl">
+        <menclose notation="right">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="updiagonalstrike":
+      <math dir="rtl">
+        <menclose notation="updiagonalstrike">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="downdiagonalstrike":
+      <math dir="rtl">
+        <menclose notation="downdiagonalstrike">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </menclose>
+      </math>
+    </p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-3-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body style="background: white;">
+
+    <div style="position: absolute; top: 5px; left: 5px;">
+      <div style="width: 30px; height: 500px; background: black;"></div>
+    </div>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-3.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body style="background: white;">
+
+    <!-- The visible part of the formulas below should be covered by the
+         black rectangle when dir=rtl -->
+
+    <div style="position: absolute; top: 5px; left: 5px;">
+      <!-- msup -->
+      <math dir="rtl">
+        <msup>
+          <mspace width="20px" height="20px"/>
+          <mspace width="20px" height="20px" mathbackground="red"/>
+        </msup>
+      </math><br/>
+      <!-- msub -->
+      <math dir="rtl">
+        <msub>
+          <mspace width="20px" height="20px"/>
+          <mspace width="20px" height="20px" mathbackground="orange"/>
+        </msub>
+      </math><br/>
+      <!-- msubsup -->
+      <math dir="rtl">
+        <msubsup>
+          <mspace width="20px" height="20px"/>
+          <mspace width="20px" height="20px" mathbackground="green"/>
+          <mspace width="20px" height="20px" mathbackground="blue"/>
+        </msubsup>
+      </math><br/>
+      <!-- mmultiscripts -->
+      <math dir="rtl">
+        <mmultiscripts>
+          <mspace/>
+          <mspace width="20px" height="20px" mathbackground="cyan"/>
+          <mspace width="20px" height="20px" mathbackground="yellow"/>
+          <mprescripts/>
+          <mspace width="20px" height="20px"/>
+          <mspace width="20px" height="20px"/>
+        </mmultiscripts>
+      </math><br/>
+      <!-- munder (mo with movablelimits=true and displaystyle=false) -->
+      <math dir="rtl">
+        <munder>
+          <mpadded width="20px">
+            <mphantom>
+              <mo movablelimits="true" displaystyle="false">|</mo>
+            </mphantom>
+          </mpadded>
+          <mspace width="20px" height="20px" mathbackground="magenta"/>
+        </munder>
+      </math><br/>
+      <!-- mover (mo with movablelimits=true and displaystyle=false) -->
+      <math dir="rtl">
+        <mover>
+          <mpadded width="20px">
+            <mphantom>
+              <mo movablelimits="true" displaystyle="false">|</mo>
+            </mphantom>
+          </mpadded>
+          <mspace width="20px" height="20px" mathbackground="cyan"/>
+        </mover>
+      </math><br/>
+      <!-- munderover (mo with movablelimits=true and displaystyle=false) -->
+      <math dir="rtl">
+        <munderover>
+          <mpadded width="20px">
+            <mphantom>
+              <mo movablelimits="true" displaystyle="false">|</mo>
+            </mphantom>
+          </mpadded>
+          <mspace width="20px" height="20px" mathbackground="yellow"/>
+          <mspace width="20px" height="20px" mathbackground="grey"/>
+        </munderover>
+      </math>
+      <!-- mfrac (bevelled=true) -->
+      <math dir="rtl">
+        <mstyle mathcolor="white">
+          <mfrac bevelled="true">
+            <mspace width="20px" height="20px"/>
+            <mspace width="20px" height="20px" mathbackground="red"/>
+          </mfrac>
+        </mstyle>
+      </math><br/>
+      <!-- mroot -->
+      <math dir="rtl">
+        <mstyle mathcolor="white">
+          <mroot>
+            <mspace width="20px" height="20px" mathbackground="orange"/>
+            <mspace width="20px" height="20px"/>
+          </mroot>
+        </mstyle>
+      </math>
+      <!-- msqrt -->
+      <math dir="rtl">
+        <mstyle mathcolor="white">
+          <msqrt>
+            <!-- Here, we assume that (width of radical + width of mspace)
+                 is greater than the width of the black rectangle (i.e.
+                 width of radical > 30 - 25 = 5px), so the test fails if the
+                 radical is placed on the left. -->
+            <mspace width="25px" height="20px" mathbackground="grey"/>
+          </msqrt>
+        </mstyle>
+      </math>
+    </div>
+
+    <div style="position: absolute; top: 5px; left: 5px;">
+      <div style="width: 30px; height: 500px; background: black;"></div>
+    </div>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-4-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body style="background: white;">
+
+    <div style="position: absolute;
+                top: 5px; left: 5px; width: 100px; height: 100px;
+                text-align: center; background: black;">
+      <div style="position: absolute;
+                  width: 35px; height: 100px; background: red;"></div>
+      <div style="position: absolute; left: 40px;
+                  width: 20px; height: 100px; background: blue;"></div>
+      <div style="position: absolute; left: 60px; width: 40px; height: 100px;
+                  background: green;"></div>
+    </div>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-4.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body style="background: white;">
+
+    <!-- menclose notation=radical -->
+
+    <div style="position: absolute;
+                top: 5px; left: 5px; width: 100px; height: 100px;
+                text-align: center; background: black;">
+      <math dir="rtl">
+        <mstyle mathcolor="yellow">
+          <!-- left and right notation make the menclose symmetric -->
+          <menclose notation="radical left right">
+            <mspace width="20px" height="20px"/>
+          </menclose>
+        </mstyle>
+      </math>
+    </div>
+
+    <div style="position: absolute;
+                top: 5px; left: 5px; width: 100px; height: 100px;">
+      <!-- hide the left part of the menclose. A 5px band is not covered, where
+           the radical may be seen if it is wrongly placed on the left instead.
+        -->
+      <div style="position: absolute;
+                  width: 35px; height: 100px; background: red;"></div>
+      <!-- hide the middle part of the menclose -->
+      <div style="position: absolute; left: 40px;
+                  width: 20px; height: 100px; background: blue;"></div>
+      <!-- hide the right part of the menclose -->
+      <div style="position: absolute; left: 60px; width: 40px; height: 100px;
+                  background: green;"></div>
+    </div>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-5-ref.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+
+    <div style="position: absolute;
+                top: 5px; left: 5px; width: 200px; height: 200px;">
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 0px; background: red;"></div>
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 40px; background: green;"></div>
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 80px; background: magenta;"></div>
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 120px; background: blue;"></div>
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 160px; background: yellow;"></div>
+    </div>
+
+    <div style="position: absolute;
+                top: 5px; left: 5px; width: 200px; height: 200px;">
+      <div style="position: absolute; width: 10px; height: 200px;
+                  left: -5px; background: black;"></div>
+      <div style="position: absolute; width: 10px; height: 200px;
+                  left: 35px; background: black;"></div>
+      <div style="position: absolute; width: 10px; height: 200px;
+                  left: 75px; background: black;"></div>
+      <div style="position: absolute; width: 10px; height: 200px;
+                  left: 115px; background: black;"></div>
+      <div style="position: absolute; width: 10px; height: 200px;
+                  left: 155px; background: black;"></div>
+      <div style="position: absolute; width: 10px; height: 200px;
+                  left: 195px; background: black;"></div>
+    </div>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-5.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+
+    <!-- mmultiscripts. The formulas
+
+         1 3                 3 1
+          X  in dir=ltr  and  X  in dir=rtl
+         2 4                 4 2
+
+         do not match perfectly, so we use an alternative == reftest here
+         which is less strict. -->
+
+    <!-- five vertical bands: red, green, magenta, blue and yellow -->
+    <div style="position: absolute;
+                top: 5px; left: 5px; width: 200px; height: 200px;">
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 0px; background: red;"></div>
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 40px; background: green;"></div>
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 80px; background: magenta;"></div>
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 120px; background: blue;"></div>
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 160px; background: yellow;"></div>
+    </div>
+
+    <!-- a mmultiscripts element whose children are squares of different
+         colors. In dir=rtl, the color of each square should match the one of
+         the band over which the square is positioned. Hence, this
+         mmultiscripts should not be visible. -->
+    <div style="position: absolute;
+                top: 5px; left: 5px; width: 200px; height: 200px;">
+      <math dir="rtl">
+        <mmultiscripts>
+          <mspace width="40px" height="40px" mathbackground="magenta"/>
+
+          <mspace width="40px" height="40px" mathbackground="green"/>
+          <mspace width="40px" height="40px" mathbackground="green"/>
+
+          <mspace width="40px" height="40px" mathbackground="red"/>
+          <mspace width="40px" height="40px" mathbackground="red"/>
+
+           <mprescripts/>
+
+          <mspace width="40px" height="40px" mathbackground="yellow"/>
+          <mspace width="40px" height="40px" mathbackground="yellow"/>
+
+          <mspace width="40px" height="40px" mathbackground="blue"/>
+          <mspace width="40px" height="40px" mathbackground="blue"/>
+        </mmultiscripts>
+      </math>
+    </div>
+
+    <!-- We add black vertical bands to cover spaces between the children of
+         mmultiscripts. -->
+    <div style="position: absolute;
+                top: 5px; left: 5px; width: 200px; height: 200px;">
+      <div style="position: absolute; width: 10px; height: 200px;
+                  left: -5px; background: black;"></div>
+      <div style="position: absolute; width: 10px; height: 200px;
+                  left: 35px; background: black;"></div>
+      <div style="position: absolute; width: 10px; height: 200px;
+                  left: 75px; background: black;"></div>
+      <div style="position: absolute; width: 10px; height: 200px;
+                  left: 115px; background: black;"></div>
+      <div style="position: absolute; width: 10px; height: 200px;
+                  left: 155px; background: black;"></div>
+      <div style="position: absolute; width: 10px; height: 200px;
+                  left: 195px; background: black;"></div>
+    </div>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-6-ref.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+
+    <p>
+      mtable:
+      <math>
+        <mtable>
+          <mtr>
+            <mtd>
+              <mtext>c</mtext>
+            </mtd>
+            <mtd>
+              <mtext>b</mtext>
+            </mtd>
+            <mtd>
+              <mtext>a</mtext>
+            </mtd>
+          </mtr>
+          <mtr>
+            <mtd>
+              <mtext>f</mtext>
+            </mtd>
+            <mtd>
+              <mtext>e</mtext>
+            </mtd>
+            <mtd>
+              <mtext>d</mtext>
+            </mtd>
+          </mtr>
+        </mtable>
+      </math>
+    </p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-6.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+
+    <p>
+      mtable:
+      <math dir="rtl">
+        <mtable>
+          <mtr>
+            <mtd>
+              <mtext>a</mtext>
+            </mtd>
+            <mtd>
+              <mtext>b</mtext>
+            </mtd>
+            <mtd>
+              <mtext>c</mtext>
+            </mtd>
+          </mtr>
+          <mtr>
+            <mtd>
+              <mtext>d</mtext>
+            </mtd>
+            <mtd>
+              <mtext>e</mtext>
+            </mtd>
+            <mtd>
+              <mtext>f</mtext>
+            </mtd>
+          </mtr>
+        </mtable>
+      </math>
+    </p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-7-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+
+    <p>
+      mo (lspace=1em rspace=2em):
+      <math>
+        <mtext>_</mtext><mo lspace="2em" rspace="1em">+</mo><mtext>_</mtext>
+      </math>
+    </p>
+
+    <p>
+      embellished mrow (lspace=1em rspace=2em):
+      <math>
+        <mtext>_</mtext>
+        <mrow><mo lspace="2em" rspace="1em">+</mo></mrow>
+        <mtext>_</mtext>
+      </math>
+    </p>
+
+    <p>
+      embellished munderover (lspace=1em rspace=2em):
+      <math>
+        <mtext>_</mtext>
+        <munderover>
+          <mo lspace="2em" rspace="1em">+</mo>
+          <mtext>|</mtext>
+          <mtext>|</mtext>
+        </munderover>
+        <mtext>_</mtext>
+      </math>
+    </p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-7.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+
+    <p>
+      mo (lspace=1em rspace=2em):
+      <math dir="rtl">
+        <mtext>_</mtext><mo lspace="1em" rspace="2em">+</mo><mtext>_</mtext>
+      </math>
+    </p>
+
+    <p>
+      embellished mrow (lspace=1em rspace=2em):
+      <math dir="rtl">
+        <mtext>_</mtext>
+        <mrow><mo lspace="1em" rspace="2em">+</mo></mrow>
+        <mtext>_</mtext>
+      </math>
+    </p>
+
+    <p>
+      embellished munderover (lspace=1em rspace=2em):
+      <math dir="rtl">
+        <mtext>_</mtext>
+        <munderover>
+          <mo lspace="1em" rspace="2em">+</mo>
+          <mtext>|</mtext>
+          <mtext>|</mtext>
+        </munderover>
+        <mtext>_</mtext>
+      </math>
+    </p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-8-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+     
+    <p>
+      embellished mfrac (lspace=1em rspace=2em):
+      <math
+        <mtext>_</mtext>
+        <mfrac>
+          <mo lspace="2em" rspace="1em">+</mo>
+          <mtext>|</mtext>
+        </mfrac>
+        <mtext>_</mtext>
+      </math>
+    </p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-8.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+
+    <p>
+      embellished mfrac (lspace=1em rspace=2em):
+      <math dir="rtl">
+        <mtext>_</mtext>
+        <mfrac>
+          <mo lspace="1em" rspace="2em">+</mo>
+          <mtext>|</mtext>
+        </mfrac>
+        <mtext>_</mtext>
+      </math>
+    </p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/mirror-op-1-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test mirror op</title></head>
+  <style type="text/css">
+    mo {
+      -moz-transform: scaleX(-1.0);
+    }
+  </style>
+  <body>
+
+    <p><math><mo>(</mo></math></p>
+    <p><math><mo>)</mo></math></p>
+    <p><math><mo>[</mo></math></p>
+    <p><math><mo>]</mo></math></p>
+    <p><math><mo>{</mo></math></p>
+    <p><math><mo>}</mo></math></p>
+    
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/mirror-op-1.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test mirror op</title></head>
+  <body>
+
+    <p><math dir="rtl"><mo>(</mo></math></p>
+    <p><math dir="rtl"><mo>)</mo></math></p>
+    <p><math dir="rtl"><mo>[</mo></math></p>
+    <p><math dir="rtl"><mo>]</mo></math></p>
+    <p><math dir="rtl"><mo>{</mo></math></p>
+    <p><math dir="rtl"><mo>}</mo></math></p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/mirror-op-2-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test mirror op</title></head>
+  <body>
+
+    <p><math display="block"><mo>&#x2211;</mo></math></p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/mirror-op-2.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test mirror op</title></head>
+  <body>
+
+    <p><math display="block" dir="rtl"><mo>&#x2211;</mo></math></p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/mirror-op-3-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test mirror op</title></head>
+  <body>
+
+    <p><math display="block"><mo>&#x221A;</mo></math></p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/mirror-op-3.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test mirror op</title></head>
+  <body>
+
+    <p><math display="block" dir="rtl"><mo>&#x221A;</mo></math></p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/mirror-op-4-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test mirror op</title></head>
+  <body>
+
+    <p><math display="block"><mo>&#x222B;</mo></math></p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/mirror-op-4.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test mirror op</title></head>
+  <body>
+
+    <p><math display="block" dir="rtl"><mo>&#x222B;</mo></math></p>
+
+  </body>
+</html>
--- a/layout/reftests/mathml/reftest.list
+++ b/layout/reftests/mathml/reftest.list
@@ -1,8 +1,20 @@
+== dir-1.html dir-1-ref.html
+== dir-2.html dir-2-ref.html
+== dir-3.html dir-3-ref.html
+== dir-4.html dir-4-ref.html
+== dir-5.html dir-5-ref.html
+fails == dir-6.html dir-6-ref.html
+== dir-7.html dir-7-ref.html
+fails == dir-8.html dir-8-ref.html
+== mirror-op-1.html mirror-op-1-ref.html
+!= mirror-op-2.html mirror-op-2-ref.html
+!= mirror-op-3.html mirror-op-3-ref.html
+!= mirror-op-4.html mirror-op-4-ref.html
 == dynamic-mi.xhtml dynamic-mi-ref.xhtml
 == mfenced-1.xhtml mfenced-1-ref.xhtml
 == mfenced-2a.xhtml mfenced-2-ref.xhtml
 == mfenced-2b.xhtml mfenced-2-ref.xhtml
 == mfenced-3a.xhtml mfenced-3-ref.xhtml
 == mfenced-3b.xhtml mfenced-3-ref.xhtml
 == mfenced-3c.xhtml mfenced-3-ref.xhtml
 == mfenced-3d.xhtml mfenced-3-ref.xhtml
--- a/layout/style/Declaration.h
+++ b/layout/style/Declaration.h
@@ -39,16 +39,18 @@
 /*
  * representation of a declaration block (or style attribute) in a CSS
  * stylesheet
  */
 
 #ifndef mozilla_css_Declaration_h
 #define mozilla_css_Declaration_h
 
+#include "mozilla/Attributes.h"
+
 // This header is in EXPORTS because it's used in several places in content/,
 // but it's not really a public interface.
 #ifndef _IMPL_NS_LAYOUT
 #error "This file should only be included within the layout library"
 #endif
 
 #include "nsCSSDataBlock.h"
 #include "nsCSSProperty.h"
@@ -234,19 +236,18 @@ public:
     mOrder.Clear();
   }
 
 #ifdef DEBUG
   void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
 #endif
 
 private:
-  // Not implemented, and not supported.
-  Declaration& operator=(const Declaration& aCopy);
-  bool operator==(const Declaration& aCopy) const;
+  Declaration& operator=(const Declaration& aCopy) MOZ_DELETE;
+  bool operator==(const Declaration& aCopy) const MOZ_DELETE;
 
   static void AppendImportanceToString(bool aIsImportant, nsAString& aString);
   // return whether there was a value in |aValue| (i.e., it had a non-null unit)
   bool AppendValueToString(nsCSSProperty aProperty, nsAString& aResult) const;
   // Helper for ToString with strange semantics regarding aValue.
   void AppendPropertyAndValueToString(nsCSSProperty aProperty,
                                       nsAutoString& aValue,
                                       nsAString& aResult) const;
--- a/layout/style/NameSpaceRule.h
+++ b/layout/style/NameSpaceRule.h
@@ -35,31 +35,33 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* class for CSS @namespace rules */
 
 #ifndef mozilla_css_NameSpaceRule_h__
 #define mozilla_css_NameSpaceRule_h__
 
+#include "mozilla/Attributes.h"
 #include "mozilla/css/Rule.h"
+
 #include "nsIDOMCSSRule.h"
 
 class nsIAtom;
 
 // IID for the NameSpaceRule class {f0b0dbe1-5031-4a21-b06a-dc141ef2af98}
 #define NS_CSS_NAMESPACE_RULE_IMPL_CID     \
 {0xf0b0dbe1, 0x5031, 0x4a21, {0xb0, 0x6a, 0xdc, 0x14, 0x1e, 0xf2, 0xaf, 0x98}}
 
 
 namespace mozilla {
 namespace css {
 
-class NameSpaceRule : public Rule,
-                      public nsIDOMCSSRule
+class NameSpaceRule MOZ_FINAL : public Rule,
+                                public nsIDOMCSSRule
 {
 public:
   NameSpaceRule(nsIAtom* aPrefix, const nsString& aURLSpec);
 private:
   // for |Clone|
   NameSpaceRule(const NameSpaceRule& aCopy);
   ~NameSpaceRule();
 public:
--- a/layout/style/StyleRule.h
+++ b/layout/style/StyleRule.h
@@ -40,18 +40,21 @@
 /*
  * representation of CSS style rules (selectors+declaration) and CSS
  * selectors
  */
 
 #ifndef mozilla_css_StyleRule_h__
 #define mozilla_css_StyleRule_h__
 
-//#include <stdio.h>
+#include "mozilla/Attributes.h"
+
+#include "mozilla/Attributes.h"
 #include "mozilla/css/Rule.h"
+
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsCSSPseudoElements.h"
 #include "nsCSSPseudoClasses.h"
 #include "nsAutoPtr.h"
 
 class nsIAtom;
 class nsCSSStyleSheet;
@@ -67,19 +70,18 @@ public:
   /** Do a deep clone.  Should be used only on the first in the linked list. */
   nsAtomList* Clone() const { return Clone(true); }
 
   nsCOMPtr<nsIAtom> mAtom;
   nsAtomList*       mNext;
 private: 
   nsAtomList* Clone(bool aDeep) const;
 
-  // These are not supported and are not implemented! 
-  nsAtomList(const nsAtomList& aCopy);
-  nsAtomList& operator=(const nsAtomList& aCopy); 
+  nsAtomList(const nsAtomList& aCopy) MOZ_DELETE;
+  nsAtomList& operator=(const nsAtomList& aCopy) MOZ_DELETE;
 };
 
 struct nsPseudoClassList {
 public:
   nsPseudoClassList(nsCSSPseudoClasses::Type aType);
   nsPseudoClassList(nsCSSPseudoClasses::Type aType, const PRUnichar *aString);
   nsPseudoClassList(nsCSSPseudoClasses::Type aType, const PRInt32 *aIntPair);
   nsPseudoClassList(nsCSSPseudoClasses::Type aType,
@@ -104,19 +106,18 @@ public:
     PRInt32*        mNumbers;
     nsCSSSelectorList* mSelectors;
   } u;
   nsCSSPseudoClasses::Type mType;
   nsPseudoClassList* mNext;
 private: 
   nsPseudoClassList* Clone(bool aDeep) const;
 
-  // These are not supported and are not implemented! 
-  nsPseudoClassList(const nsPseudoClassList& aCopy);
-  nsPseudoClassList& operator=(const nsPseudoClassList& aCopy); 
+  nsPseudoClassList(const nsPseudoClassList& aCopy) MOZ_DELETE;
+  nsPseudoClassList& operator=(const nsPseudoClassList& aCopy) MOZ_DELETE;
 };
 
 #define NS_ATTR_FUNC_SET        0     // [attr]
 #define NS_ATTR_FUNC_EQUALS     1     // [attr=value]
 #define NS_ATTR_FUNC_INCLUDES   2     // [attr~=value] (space separated)
 #define NS_ATTR_FUNC_DASHMATCH  3     // [attr|=value] ('-' truncated)
 #define NS_ATTR_FUNC_BEGINSMATCH  4   // [attr^=value] (begins with)
 #define NS_ATTR_FUNC_ENDSMATCH  5     // [attr$=value] (ends with)
@@ -141,19 +142,18 @@ public:
   nsCOMPtr<nsIAtom> mCasedAttr;
   PRInt32         mNameSpace;
   PRUint8         mFunction;
   bool            mCaseSensitive; // If we are in an HTML document,
                                   // is the value case sensitive?
 private: 
   nsAttrSelector* Clone(bool aDeep) const;
 
-  // These are not supported and are not implemented! 
-  nsAttrSelector(const nsAttrSelector& aCopy);
-  nsAttrSelector& operator=(const nsAttrSelector& aCopy); 
+  nsAttrSelector(const nsAttrSelector& aCopy) MOZ_DELETE;
+  nsAttrSelector& operator=(const nsAttrSelector& aCopy) MOZ_DELETE;
 };
 
 struct nsCSSSelector {
 public:
   nsCSSSelector(void);
   ~nsCSSSelector(void);
 
   /** Do a deep clone.  Should be used only on the first in the linked list. */
@@ -230,19 +230,19 @@ public:
   nsAttrSelector* mAttrList;
   nsCSSSelector*  mNegations;
   nsCSSSelector*  mNext;
   PRInt32         mNameSpace;
   PRUnichar       mOperator;
 private:
   // PRInt16 to make sure it packs well with mOperator
   PRInt16        mPseudoType;
-  // These are not supported and are not implemented! 
-  nsCSSSelector(const nsCSSSelector& aCopy);
-  nsCSSSelector& operator=(const nsCSSSelector& aCopy); 
+
+  nsCSSSelector(const nsCSSSelector& aCopy) MOZ_DELETE;
+  nsCSSSelector& operator=(const nsCSSSelector& aCopy) MOZ_DELETE;
 };
 
 /**
  * A selector list is the unit of selectors that each style rule has.
  * For example, "P B, H1 B { ... }" would be a selector list with two
  * items (where each |nsCSSSelectorList| object's |mSelectors| has
  * an |mNext| for the P or H1).  We represent them as linked lists.
  */
@@ -272,19 +272,18 @@ struct nsCSSSelectorList {
   nsCSSSelectorList* Clone() const { return Clone(true); }
 
   nsCSSSelector*     mSelectors;
   PRInt32            mWeight;
   nsCSSSelectorList* mNext;
 private: 
   nsCSSSelectorList* Clone(bool aDeep) const;
 
-  // These are not supported and are not implemented! 
-  nsCSSSelectorList(const nsCSSSelectorList& aCopy);
-  nsCSSSelectorList& operator=(const nsCSSSelectorList& aCopy); 
+  nsCSSSelectorList(const nsCSSSelectorList& aCopy) MOZ_DELETE;
+  nsCSSSelectorList& operator=(const nsCSSSelectorList& aCopy) MOZ_DELETE;
 };
 
 // 464bab7a-2fce-4f30-ab44-b7a5f3aae57d
 #define NS_CSS_STYLE_RULE_IMPL_CID \
 { 0x464bab7a, 0x2fce, 0x4f30, \
   { 0xab, 0x44, 0xb7, 0xa5, 0xf3, 0xaa, 0xe5, 0x7d } }
 
 namespace mozilla {
@@ -313,17 +312,17 @@ protected:
   // Not an owning reference; the StyleRule that owns this
   // ImportantRule also owns the mDeclaration, and any rule node
   // pointing to this rule keeps that StyleRule alive as well.
   Declaration* mDeclaration;
 
   friend class StyleRule;
 };
 
-class StyleRule : public Rule
+class StyleRule MOZ_FINAL : public Rule
 {
  public:
   StyleRule(nsCSSSelectorList* aSelector,
             Declaration *aDeclaration);
 private:
   // for |Clone|
   StyleRule(const StyleRule& aCopy);
   // for |DeclarationChanged|
@@ -377,30 +376,29 @@ public:
   // The new mapping function.
   virtual void MapRuleInfoInto(nsRuleData* aRuleData);
 
 #ifdef DEBUG
   virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
 #endif
 
 private:
-  // This is not supported and not implemented!
-  StyleRule& operator=(const StyleRule& aCopy);
-
-private:
   ~StyleRule();
 
 private:
   nsCSSSelectorList*      mSelector; // null for style attribute
   Declaration*            mDeclaration;
   ImportantRule*          mImportantRule; // initialized by RuleMatched
   DOMCSSStyleRule*        mDOMRule;
   // Keep the same type so that MSVC packs them.
   PRUint32                mLineNumber : 31;
   PRUint32                mWasMatched : 1;
+
+private:
+  StyleRule& operator=(const StyleRule& aCopy) MOZ_DELETE;
 };
 
 } // namespace css
 } // namespace mozilla
 
 NS_DEFINE_STATIC_IID_ACCESSOR(mozilla::css::StyleRule, NS_CSS_STYLE_RULE_IMPL_CID)
 
 #endif /* mozilla_css_StyleRule_h__ */
--- a/layout/style/nsCSSParser.h
+++ b/layout/style/nsCSSParser.h
@@ -35,16 +35,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* parsing of CSS stylesheets, based on a token stream from the CSS scanner */
 
 #ifndef nsCSSParser_h___
 #define nsCSSParser_h___
 
+#include "mozilla/Attributes.h"
+
 #include "nsAString.h"
 #include "nsCSSProperty.h"
 #include "nsColor.h"
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 
 class nsCSSStyleSheet;
@@ -69,19 +71,18 @@ class NS_STACK_CLASS nsCSSParser {
 public:
   nsCSSParser(mozilla::css::Loader* aLoader = nsnull,
               nsCSSStyleSheet* aSheet = nsnull);
   ~nsCSSParser();
 
   static void Shutdown();
 
 private:
-  // not to be implemented
-  nsCSSParser(nsCSSParser const&);
-  nsCSSParser& operator=(nsCSSParser const&);
+  nsCSSParser(nsCSSParser const&) MOZ_DELETE;
+  nsCSSParser& operator=(nsCSSParser const&) MOZ_DELETE;
 
 public:
   // Set a style sheet for the parser to fill in. The style sheet must
   // implement the nsCSSStyleSheet interface.  Null can be passed in to clear
   // out an existing stylesheet reference.
   nsresult SetStyleSheet(nsCSSStyleSheet* aSheet);
 
   // Set whether or not to emulate Nav quirks
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -33,16 +33,18 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* rules in a CSS stylesheet other than style rules (e.g., @import rules) */
 
+#include "mozilla/Attributes.h"
+
 #include "nsCSSRules.h"
 #include "nsCSSValue.h"
 #include "mozilla/css/ImportRule.h"
 #include "mozilla/css/NameSpaceRule.h"
 
 #include "nsString.h"
 #include "nsIAtom.h"
 #include "nsIURL.h"
@@ -115,17 +117,17 @@ Rule::GetParentStyleSheet(nsIDOMCSSStyle
   return NS_OK;
 }
 
 
 // -------------------------------
 // Style Rule List for group rules
 //
 
-class GroupRuleRuleList : public nsICSSRuleList
+class GroupRuleRuleList MOZ_FINAL : public nsICSSRuleList
 {
 public:
   GroupRuleRuleList(GroupRule *aGroupRule);
 
   NS_DECL_ISUPPORTS
 
   NS_DECL_NSIDOMCSSRULELIST
 
--- a/layout/style/nsCSSRules.h
+++ b/layout/style/nsCSSRules.h
@@ -67,18 +67,18 @@ class StyleRule;
 }
 }
 
 class nsMediaList;
 
 namespace mozilla {
 namespace css {
 
-class MediaRule : public GroupRule,
-                  public nsIDOMCSSMediaRule
+class MediaRule MOZ_FINAL : public GroupRule,
+                            public nsIDOMCSSMediaRule
 {
 public:
   MediaRule();
 private:
   MediaRule(const MediaRule& aCopy);
   ~MediaRule();
 public:
 
@@ -110,18 +110,18 @@ public:
 
   // @media rule methods
   nsresult SetMedia(nsMediaList* aMedia);
   
 protected:
   nsRefPtr<nsMediaList> mMedia;
 };
 
-class DocumentRule : public GroupRule,
-                     public nsIDOMCSSMozDocumentRule
+class DocumentRule MOZ_FINAL : public GroupRule,
+                               public nsIDOMCSSMozDocumentRule
 {
 public:
   DocumentRule();
 private:
   DocumentRule(const DocumentRule& aCopy);
   ~DocumentRule();
 public:
 
@@ -310,17 +310,17 @@ private:
   nsString  mEncoding;
 };
 
 } // namespace css
 } // namespace mozilla
 
 class nsCSSKeyframeRule;
 
-class nsCSSKeyframeStyleDeclaration : public nsDOMCSSDeclaration
+class nsCSSKeyframeStyleDeclaration MOZ_FINAL : public nsDOMCSSDeclaration
 {
 public:
   nsCSSKeyframeStyleDeclaration(nsCSSKeyframeRule *aRule);
   virtual ~nsCSSKeyframeStyleDeclaration();
 
   NS_IMETHOD GetParentRule(nsIDOMCSSRule **aParent);
   void DropReference() { mRule = nsnull; }
   virtual mozilla::css::Declaration* GetCSSDeclaration(bool aAllocate);
@@ -385,18 +385,18 @@ public:
 
 private:
   nsAutoTArray<float, 1>                     mKeys;
   nsAutoPtr<mozilla::css::Declaration>       mDeclaration;
   // lazily created when needed:
   nsRefPtr<nsCSSKeyframeStyleDeclaration>    mDOMDeclaration;
 };
 
-class nsCSSKeyframesRule : public mozilla::css::GroupRule,
-                           public nsIDOMMozCSSKeyframesRule
+class nsCSSKeyframesRule MOZ_FINAL : public mozilla::css::GroupRule,
+                                     public nsIDOMMozCSSKeyframesRule
 {
 public:
   nsCSSKeyframesRule(const nsSubstring& aName)
     : mName(aName)
   {
   }
 private:
   nsCSSKeyframesRule(const nsCSSKeyframesRule& aCopy);
--- a/layout/style/nsCSSScanner.cpp
+++ b/layout/style/nsCSSScanner.cpp
@@ -419,31 +419,30 @@ nsCSSScanner::OutputError()
         if (doc) {
           mInnerWindowID = doc->InnerWindowID();
         }
       }
       mWindowIDCached = true;
     }
 
     nsresult rv;
-    nsCOMPtr<nsIScriptError2> errorObject =
+    nsCOMPtr<nsIScriptError> errorObject =
       do_CreateInstance(gScriptErrorFactory, &rv);
 
     if (NS_SUCCEEDED(rv)) {
       rv = errorObject->InitWithWindowID(mError.get(),
                                          NS_ConvertUTF8toUTF16(mFileName).get(),
                                          EmptyString().get(),
                                          mErrorLineNumber,
                                          mErrorColNumber,
                                          nsIScriptError::warningFlag,
                                          "CSS Parser",
                                          mInnerWindowID);
       if (NS_SUCCEEDED(rv)) {
-        nsCOMPtr<nsIScriptError> logError = do_QueryInterface(errorObject);
-        gConsoleService->LogMessage(logError);
+        gConsoleService->LogMessage(errorObject);
       }
     }
   }
   ClearError();
 }
 
 static bool
 InitStringBundle()
--- a/layout/style/nsCSSStyleSheet.h
+++ b/layout/style/nsCSSStyleSheet.h
@@ -129,19 +129,19 @@ struct ChildSheetListBuilder;
 
 // CID for the nsCSSStyleSheet class
 // ca926f30-2a7e-477e-8467-803fb32af20a
 #define NS_CSS_STYLE_SHEET_IMPL_CID     \
 { 0xca926f30, 0x2a7e, 0x477e, \
  { 0x84, 0x67, 0x80, 0x3f, 0xb3, 0x2a, 0xf2, 0x0a } }
 
 
-class nsCSSStyleSheet : public nsIStyleSheet,
-                        public nsIDOMCSSStyleSheet,
-                        public nsICSSLoaderObserver
+class nsCSSStyleSheet MOZ_FINAL : public nsIStyleSheet,
+                                  public nsIDOMCSSStyleSheet,
+                                  public nsICSSLoaderObserver
 {
 public:
   nsCSSStyleSheet();
 
   NS_DECL_ISUPPORTS
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_CSS_STYLE_SHEET_IMPL_CID)
 
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -35,16 +35,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* representation of simple property values within CSS declarations */
 
 #ifndef nsCSSValue_h___
 #define nsCSSValue_h___
 
+#include "mozilla/Attributes.h"
+
 #include "nsCOMPtr.h"
 #include "nsCRTGlue.h"
 #include "nsCSSKeywords.h"
 #include "nsCSSProperty.h"
 #include "nsColor.h"
 #include "nsCoord.h"
 #include "nsString.h"
 #include "nsStringBuffer.h"
@@ -490,19 +492,18 @@ public:
     nsCOMPtr<nsIURI> mReferrer;
     nsCOMPtr<nsIPrincipal> mOriginPrincipal;
 
     NS_INLINE_DECL_REFCOUNTING(nsCSSValue::URL)
 
   private:
     mutable bool mURIResolved;
 
-    // not to be implemented
-    URL(const URL& aOther);
-    URL& operator=(const URL& aOther);
+    URL(const URL& aOther) MOZ_DELETE;
+    URL& operator=(const URL& aOther) MOZ_DELETE;
   };
 
   struct Image : public URL {
     // Not making the constructor and destructor inline because that would
     // force us to include imgIRequest.h, which leads to REQUIRES hell, since
     // this header is included all over.
     // aString must not be null.
     Image(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aReferrer,
@@ -639,19 +640,18 @@ private:
     CSSVALUE_LIST_FOR_EXTRA_VALUES(val) {
       val->~nsCSSValue();
     }
   }
 
 #undef CSSVALUE_LIST_FOR_EXTRA_VALUES
 
 private:
-  // not to be implemented
-  Array(const Array& aOther);
-  Array& operator=(const Array& aOther);
+  Array(const Array& aOther) MOZ_DELETE;
+  Array& operator=(const Array& aOther) MOZ_DELETE;
 };
 
 // Prefer nsCSSValue::Array for lists of fixed size.
 struct nsCSSValueList {
   nsCSSValueList() : mNext(nsnull) { MOZ_COUNT_CTOR(nsCSSValueList); }
   ~nsCSSValueList();
 
   nsCSSValueList* Clone() const;  // makes a deep copy
@@ -1068,19 +1068,18 @@ struct nsCSSValueGradient {
   bool operator!=(const nsCSSValueGradient& aOther) const
   {
     return !(*this == aOther);
   }
 
   NS_INLINE_DECL_REFCOUNTING(nsCSSValueGradient)
 
 private:
-  // not to be implemented
-  nsCSSValueGradient(const nsCSSValueGradient& aOther);
-  nsCSSValueGradient& operator=(const nsCSSValueGradient& aOther);
+  nsCSSValueGradient(const nsCSSValueGradient& aOther) MOZ_DELETE;
+  nsCSSValueGradient& operator=(const nsCSSValueGradient& aOther) MOZ_DELETE;
 };
 
 struct nsCSSCornerSizes {
   nsCSSCornerSizes(void);
   nsCSSCornerSizes(const nsCSSCornerSizes& aCopy);
   ~nsCSSCornerSizes();
 
   // argument is a "full corner" constant from nsStyleConsts.h
--- a/layout/style/nsFontFaceLoader.cpp
+++ b/layout/style/nsFontFaceLoader.cpp
@@ -792,29 +792,26 @@ nsUserFontSet::LogMessage(gfxProxyFontEn
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIDOMCSSStyleSheet> sheet;
     rv = rule->GetParentStyleSheet(getter_AddRefs(sheet));
     NS_ENSURE_SUCCESS(rv, rv);
     rv = sheet->GetHref(href);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  nsCOMPtr<nsIScriptError2> scriptError =
+  nsCOMPtr<nsIScriptError> scriptError =
     do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRUint64 innerWindowID = GetPresContext()->Document()->InnerWindowID();
   rv = scriptError->InitWithWindowID(NS_ConvertUTF8toUTF16(msg).get(),
                                      href.get(),   // file
                                      text.get(),   // src line
                                      0, 0,         // line & column number
                                      aFlags,       // flags
                                      "CSS Loader", // category (make separate?)
                                      innerWindowID);
-  if (NS_SUCCEEDED(rv)){
-    nsCOMPtr<nsIScriptError> logError = do_QueryInterface(scriptError);
-    if (logError) {
-      console->LogMessage(logError);
-    }
+  if (NS_SUCCEEDED(rv)) {
+    console->LogMessage(scriptError);
   }
 
   return NS_OK;
 }
--- a/layout/style/nsHTMLCSSStyleSheet.h
+++ b/layout/style/nsHTMLCSSStyleSheet.h
@@ -37,16 +37,18 @@
 
 /*
  * style sheet and style rule processor representing style attributes
  */
 
 #ifndef nsHTMLCSSStyleSheet_h_
 #define nsHTMLCSSStyleSheet_h_
 
+#include "mozilla/Attributes.h"
+
 #include "nsIStyleSheet.h"
 #include "nsIStyleRuleProcessor.h"
 
 class nsHTMLCSSStyleSheet : public nsIStyleSheet,
                             public nsIStyleRuleProcessor {
 public:
   nsHTMLCSSStyleSheet();
 
@@ -85,18 +87,17 @@ public:
     HasAttributeDependentStyle(AttributeRuleProcessorData* aData);
   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext);
   virtual NS_MUST_OVERRIDE size_t
     SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE;
   virtual NS_MUST_OVERRIDE size_t
     SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE;
 
 private: 
-  // These are not supported and are not implemented! 
-  nsHTMLCSSStyleSheet(const nsHTMLCSSStyleSheet& aCopy); 
-  nsHTMLCSSStyleSheet& operator=(const nsHTMLCSSStyleSheet& aCopy); 
+  nsHTMLCSSStyleSheet(const nsHTMLCSSStyleSheet& aCopy) MOZ_DELETE;
+  nsHTMLCSSStyleSheet& operator=(const nsHTMLCSSStyleSheet& aCopy) MOZ_DELETE;
 
 protected:
   nsCOMPtr<nsIURI> mURL;
   nsIDocument*     mDocument;
 };
 
 #endif /* !defined(nsHTMLCSSStyleSheet_h_) */
--- a/layout/style/nsHTMLStyleSheet.h
+++ b/layout/style/nsHTMLStyleSheet.h
@@ -40,16 +40,18 @@
 /*
  * style sheet and style rule processor representing data from presentational
  * HTML attributes
  */
 
 #ifndef nsHTMLStyleSheet_h_
 #define nsHTMLStyleSheet_h_
 
+#include "mozilla/Attributes.h"
+
 #include "nsIStyleSheet.h"
 #include "nsIStyleRuleProcessor.h"
 #include "nsIStyleRule.h"
 #include "pldhash.h"
 #include "nsCOMPtr.h"
 #include "nsColor.h"
 class nsMappedAttributes;
 
@@ -102,19 +104,18 @@ public:
 
   // Mapped Attribute management methods
   already_AddRefed<nsMappedAttributes>
     UniqueMappedAttributes(nsMappedAttributes* aMapped);
   void DropMappedAttributes(nsMappedAttributes* aMapped);
 
   PRInt64 DOMSizeOf() const;
 private: 
-  // These are not supported and are not implemented! 
-  nsHTMLStyleSheet(const nsHTMLStyleSheet& aCopy); 
-  nsHTMLStyleSheet& operator=(const nsHTMLStyleSheet& aCopy); 
+  nsHTMLStyleSheet(const nsHTMLStyleSheet& aCopy) MOZ_DELETE;
+  nsHTMLStyleSheet& operator=(const nsHTMLStyleSheet& aCopy) MOZ_DELETE;
 
   ~nsHTMLStyleSheet();
 
   class HTMLColorRule;
   friend class HTMLColorRule;
   class HTMLColorRule : public nsIStyleRule {
   public:
     HTMLColorRule() {}
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -7130,42 +7130,44 @@ nsRuleNode::HasAuthorSpecifiedRules(nsSt
     eCSSProperty_padding_left_value,
     eCSSProperty_padding_start_value,
     eCSSProperty_padding_end_value,
   };
 
   // Number of properties we care about
   size_t nValues = 0;
 
-  size_t backColorIndex = size_t(-1);
-
   nsCSSValue* values[NS_ARRAY_LENGTH(backgroundValues) +
                      NS_ARRAY_LENGTH(borderValues) +
                      NS_ARRAY_LENGTH(paddingValues)];
 
+  nsCSSProperty properties[NS_ARRAY_LENGTH(backgroundValues) +
+                           NS_ARRAY_LENGTH(borderValues) +
+                           NS_ARRAY_LENGTH(paddingValues)];
+
   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
     for (PRUint32 i = 0, i_end = ArrayLength(backgroundValues);
          i < i_end; ++i) {
-      if (backgroundValues[i] == eCSSProperty_background_color) {
-        backColorIndex = nValues;
-      }
+      properties[nValues] = backgroundValues[i];
       values[nValues++] = ruleData.ValueFor(backgroundValues[i]);
     }
   }
 
   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) {
     for (PRUint32 i = 0, i_end = ArrayLength(borderValues);
          i < i_end; ++i) {
+      properties[nValues] = borderValues[i];
       values[nValues++] = ruleData.ValueFor(borderValues[i]);
     }
   }
 
   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) {
     for (PRUint32 i = 0, i_end = ArrayLength(paddingValues);
          i < i_end; ++i) {
+      properties[nValues] = paddingValues[i];
       values[nValues++] = ruleData.ValueFor(paddingValues[i]);
     }
   }
 
   nsStyleContext* styleContext = aStyleContext;
 
   // We need to be careful not to count styles covered up by user-important or
   // UA-important declarations.  But we do want to catch explicit inherit
@@ -7206,21 +7208,24 @@ nsRuleNode::HasAuthorSpecifiedRules(nsSt
         } else {
           // If any of the values we care about was set by the above rule,
           // we have author style.
           for (PRUint32 i = 0; i < nValues; ++i) {
             if (values[i]->GetUnit() != eCSSUnit_Null &&
                 values[i]->GetUnit() != eCSSUnit_Dummy && // see above
                 values[i]->GetUnit() != eCSSUnit_DummyInherit) {
               // If author colors are not allowed, only claim to have
-              // author-specified rules if we're looking at the background
-              // color and it's set to transparent.  Anything else should get
-              // set to a dummy value instead.
+              // author-specified rules if we're looking at a non-color
+              // property or if we're looking at the background color and it's
+              // set to transparent.  Anything else should get set to a dummy
+              // value instead.
               if (aAuthorColorsAllowed ||
-                  (i == backColorIndex &&
+                  !nsCSSProps::PropHasFlags(properties[i],
+                     CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED) ||
+                  (properties[i] == eCSSProperty_background_color &&
                    !values[i]->IsNonTransparentColor())) {
                 return true;
               }
 
               values[i]->SetDummyValue();
             }
           }
         }
--- a/layout/style/nsStyleSet.h
+++ b/layout/style/nsStyleSet.h
@@ -42,16 +42,18 @@
  * the container for the style sheets that apply to a presentation, and
  * the internal API that the style system exposes for creating (and
  * potentially re-creating) style contexts
  */
 
 #ifndef nsStyleSet_h_
 #define nsStyleSet_h_
 
+#include "mozilla/Attributes.h"
+
 #include "nsIStyleRuleProcessor.h"
 #include "nsCSSStyleSheet.h"
 #include "nsBindingManager.h"
 #include "nsRuleNode.h"
 #include "nsTArray.h"
 #include "nsCOMArray.h"
 #include "nsAutoPtr.h"
 #include "nsIStyleRule.h"
@@ -316,19 +318,18 @@ class nsStyleSet
     --mUnusedRuleNodeCount;
   }
 
   nsCSSStyleSheet::EnsureUniqueInnerResult EnsureUniqueInnerOnCSSSheets();
 
   nsIStyleRule* InitialStyleRule();
 
  private:
-  // Not to be implemented
-  nsStyleSet(const nsStyleSet& aCopy);
-  nsStyleSet& operator=(const nsStyleSet& aCopy);
+  nsStyleSet(const nsStyleSet& aCopy) MOZ_DELETE;
+  nsStyleSet& operator=(const nsStyleSet& aCopy) MOZ_DELETE;
 
   // Returns false on out-of-memory.
   bool BuildDefaultStyleData(nsPresContext* aPresContext);
 
   // Run mark-and-sweep GC on mRuleTree and mOldRuleTrees, based on mRoots.
   void GCRuleTrees();
 
   // Update the rule processor list after a change to the style sheet list.
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -43,16 +43,18 @@
 /*
  * structs that contain the data provided by nsStyleContext, the
  * internal API for computed style data for an element
  */
 
 #ifndef nsStyleStruct_h___
 #define nsStyleStruct_h___
 
+#include "mozilla/Attributes.h"
+
 #include "nsColor.h"
 #include "nsCoord.h"
 #include "nsMargin.h"
 #include "nsRect.h"
 #include "nsFont.h"
 #include "nsStyleCoord.h"
 #include "nsStyleConsts.h"
 #include "nsChangeHint.h"
@@ -174,19 +176,18 @@ public:
 
   bool IsOpaque();
 
   NS_INLINE_DECL_REFCOUNTING(nsStyleGradient)
 
 private:
   ~nsStyleGradient() {}
 
-  // Not to be implemented
-  nsStyleGradient(const nsStyleGradient& aOther);
-  nsStyleGradient& operator=(const nsStyleGradient& aOther);
+  nsStyleGradient(const nsStyleGradient& aOther) MOZ_DELETE;
+  nsStyleGradient& operator=(const nsStyleGradient& aOther) MOZ_DELETE;
 };
 
 enum nsStyleImageType {
   eStyleImageType_Null,
   eStyleImageType_Image,
   eStyleImageType_Gradient,
   eStyleImageType_Element
 };
@@ -933,17 +934,17 @@ protected:
 private:
   nsCOMPtr<imgIRequest> mBorderImage; // [reset]
 
   // Cache used by callers for border-image painting
   nsCOMArray<imgIContainer> mSubImages;
 
   nscoord       mTwipsPerPixel;
 
-  nsStyleBorder& operator=(const nsStyleBorder& aOther); // Not to be implemented
+  nsStyleBorder& operator=(const nsStyleBorder& aOther) MOZ_DELETE;
 };
 
 
 struct nsStyleOutline {
   nsStyleOutline(nsPresContext* aPresContext);
   nsStyleOutline(const nsStyleOutline& aOutline);
   ~nsStyleOutline(void) {
     MOZ_COUNT_DTOR(nsStyleOutline);
@@ -1059,17 +1060,17 @@ struct nsStyleList {
     if (mListStyleImage)
       mListStyleImage->LockImage();
   }
 
   PRUint8   mListStyleType;             // [inherited] See nsStyleConsts.h
   PRUint8   mListStylePosition;         // [inherited]
 private:
   nsCOMPtr<imgIRequest> mListStyleImage; // [inherited]
-  nsStyleList& operator=(const nsStyleList& aOther); // Not to be implemented
+  nsStyleList& operator=(const nsStyleList& aOther) MOZ_DELETE;
 public:
   nsRect        mImageRegion;           // [inherited] the rect to use within an image
 };
 
 struct nsStylePosition {
   nsStylePosition(void);
   nsStylePosition(const nsStylePosition& aOther);
   ~nsStylePosition(void);
new file mode 100644
--- /dev/null
+++ b/mfbt/Assertions.h
@@ -0,0 +1,222 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99 ft=cpp:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jeff Walden <jwalden+code@mit.edu>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_Assertions_h_
+#define mozilla_Assertions_h_
+
+#include "mozilla/Types.h"
+
+/*
+ * MOZ_STATIC_ASSERT may be used to assert a condition *at compile time*.  This
+ * can be useful when you make certain assumptions about what must hold for
+ * optimal, or even correct, behavior.  For example, you might assert that the
+ * size of a struct is a multiple of the target architecture's word size:
+ *
+ *   struct S { ... };
+ *   MOZ_STATIC_ASSERT(sizeof(S) % sizeof(size_t) == 0,
+ *                     "S should be a multiple of word size for efficiency");
+ *
+ * This macro can be used in any location where both an extern declaration and a
+ * typedef could be used.
+ *
+ * Be aware of the gcc 4.2 concerns noted further down when writing patches that
+ * use this macro, particularly if a patch only bounces on OS X.
+ */
+#ifdef __cplusplus
+#  if defined(__clang__)
+#    ifndef __has_extension
+#      define __has_extension __has_feature /* compatibility, for older versions of clang */
+#    endif
+#    if __has_extension(cxx_static_assert)
+#      define MOZ_STATIC_ASSERT(cond, reason)    static_assert((cond), reason)
+#    endif
+#  elif defined(__GNUC__)
+#    if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L) && \
+        (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+#      define MOZ_STATIC_ASSERT(cond, reason)    static_assert((cond), #cond)
+#    endif
+#  elif defined(_MSC_VER)
+#    if _MSC_VER >= 1600 /* MSVC 10 */
+#      define MOZ_STATIC_ASSERT(cond, reason)    static_assert((cond), #cond)
+#    endif
+#  elif defined(__HP_aCC)
+#    if __HP_aCC >= 62500 && defined(_HP_CXX0x_SOURCE)
+#      define MOZ_STATIC_ASSERT(cond, reason)    static_assert((cond), #cond)
+#    endif
+#  endif
+#endif
+#ifndef MOZ_STATIC_ASSERT
+#  define MOZ_STATIC_ASSERT_GLUE1(x, y)          x##y
+#  define MOZ_STATIC_ASSERT_GLUE(x, y)           MOZ_STATIC_ASSERT_GLUE1(x, y)
+#  if defined(__SUNPRO_CC)
+     /*
+      * The Sun Studio C++ compiler is buggy when declaring, inside a function,
+      * another extern'd function with an array argument whose length contains a
+      * sizeof, triggering the error message "sizeof expression not accepted as
+      * size of array parameter".  This bug (6688515, not public yet) would hit
+      * defining moz_static_assert as a function, so we always define an extern
+      * array for Sun Studio.
+      *
+      * We include the line number in the symbol name in a best-effort attempt
+      * to avoid conflicts (see below).
+      */
+#    define MOZ_STATIC_ASSERT(cond, reason) \
+       extern char MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)[(cond) ? 1 : -1]
+#  elif defined(__COUNTER__)
+     /*
+      * If there was no preferred alternative, use a compiler-agnostic version.
+      *
+      * Note that the non-__COUNTER__ version has a bug in C++: it can't be used
+      * in both |extern "C"| and normal C++ in the same translation unit.  (Alas
+      * |extern "C"| isn't allowed in a function.)  The only affected compiler
+      * we really care about is gcc 4.2.  For that compiler and others like it,
+      * we include the line number in the function name to do the best we can to
+      * avoid conflicts.  These should be rare: a conflict would require use of
+      * MOZ_STATIC_ASSERT on the same line in separate files in the same
+      * translation unit, *and* the uses would have to be in code with
+      * different linkage, *and* the first observed use must be in C++-linkage
+      * code.
+      */
+#    define MOZ_STATIC_ASSERT(cond, reason) \
+       typedef int MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __COUNTER__)[(cond) ? 1 : -1]
+#  else
+#    define MOZ_STATIC_ASSERT(cond, reason) \
+       extern void MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)(int arg[(cond) ? 1 : -1])
+#  endif
+#endif
+
+#define MOZ_STATIC_ASSERT_IF(cond, expr, reason)  MOZ_STATIC_ASSERT(!(cond) || (expr), reason)
+
+/*
+ * XXX: we're cheating here in order to avoid creating object files
+ * for mfbt /just/ to provide a function like FatalError() to be used
+ * by MOZ_ASSERT().  (It'll happen eventually, but for just ASSERT()
+ * it isn't worth the pain.)  JS_Assert(), although unfortunately
+ * named, is part of SpiderMonkey's stable, external API, so this
+ * isn't quite as bad as it seems.
+ *
+ * Once mfbt needs object files, this unholy union with JS_Assert()
+ * will be broken.
+ *
+ * JS_Assert is present even in release builds, for the benefit of applications
+ * that build DEBUG and link against a non-DEBUG SpiderMonkey library.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern MFBT_API(void)
+JS_Assert(const char* s, const char* file, int ln);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+/*
+ * MOZ_ASSERT() is a "strong" assertion of state, like libc's
+ * assert().
+ *
+ *   MOZ_ASSERT(twoToThePowerOf(5) == 32);
+ *
+ * If a MOZ_ASSERT() fails in a debug build, the process in which it fails will
+ * stop running in a loud and dramatic way.  It has no effect in an optimized
+ * build.  This macro is designed to catch bugs during debugging, not "in the
+ * field".
+ */
+#ifdef DEBUG
+#  define MOZ_ASSERT(expr_)                                      \
+     ((expr_) ? ((void)0) : JS_Assert(#expr_, __FILE__, __LINE__))
+#else
+#  define MOZ_ASSERT(expr_) ((void)0)
+#endif /* DEBUG */
+
+/*
+ * MOZ_ASSERT_IF(cond1, cond2) is equivalent to MOZ_ASSERT(cond2) if cond1 is
+ * true.
+ *
+ *   MOZ_ASSERT_IF(isPrime(num), num == 2 || isOdd(num));
+ *
+ * As with MOZ_ASSERT, MOZ_ASSERT_IF has effect only in debug builds.  It is
+ * designed to catch bugs during debugging, not "in the field".
+ */
+#ifdef DEBUG
+#  define MOZ_ASSERT_IF(cond, expr)  ((cond) ? MOZ_ASSERT(expr) : ((void)0))
+#else
+#  define MOZ_ASSERT_IF(cond, expr)  ((void)0)
+#endif
+
+/*
+ * MOZ_NOT_REACHED(reason) indicates that the given point can't be reached
+ * during execution: simply reaching that point in execution is a bug.  It takes
+ * as an argument an error message indicating the reason why that point should
+ * not have been reachable.
+ *
+ *   // ...in a language parser...
+ *   void handle(BooleanLiteralNode node)
+ *   {
+ *     if (node.isTrue())
+ *       handleTrueLiteral();
+ *     else if (node.isFalse())
+ *       handleFalseLiteral();
+ *     else
+ *       MOZ_NOT_REACHED("boolean literal that's not true or false?");
+ *   }
+ */
+#ifdef DEBUG
+#  define MOZ_NOT_REACHED(reason)    JS_Assert(reason, __FILE__, __LINE__)
+#else
+#  define MOZ_NOT_REACHED(reason)    ((void)0)
+#endif
+
+/*
+ * MOZ_ALWAYS_TRUE(expr) and MOZ_ALWAYS_FALSE(expr) always evaluate the provided
+ * expression, in debug builds and in release builds both.  Then, in debug
+ * builds only, the value of the expression is asserted either true or false
+ * using MOZ_ASSERT.
+ */
+#ifdef DEBUG
+#  define MOZ_ALWAYS_TRUE(expr)      MOZ_ASSERT((expr))
+#  define MOZ_ALWAYS_FALSE(expr)     MOZ_ASSERT(!(expr))
+#else
+#  define MOZ_ALWAYS_TRUE(expr)      ((void)(expr))
+#  define MOZ_ALWAYS_FALSE(expr)     ((void)(expr))
+#endif
+
+#endif /* mozilla_Assertions_h_ */
--- a/mfbt/Attributes.h
+++ b/mfbt/Attributes.h
@@ -44,16 +44,49 @@
 #define mozilla_Attributes_h_
 
 /*
  * This header does not include any other headers so that it can be included by
  * code that is (only currently) mfbt-incompatible.
  */
 
 /*
+ * MOZ_INLINE is a macro which expands to tell the compiler that the method
+ * decorated with it should be inlined.  This macro is usable from C and C++
+ * code, even though C89 does not support the |inline| keyword.  The compiler
+ * may ignore this directive if it chooses.
+ */
+#if defined(__cplusplus)
+#  define MOZ_INLINE            inline
+#elif defined(_MSC_VER)
+#  define MOZ_INLINE            __inline
+#elif defined(__GNUC__)
+#  define MOZ_INLINE            __inline__
+#else
+#  define MOZ_INLINE            inline
+#endif
+
+/*
+ * MOZ_ALWAYS_INLINE is a macro which expands to tell the compiler that the
+ * method decorated with it must be inlined, even if the compiler thinks
+ * otherwise.  This is only a (much) stronger version of the MOZ_INLINE hint:
+ * compilers are not guaranteed to respect it (although they're much more likely
+ * to do so).
+ */
+#if defined(DEBUG)
+#  define MOZ_ALWAYS_INLINE     MOZ_INLINE
+#elif defined(_MSC_VER)
+#  define MOZ_ALWAYS_INLINE     __forceinline
+#elif defined(__GNUC__)
+#  define MOZ_ALWAYS_INLINE     __attribute__((always_inline)) MOZ_INLINE
+#else
+#  define MOZ_ALWAYS_INLINE     MOZ_INLINE
+#endif
+
+/*
  * g++ requires -std=c++0x or -std=gnu++0x to support C++11 functionality
  * without warnings (functionality used by the macros below).  These modes are
  * detectable by checking whether __GXX_EXPERIMENTAL_CXX0X__ is defined or, more
  * standardly, by checking whether __cplusplus has a C++11 or greater value.
  * Current versions of g++ do not correctly set __cplusplus, so we check both
  * for forward compatibility.
  */
 #if defined(__clang__)
@@ -67,16 +100,19 @@
 #  endif
 #  if __has_extension(cxx_deleted_functions)
 #    define MOZ_HAVE_CXX11_DELETE
 #  endif
 #  if __has_extension(cxx_override_control)
 #    define MOZ_HAVE_CXX11_OVERRIDE
 #    define MOZ_HAVE_CXX11_FINAL         final
 #  endif
+#  if __has_attribute(noinline)
+#    define MOZ_HAVE_NEVER_INLINE        __attribute__((noinline))
+#  endif
 #  if __has_attribute(noreturn)
 #    define MOZ_HAVE_NORETURN            __attribute__((noreturn))
 #  endif
 #elif defined(__GNUC__)
 #  if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
 #    if __GNUC__ > 4
 #      define MOZ_HAVE_CXX11_DELETE
 #      define MOZ_HAVE_CXX11_OVERRIDE
@@ -95,27 +131,41 @@
 #    if __GNUC__ > 4
 #      define MOZ_HAVE_CXX11_FINAL       __final
 #    elif __GNUC__ == 4
 #      if __GNUC_MINOR__ >= 7
 #        define MOZ_HAVE_CXX11_FINAL     __final
 #      endif
 #    endif
 #  endif
+#  define MOZ_HAVE_NEVER_INLINE          __attribute__((noinline))
 #  define MOZ_HAVE_NORETURN              __attribute__((noreturn))
 #elif defined(_MSC_VER)
 #  if _MSC_VER >= 1400
 #    define MOZ_HAVE_CXX11_OVERRIDE
      /* MSVC currently spells "final" as "sealed". */
 #    define MOZ_HAVE_CXX11_FINAL         sealed
 #  endif
+#  define MOZ_HAVE_NEVER_INLINE          __declspec(noinline)
 #  define MOZ_HAVE_NORETURN              __declspec(noreturn)
 #endif
 
 /*
+ * MOZ_NEVER_INLINE is a macro which expands to tell the compiler that the
+ * method decorated with it must never be inlined, even if the compiler would
+ * otherwise choose to inline the method.  Compilers aren't absolutely
+ * guaranteed to support this, but most do.
+ */
+#if defined(MOZ_HAVE_NEVER_INLINE)
+#  define MOZ_NEVER_INLINE      MOZ_HAVE_NEVER_INLINE
+#else
+#  define MOZ_NEVER_INLINE      /* no support */
+#endif
+
+/*
  * MOZ_NORETURN, specified at the start of a function declaration, indicates
  * that the given function does not return.  (The function definition does not
  * need to be annotated.)
  *
  *   MOZ_NORETURN void abort(const char* msg);
  *
  * This modifier permits the compiler to optimize code assuming a call to such a
  * function will never return.  It also enables the compiler to avoid spurious
--- a/mfbt/GuardObjects.h
+++ b/mfbt/GuardObjects.h
@@ -36,18 +36,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_GuardObjects_h
 #define mozilla_GuardObjects_h
 
-#include "mozilla/Types.h"
-#include "mozilla/Util.h"
+#include "mozilla/Assertions.h"
 
 namespace mozilla {
   /**
    * The following classes are designed to cause assertions to detect
    * inadvertent use of guard objects as temporaries.  In other words,
    * when we have a guard object whose only purpose is its constructor and
    * destructor (and is never otherwise referenced), the intended use
    * might be:
--- a/mfbt/RangedPtr.h
+++ b/mfbt/RangedPtr.h
@@ -36,16 +36,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_RangedPtr_h_
 #define mozilla_RangedPtr_h_
 
+#include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Util.h"
 
 namespace mozilla {
 
 /*
  * RangedPtr is a smart pointer restricted to an address range specified at
  * creation.  The pointer (and any smart pointers derived from it) must remain
--- a/mfbt/RefPtr.h
+++ b/mfbt/RefPtr.h
@@ -36,18 +36,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_RefPtr_h_
 #define mozilla_RefPtr_h_
 
+#include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
-#include "mozilla/Util.h"
 
 /**
  * Helpers for defining and using refcounted objects.
  */
 
 namespace mozilla {
 
 template<typename T> class RefCounted;
--- a/mfbt/Util.h
+++ b/mfbt/Util.h
@@ -35,105 +35,20 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_Util_h_
 #define mozilla_Util_h_
 
+#include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Types.h"
 
-/*
- * XXX: we're cheating here in order to avoid creating object files
- * for mfbt /just/ to provide a function like FatalError() to be used
- * by MOZ_ASSERT().  (It'll happen eventually, but for just ASSERT()
- * it isn't worth the pain.)  JS_Assert(), although unfortunately
- * named, is part of SpiderMonkey's stable, external API, so this
- * isn't quite as bad as it seems.
- *
- * Once mfbt needs object files, this unholy union with JS_Assert()
- * will be broken.
- *
- * JS_Assert is present even in release builds, for the benefit of applications
- * that build DEBUG and link against a non-DEBUG SpiderMonkey library.
- */
-MOZ_BEGIN_EXTERN_C
-
-extern MFBT_API(void)
-JS_Assert(const char *s, const char *file, int ln);
-
-MOZ_END_EXTERN_C
-
-/*
- * MOZ_ASSERT() is a "strong" assertion of state, like libc's
- * assert().  If a MOZ_ASSERT() fails in a debug build, the process in
- * which it fails will stop running in a loud and dramatic way.
- */
-#ifdef DEBUG
-#  define MOZ_ASSERT(expr_)                                      \
-     ((expr_) ? (void)0 : JS_Assert(#expr_, __FILE__, __LINE__))
-#else
-#  define MOZ_ASSERT(expr_) ((void)0)
-#endif  /* DEBUG */
-
-/*
- * MOZ_INLINE is a macro which expands to tell the compiler that the method
- * decorated with it should be inlined.  This macro is usable from C and C++
- * code, even though C89 does not support the |inline| keyword.  The compiler
- * may ignore this directive if it chooses.
- */
-#ifndef MOZ_INLINE
-#  if defined __cplusplus
-#    define MOZ_INLINE          inline
-#  elif defined _MSC_VER
-#    define MOZ_INLINE          __inline
-#  elif defined __GNUC__
-#    define MOZ_INLINE          __inline__
-#  else
-#    define MOZ_INLINE          inline
-#  endif
-#endif
-
-/*
- * MOZ_ALWAYS_INLINE is a macro which expands to tell the compiler that the
- * method decorated with it must be inlined, even if the compiler thinks
- * otherwise.  This is only a (much) stronger version of the MOZ_INLINE hint:
- * compilers are not guaranteed to respect it (although they're much more likely
- * to do so).
- */
-#ifndef MOZ_ALWAYS_INLINE
-#  if defined DEBUG
-#    define MOZ_ALWAYS_INLINE   MOZ_INLINE
-#  elif defined _MSC_VER
-#    define MOZ_ALWAYS_INLINE   __forceinline
-#  elif defined __GNUC__
-#    define MOZ_ALWAYS_INLINE   __attribute__((always_inline)) MOZ_INLINE
-#  else
-#    define MOZ_ALWAYS_INLINE   MOZ_INLINE
-#  endif
-#endif
-
-/*
- * MOZ_NEVER_INLINE is a macro which expands to tell the compiler that the
- * method decorated with it must never be inlined, even if the compiler would
- * otherwise choose to inline the method.  Compilers aren't absolutely
- * guaranteed to support this, but most do.
- */
-#ifndef MOZ_NEVER_INLINE
-#  if defined _MSC_VER
-#    define MOZ_NEVER_INLINE __declspec(noinline)
-#  elif defined __GNUC__
-#    define MOZ_NEVER_INLINE __attribute__((noinline))
-#  else
-#    define MOZ_NEVER_INLINE
-#  endif
-#endif
-
 #ifdef __cplusplus
 
 namespace mozilla {
 
 /**
  * DebugOnly contains a value of type T, but only in debug builds.  In
  * release builds, it does not contain a value.  This helper is
  * intended to be used along with ASSERT()-style macros, allowing one
--- a/mfbt/exported_headers.mk
+++ b/mfbt/exported_headers.mk
@@ -37,16 +37,17 @@
 
 # This file defines the headers exported by mfbt.  It is included by mfbt
 # itself and by the JS engine, which, when built standalone, must install
 # mfbt's exported headers itself.
 
 EXPORTS_NAMESPACES += mozilla
 
 EXPORTS_mozilla += \
+  Assertions.h \
   Attributes.h \
   GuardObjects.h \
   MSStdInt.h \
   RangedPtr.h \
   RefPtr.h \
   StdInt.h \
   Types.h \
   Util.h \
--- a/mobile/android/base/AutoCompletePopup.java
+++ b/mobile/android/base/AutoCompletePopup.java
@@ -63,18 +63,16 @@ public class AutoCompletePopup extends L
 
     private int mWidth;
     private int mHeight;
 
     private Animation mAnimation; 
 
     private static final String LOGTAG = "AutoCompletePopup";
 
-    private static int sMinWidth = 0;
-
     public AutoCompletePopup(Context context, AttributeSet attrs) {
         super(context, attrs);
         mContext = context;
 
         mAnimation = AnimationUtils.loadAnimation(context, R.anim.grow_fade_in);
         mAnimation.setDuration(75);
 
         setFocusable(false);
@@ -129,28 +127,17 @@ public class AutoCompletePopup extends L
         int listLeft = left < 0 ? 0 : left;
         int listTop = top + height;
 
         FloatSize viewport = GeckoApp.mAppContext.getLayerController().getViewportSize();
 
         // If the textbox is smaller than the screen-width,
         // shrink the list's width
         if ((left + width) < viewport.width) 
-            listWidth = left < 0 ? left + width : width;
-
-        // Late initializing variable to allow DisplayMetrics not to be null and avoid NPE
-        if (sMinWidth == 0)
-            sMinWidth = 100 * GeckoAppShell.getDpi();
-
-        if (listWidth < sMinWidth) {
-            listWidth = sMinWidth;
-
-            if ((listLeft + listWidth) > viewport.width)
-                listLeft = (int)viewport.width - listWidth;
-        }
+            listWidth = left + width;
 
         // If the list is extending outside of the viewport
         // try moving above
         if (((listTop + listHeight) > viewport.height) && (listHeight <= top))
             listTop = (top - listHeight);
 
         mLayout = new RelativeLayout.LayoutParams(listWidth, listHeight);
         mLayout.setMargins(listLeft, listTop, 0, 0);
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -106,16 +106,17 @@ abstract public class GeckoApp
     public static SurfaceView cameraView;
     public static GeckoApp mAppContext;
     public static boolean mFullScreen = false;
     public static File sGREDir = null;
     public static Menu sMenu;
     public Handler mMainHandler;
     private File mProfileDir;
     private static boolean sIsGeckoReady = false;
+    private static int mOrientation;
 
     private IntentFilter mConnectivityFilter;
     private IntentFilter mBatteryFilter;
 
     private BroadcastReceiver mConnectivityReceiver;
     private BroadcastReceiver mSmsReceiver;
     private BroadcastReceiver mBatteryReceiver;
 
@@ -897,17 +898,17 @@ abstract public class GeckoApp
                 final int tabId = message.getInt("tabID");
                 final String mode = message.getString("mode");
                 Log.i(LOGTAG, "Security Mode - " + mode);
                 handleSecurityChange(tabId, mode);
             } else if (event.equals("Content:StateChange")) {
                 final int tabId = message.getInt("tabID");
                 int state = message.getInt("state");
                 Log.i(LOGTAG, "State - " + state);
-                if ((state & GeckoAppShell.WPL_STATE_IS_DOCUMENT) != 0) {
+                if ((state & GeckoAppShell.WPL_STATE_IS_NETWORK) != 0) {
                     if ((state & GeckoAppShell.WPL_STATE_START) != 0) {
                         Log.i(LOGTAG, "Got a document start");
                         handleDocumentStart(tabId);
                     } else if ((state & GeckoAppShell.WPL_STATE_STOP) != 0) {
                         Log.i(LOGTAG, "Got a document stop");
                         handleDocumentStop(tabId);
                     }
                 }
@@ -1589,16 +1590,18 @@ abstract public class GeckoApp
 
                 // it would be good only to do this if MOZ_UPDATER was defined 
                 long startTime = new Date().getTime();
                 checkAndLaunchUpdate();
                 Log.w(LOGTAG, "checking for an update took " + (new Date().getTime() - startTime) + "ms");
                 checkMigrateProfile();
             }
         }, 50);
+
+        mOrientation = getResources().getConfiguration().orientation;
     }
 
     /**
      * Enable Android StrictMode checks (for supported OS versions).
      * http://developer.android.com/reference/android/os/StrictMode.html
      */
     private void enableStrictMode()
     {
@@ -1797,24 +1800,31 @@ abstract public class GeckoApp
     public void onContentChanged() {
         super.onContentChanged();
         if (mAboutHomeContent != null)
             mAboutHomeContent.onActivityContentChanged(this);
     }
 
 
     @Override
-    public void onConfigurationChanged(android.content.res.Configuration newConfig)
+    public void onConfigurationChanged(Configuration newConfig)
     {
         Log.i(LOGTAG, "configuration changed");
 
-        // hide the autocomplete list on rotation
-        mAutoCompletePopup.hide();
+        super.onConfigurationChanged(newConfig);
+
+        if (mOrientation != newConfig.orientation) {
+            mOrientation = newConfig.orientation;
+            mAutoCompletePopup.hide();
 
-        super.onConfigurationChanged(newConfig);
+            if (Build.VERSION.SDK_INT >= 11) {
+                mBrowserToolbar = (BrowserToolbar) getLayoutInflater().inflate(R.layout.gecko_app_actionbar, null);
+                GeckoActionBar.setCustomView(mAppContext, mBrowserToolbar);
+            }
+        }
     }
 
     @Override
     public void onLowMemory()
     {
         Log.e(LOGTAG, "low memory");
         if (checkLaunchState(LaunchState.GeckoRunning))
             GeckoAppShell.onLowMemory();
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -101,16 +101,17 @@ public class GeckoAppShell
         mAlertNotifications = new HashMap<Integer, AlertNotification>();
 
     /* Keep in sync with constants found here:
       http://mxr.mozilla.org/mozilla-central/source/uriloader/base/nsIWebProgressListener.idl
     */
     static public final int WPL_STATE_START = 0x00000001;
     static public final int WPL_STATE_STOP = 0x00000010;
     static public final int WPL_STATE_IS_DOCUMENT = 0x00020000;
+    static public final int WPL_STATE_IS_NETWORK = 0x00040000;
 
     static private File sCacheFile = null;
     static private int sFreeSpace = -1;
     static File sHomeDir = null;
     static private int sDensityDpi = 0;
 
     private static HashMap<String, ArrayList<GeckoEventListener>> mEventListeners;
 
@@ -135,16 +136,18 @@ public class GeckoAppShell
 
     public static native void processNextNativeEvent();
 
     public static native void notifyBatteryChange(double aLevel, boolean aCharging, double aRemainingTime);
 
     public static native void notifySmsReceived(String aSender, String aBody, long aTimestamp);
     public static native ByteBuffer allocateDirectBuffer(long size);
     public static native void freeDirectBuffer(ByteBuffer buf);
+    public static native void bindWidgetTexture();
+    public static native boolean testDirectTexture();
 
     // A looper thread, accessed by GeckoAppShell.getHandler
     private static class LooperThread extends Thread {
         public SynchronousQueue<Handler> mHandlerQueue =
             new SynchronousQueue<Handler>();
         
         public void run() {
             setName("GeckoLooper Thread");
@@ -422,16 +425,24 @@ public class GeckoAppShell
     }
 
     public static void runGecko(String apkPath, String args, String url) {
         // run gecko -- it will spawn its own thread
         GeckoAppShell.nativeInit();
 
         Log.i(LOGTAG, "post native init");
 
+        // If we have direct texture available, use it
+        if (GeckoAppShell.testDirectTexture()) {
+            Log.i(LOGTAG, "Using direct texture for widget layer");
+            GeckoApp.mAppContext.getSoftwareLayerClient().installWidgetLayer();
+        } else {
+            Log.i(LOGTAG, "Falling back to traditional texture upload");
+        }
+
         // Tell Gecko where the target byte buffer is for rendering
         GeckoAppShell.setSoftwareLayerClient(GeckoApp.mAppContext.getSoftwareLayerClient());
 
         Log.i(LOGTAG, "setSoftwareLayerClient called");
 
         // First argument is the .apk path
         String combinedArgs = apkPath + " -greomni " + apkPath;
         if (args != null)
@@ -489,26 +500,29 @@ public class GeckoAppShell
 
     // Tell the Gecko event loop that an event is available.
     public static native void notifyGeckoOfEvent(GeckoEvent event);
 
     /*
      *  The Gecko-side API: API methods that Gecko calls
      */
     public static void notifyIME(int type, int state) {
-        mInputConnection.notifyIME(type, state);
+        if (mInputConnection != null)
+            mInputConnection.notifyIME(type, state);
     }
 
     public static void notifyIMEEnabled(int state, String typeHint,
                                         String actionHint, boolean landscapeFS) {
-        mInputConnection.notifyIMEEnabled(state, typeHint, actionHint, landscapeFS);
+        if (mInputConnection != null)
+            mInputConnection.notifyIMEEnabled(state, typeHint, actionHint, landscapeFS);
     }
 
     public static void notifyIMEChange(String text, int start, int end, int newEnd) {
-        mInputConnection.notifyIMEChange(text, start, end, newEnd);
+        if (mInputConnection != null)
+            mInputConnection.notifyIMEChange(text, start, end, newEnd);
     }
 
     private static CountDownLatch sGeckoPendingAcks = null;
 
     // Block the current thread until the Gecko event loop is caught up
     synchronized public static void geckoEventSync() {
         sGeckoPendingAcks = new CountDownLatch(1);
         GeckoAppShell.sendEventToGecko(
--- a/mobile/android/base/GeckoPreferences.java
+++ b/mobile/android/base/GeckoPreferences.java
@@ -36,26 +36,34 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 package org.mozilla.gecko;
 
 import java.lang.CharSequence;
 import java.util.ArrayList;
 
+import android.app.Dialog;
+import android.text.Editable;
+import android.app.AlertDialog;
 import android.os.Build;
 import android.os.Bundle;
 import android.content.res.Resources;
 import android.content.Context;
 import android.preference.*;
 import android.preference.Preference.*;
+import android.text.InputType;
 import android.util.Log;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.text.TextWatcher;
+import android.content.DialogInterface;
 
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
 public class GeckoPreferences
     extends PreferenceActivity
     implements OnPreferenceChangeListener, GeckoEventListener
@@ -123,31 +131,156 @@ public class GeckoPreferences
             case android.R.id.home:
                 finish();
                 return true;
         }
 
         return super.onOptionsItemSelected(item);
     }
 
+    final private int DIALOG_CREATE_MASTER_PASSWORD = 0;
+    final private int DIALOG_REMOVE_MASTER_PASSWORD = 1;
+
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         String prefName = preference.getKey();
+        if (prefName.equals("privacy.masterpassword.enabled")) {
+            showDialog((Boolean)newValue ? DIALOG_CREATE_MASTER_PASSWORD : DIALOG_REMOVE_MASTER_PASSWORD);
+            return false;
+        }
+
         setPreference(prefName, newValue);
         if (preference instanceof ListPreference) {
             // We need to find the entry for the new value
             int newIndex = ((ListPreference)preference).findIndexOfValue((String) newValue);
             CharSequence newEntry = ((ListPreference)preference).getEntries()[newIndex];
             ((ListPreference)preference).setSummary(newEntry);
         }
         if (preference instanceof LinkPreference)
             finish();
         return true;
     }
 
+    private EditText getTextBox(int aHintText) {
+        EditText input = new EditText(GeckoApp.mAppContext);
+        int inputtype = InputType.TYPE_CLASS_TEXT;
+        inputtype |= InputType.TYPE_TEXT_VARIATION_PASSWORD | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
+        input.setInputType(inputtype);
+
+        String hint = getResources().getString(aHintText);
+        input.setHint(aHintText);
+        return input;
+    }
+
+    private AlertDialog mDialog = null;
+
+    private class PasswordTextWatcher implements TextWatcher {
+        EditText input1 = null;
+        EditText input2 = null;
+
+        PasswordTextWatcher(EditText aInput1, EditText aInput2) {
+            input1 = aInput1;
+            input2 = aInput2;
+        }
+
+        public void afterTextChanged(Editable s) {
+            if (mDialog == null)
+                return;
+
+            String text1 = input1.getText().toString();
+            String text2 = input2.getText().toString();
+            mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(text1.equals(text2));
+        }
+
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
+        public void onTextChanged(CharSequence s, int start, int before, int count) { }
+    }
+
+    protected Dialog onCreateDialog(int id) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(this);
+        LinearLayout linearLayout = new LinearLayout(this);
+        linearLayout.setOrientation(LinearLayout.VERTICAL);
+        switch(id) {
+            case DIALOG_CREATE_MASTER_PASSWORD:
+                final EditText input1 = getTextBox(R.string.masterpassword_password);
+                final EditText input2 = getTextBox(R.string.masterpassword_confirm);
+                PasswordTextWatcher watcher = new PasswordTextWatcher(input1, input2);
+                input1.addTextChangedListener((TextWatcher)watcher);
+                input2.addTextChangedListener((TextWatcher)watcher);
+                linearLayout.addView(input1);
+                linearLayout.addView(input2);
+
+                builder.setTitle(R.string.masterpassword_create_title)
+                       .setView((View)linearLayout)
+                       .setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {  
+                            public void onClick(DialogInterface dialog, int which) {
+                                JSONObject jsonPref = new JSONObject();
+                                try {
+                                    jsonPref.put("name", "privacy.masterpassword.enabled");
+                                    jsonPref.put("type", "string");
+                                    jsonPref.put("value", input1.getText().toString());
+                    
+                                    GeckoEvent event = new GeckoEvent("Preferences:Set", jsonPref.toString());
+                                    GeckoAppShell.sendEventToGecko(event);
+                                } catch(Exception ex) {
+                                    Log.e(LOGTAG, "Error setting masterpassword", ex);
+                                }
+                                mDialog = null;
+                                input1.setText("");
+                                input2.setText("");
+                                return;
+                            }
+                        })
+                        .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {  
+                            public void onClick(DialogInterface dialog, int which) {
+                                mDialog = null;
+                                input1.setText("");
+                                input2.setText("");
+                                return;
+                            }
+                        });
+                break;
+            case DIALOG_REMOVE_MASTER_PASSWORD:
+                final EditText input = getTextBox(R.string.masterpassword_password);
+                linearLayout.addView(input);
+
+                builder.setTitle(R.string.masterpassword_remove_title)
+                       .setView((View)linearLayout)
+                       .setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {  
+                            public void onClick(DialogInterface dialog, int which) {
+                                try {
+                                    JSONObject jsonPref = new JSONObject();
+                                    jsonPref.put("name", "privacy.masterpassword.enabled");
+                                    jsonPref.put("type", "string");
+                                    jsonPref.put("value", input.getText().toString());
+                        
+                                    GeckoEvent event = new GeckoEvent("Preferences:Set", jsonPref.toString());
+                                    GeckoAppShell.sendEventToGecko(event);
+                                } catch(Exception ex) {
+                                    Log.e(LOGTAG, "Error setting masterpassword", ex);
+                                }
+                                input.setText("");
+                                mDialog = null;
+                                return;
+                            }
+                        })
+                       .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {  
+                            public void onClick(DialogInterface dialog, int which) {
+                                mDialog = null;
+                                input.setText("");
+                                return;
+                            }
+                        });
+                break;
+            default:
+                return null;
+        }
+        return mDialog = builder.create();
+    }
+
     private void refresh(JSONArray jsonPrefs) {
         // enable all preferences once we have them from gecko
         GeckoAppShell.getMainHandler().post(new Runnable() {
             public void run() {
                 mPreferenceScreen.setEnabled(true);
             }
         });
 
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -112,16 +112,17 @@ JAVAFILES = \
   gfx/PointUtils.java \
   gfx/RectUtils.java \
   gfx/ScrollbarLayer.java \
   gfx/SingleTileLayer.java \
   gfx/TextLayer.java \
   gfx/TextureReaper.java \
   gfx/TileLayer.java \
   gfx/ViewportMetrics.java \
+  gfx/WidgetTileLayer.java \
   ui/PanZoomController.java \
   $(NULL)
 
 PROCESSEDJAVAFILES = \
   $(SYNC_PP_JAVA_FILES) \
   App.java \
   LauncherShortcuts.java \
   NotificationHandler.java \
--- a/mobile/android/base/gfx/GeckoSoftwareLayerClient.java
+++ b/mobile/android/base/gfx/GeckoSoftwareLayerClient.java
@@ -40,16 +40,17 @@ package org.mozilla.gecko.gfx;
 
 import org.mozilla.gecko.gfx.CairoImage;
 import org.mozilla.gecko.gfx.IntSize;
 import org.mozilla.gecko.gfx.LayerClient;
 import org.mozilla.gecko.gfx.LayerController;
 import org.mozilla.gecko.gfx.LayerRenderer;
 import org.mozilla.gecko.gfx.PointUtils;
 import org.mozilla.gecko.gfx.SingleTileLayer;
+import org.mozilla.gecko.gfx.WidgetTileLayer;
 import org.mozilla.gecko.FloatUtils;
 import org.mozilla.gecko.GeckoApp;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.GeckoEventListener;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Point;
@@ -71,17 +72,17 @@ import java.nio.ByteBuffer;
 public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventListener {
     private static final String LOGTAG = "GeckoSoftwareLayerClient";
 
     private Context mContext;
     private int mFormat;
     private IntSize mScreenSize, mViewportSize;
     private IntSize mBufferSize;
     private ByteBuffer mBuffer;
-    private final SingleTileLayer mTileLayer;
+    private Layer mTileLayer;
 
     /* The viewport rect that Gecko is currently displaying. */
     private ViewportMetrics mGeckoViewport;
 
     private CairoImage mCairoImage;
 
     private static final long MIN_VIEWPORT_CHANGE_DELAY = 350L;
     private long mLastViewportChangeTime;
@@ -120,16 +121,20 @@ public class GeckoSoftwareLayerClient ex
             if (mBuffer != null)
                 GeckoAppShell.freeDirectBuffer(mBuffer);
             mBuffer = null;
         } finally {
             super.finalize();
         }
     }
 
+    public void installWidgetLayer() {
+        mTileLayer = new WidgetTileLayer(mCairoImage);
+    }
+
     /** Attaches the root layer to the layer controller so that Gecko appears. */
     @Override
     public void setLayerController(LayerController layerController) {
         super.setLayerController(layerController);
 
         layerController.setRoot(mTileLayer);
         if (mGeckoViewport != null) {
             layerController.setViewportMetrics(mGeckoViewport);
@@ -183,17 +188,19 @@ public class GeckoSoftwareLayerClient ex
      * TODO: Would be cleaner if this took an android.graphics.Rect instead, but that would require
      * a little more JNI magic.
      */
     public void endDrawing(int x, int y, int width, int height, String metadata) {
         try {
             updateViewport(metadata, !mUpdateViewportOnEndDraw);
             mUpdateViewportOnEndDraw = false;
             Rect rect = new Rect(x, y, x + width, y + height);
-            mTileLayer.invalidate(rect);
+
+            if (mTileLayer instanceof SingleTileLayer)
+                ((SingleTileLayer)mTileLayer).invalidate(rect);
         } finally {
             endTransaction(mTileLayer);
         }
     }
 
     public ViewportMetrics getGeckoViewportMetrics() {
         // Return a copy, as we modify this inside the Gecko thread
         if (mGeckoViewport != null)
--- a/mobile/android/base/gfx/LayerClient.java
+++ b/mobile/android/base/gfx/LayerClient.java
@@ -48,29 +48,29 @@ public abstract class LayerClient {
     protected abstract void render();
 
     public LayerController getLayerController() { return mLayerController; }
     public void setLayerController(LayerController layerController) {
         mLayerController = layerController;
     }
 
     /**
-     * A utility function for calling TileLayer.beginTransaction with the
+     * A utility function for calling Layer.beginTransaction with the
      * appropriate LayerView.
      */
-    public void beginTransaction(TileLayer aTileLayer) {
+    public void beginTransaction(Layer aLayer) {
         if (mLayerController != null) {
             LayerView view = mLayerController.getView();
             if (view != null) {
-                aTileLayer.beginTransaction(view);
+                aLayer.beginTransaction(view);
                 return;
             }
         }
 
-        aTileLayer.beginTransaction();
+        aLayer.beginTransaction();
     }
 
     // Included for symmetry.
-    public void endTransaction(TileLayer aTileLayer) {
-        aTileLayer.endTransaction();
+    public void endTransaction(Layer aLayer) {
+        aLayer.endTransaction();
     }
 }
 
--- a/mobile/android/base/gfx/PlaceholderLayerClient.java
+++ b/mobile/android/base/gfx/PlaceholderLayerClient.java
@@ -123,27 +123,16 @@ public class PlaceholderLayerClient exte
             mViewport.setPageSize(new FloatSize(mWidth, mHeight));
             if (getLayerController() != null)
                 getLayerController().setPageSize(mViewport.getPageSize());
         }
 
         return true;
     }
 
-    void showScreenshot() {
-        BufferedCairoImage image = new BufferedCairoImage(mBuffer, mWidth, mHeight, mFormat);
-        SingleTileLayer tileLayer = new SingleTileLayer(image);
-
-        beginTransaction(tileLayer);
-        tileLayer.setOrigin(PointUtils.round(mViewport.getDisplayportOrigin()));
-        endTransaction(tileLayer);
-
-        getLayerController().setRoot(tileLayer);
-    }
-
     @Override
     public void geometryChanged() { /* no-op */ }
     @Override
     public void viewportSizeChanged() { /* no-op */ }
     @Override
     public void render() { /* no-op */ }
 
     @Override
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/gfx/WidgetTileLayer.java
@@ -0,0 +1,116 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Android code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009-2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   James Willcox <jwillcox@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+package org.mozilla.gecko.gfx;
+
+import org.mozilla.gecko.gfx.LayerController;
+import org.mozilla.gecko.gfx.SingleTileLayer;
+import org.mozilla.gecko.GeckoAppShell;
+import android.opengl.GLES11;
+import android.opengl.GLES11Ext;
+import android.graphics.RectF;
+import android.util.Log;
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * Encapsulates the logic needed to draw the single-tiled Gecko texture
+ */
+public class WidgetTileLayer extends Layer {
+
+    private int[] mTextureIDs;
+    private CairoImage mImage;
+
+    public WidgetTileLayer(CairoImage image) {
+        mImage = image;
+    }
+
+    protected boolean initialized() { return mTextureIDs != null; }
+
+    @Override
+    public IntSize getSize() { return mImage.getSize(); }
+
+    protected void bindAndSetGLParameters() {
+        GLES11.glBindTexture(GL10.GL_TEXTURE_2D, mTextureIDs[0]);
+        GLES11.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
+        GLES11.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        if (mTextureIDs != null)
+            TextureReaper.get().add(mTextureIDs);
+    }
+
+    @Override
+    protected void performUpdates(GL10 gl) {
+        super.performUpdates(gl);
+
+        if (mTextureIDs == null) {
+            mTextureIDs = new int[1];
+            GLES11.glGenTextures(1, mTextureIDs, 0);
+        }
+
+        bindAndSetGLParameters();
+        GeckoAppShell.bindWidgetTexture();
+    }
+
+    @Override
+    public void draw(RenderContext context) {
+        // mTextureIDs may be null here during startup if Layer.java's draw method
+        // failed to acquire the transaction lock and call performUpdates.
+        if (!initialized())
+            return;
+
+        GLES11.glBindTexture(GL10.GL_TEXTURE_2D, mTextureIDs[0]);
+
+        RectF bounds;
+        int[] cropRect;
+        IntSize size = getSize();
+        RectF viewport = context.viewport;
+
+        bounds = getBounds(context, new FloatSize(size));
+        cropRect = new int[] { 0, size.height, size.width, -size.height };
+        bounds.offset(-viewport.left, -viewport.top);
+
+        GLES11.glTexParameteriv(GL10.GL_TEXTURE_2D, GLES11Ext.GL_TEXTURE_CROP_RECT_OES, cropRect,
+                                0);
+
+        float top = viewport.height() - (bounds.top + bounds.height());
+        GLES11Ext.glDrawTexfOES(bounds.left, top, 0.0f, bounds.width(), bounds.height());
+    }
+}
+
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -57,25 +57,26 @@
 <!ENTITY pref_homepage_current "Current page">
 <!ENTITY pref_remember_signons "Remember passwords">
 <!ENTITY pref_cookies "Enable cookies">
 <!ENTITY pref_char_encoding "Show character encoding">
 <!ENTITY pref_clear_history "Clear history">
 <!ENTITY pref_clear_history_confirm "Browsing history will be deleted">
 <!ENTITY pref_clear_private_data "Clear private data">
 <!ENTITY pref_clear_private_data_confirm "Browsing settings, including passwords and cookies, will be deleted">
-<!ENTITY pref_enable_plugins "Enable Plugins">
+<!ENTITY pref_enable_plugins "Enable plugins">
 <!ENTITY pref_enable_plugins_yes "Yes">
-<!ENTITY pref_enable_plugins_tap_to_play "Tap To Play">
+<!ENTITY pref_enable_plugins_tap_to_play "Tap to play">
 <!ENTITY pref_enable_plugins_no "No">
 <!ENTITY pref_font_size "Font size">
 <!ENTITY pref_font_size_small "Small">
 <!ENTITY pref_font_size_medium "Medium">
 <!ENTITY pref_font_size_large "Large">
 <!ENTITY pref_font_size_xlarge "Extra Large">
+<!ENTITY pref_use_master_password "Use master password">
 
 <!ENTITY quit "Quit">
 
 <!ENTITY addons "Add-ons">
 
 <!ENTITY share "Share">
 <!ENTITY save_as_pdf "Save as PDF">
 <!ENTITY agent_request_desktop "Request Desktop Site">
@@ -84,8 +85,16 @@
 <!ENTITY contextmenu_open_new_tab "Open in New Tab">
 <!ENTITY contextmenu_add_to_launcher "Add to Home Screen">
 <!ENTITY contextmenu_share "Share">
 
 <!ENTITY site_settings_title        "Clear Site Settings">
 <!ENTITY site_settings_cancel       "Cancel">
 <!ENTITY site_settings_clear        "Clear">
 <!ENTITY site_settings_no_settings  "There are no settings to clear.">
+
+<!ENTITY masterpassword_create_title "Create Master Password">
+<!ENTITY masterpassword_remove_title "Remove Master Password">
+<!ENTITY masterpassword_password "Password">
+<!ENTITY masterpassword_confirm "Confirm password">
+
+<!ENTITY button_ok "OK">
+<!ENTITY button_cancel "Cancel">
deleted file mode 100644
index c7d33833dda75cdce701592385cb544a13c0885d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 8e99cf467f336ddc25845b5c2f5132ce096b727e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 6fe1742d135ddc725a71c988a831f5615f5672e1..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 49ad5c3f33c883158ee1594da4f28e502eea0862..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 4d64e035c95d668d959f4516978a751ecb4eba11..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index c07c3a563a47d4dee119ccdb02d1cd73ff3d7f8c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index dc647b8c3eebd373c902546e12fbee0b31d375a5..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 1a611c71807e61435cdb804f5e309044f8f39d71..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 50cd8e69f40869e3394f1c9180c9efac478b198e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index aada9a0798ad7ebd0ba1a10ad5333740f121c706..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/mobile/android/base/resources/xml/preferences.xml
+++ b/mobile/android/base/resources/xml/preferences.xml
@@ -60,11 +60,16 @@
         <CheckBoxPreference android:key="network.cookie.cookieBehavior"
                             android:title="@string/pref_cookies"
                             android:persistent="false" />
 
         <CheckBoxPreference android:key="toolkit.telemetry.enabled"
                             android:title="@string/pref_telemetry"
                             android:persistent="false" />
 
+        <CheckBoxPreference android:key="privacy.masterpassword.enabled"
+                            android:title="@string/pref_use_master_password"
+                            android:defaultValue="false"
+                            android:persistent="false" />
+
     </PreferenceCategory>
 
 </PreferenceScreen>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -88,9 +88,18 @@
   <string name="site_settings_title">&site_settings_title;</string>
   <string name="site_settings_cancel">&site_settings_cancel;</string>
   <string name="site_settings_clear">&site_settings_clear;</string>
   <string name="site_settings_no_settings">&site_settings_no_settings;</string>
 
   <string name="contextmenu_open_new_tab">&contextmenu_open_new_tab;</string>
   <string name="contextmenu_add_to_launcher">&contextmenu_add_to_launcher;</string>
   <string name="contextmenu_share">&contextmenu_share;</string>
+
+  <string name="pref_use_master_password">&pref_use_master_password;</string>
+  <string name="masterpassword_create_title">&masterpassword_create_title;</string>
+  <string name="masterpassword_remove_title">&masterpassword_remove_title;</string>
+  <string name="masterpassword_password">&masterpassword_password;</string>
+  <string name="masterpassword_confirm">&masterpassword_confirm;</string>
+
+  <string name="button_ok">&button_ok;</string>
+  <string name="button_cancel">&button_cancel;</string>
 </resources>
--- a/mobile/android/chrome/content/about.xhtml
+++ b/mobile/android/chrome/content/about.xhtml
@@ -84,21 +84,34 @@
       <li><a href="about:rights">&aboutPage.rights.label;</a></li>
       <li><a id="releaseNotesURL">&aboutPage.relNotes.label;</a></li>
       <li><a id="creditsURL">&aboutPage.credits.label;</a></li>
       <div class="bottom-border"></div>
     </ul>
 
     <div id="aboutDetails">
       <p id="license"><b><a href="about:license">&aboutPage.licenseLink;</a>&aboutPage.licenseLinkSuffix;</b> &logoTrademark;</p>
-      <p id="aboutUA"/>
     </div>
 
     <script type="application/javascript;version=1.8"><![CDATA[
       let Ci = Components.interfaces, Cc = Components.classes, Cu = Components.utils, Cr = Components.results;
+      Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+      Cu.import("resource://gre/modules/Services.jsm");
+
+      // Include the build date if this is an "a#" (nightly or aurora) build
+#expand const version = "__MOZ_APP_VERSION__";
+      if (/a\d+$/.test(version)) {
+        let buildID = Services.appinfo.appBuildID;
+        let buildDate = buildID.slice(0,4) + "-" + buildID.slice(4,6) + "-" + buildID.slice(6,8);
+        let br = document.createElement("br");
+        let versionPara = document.getElementById("version");
+        versionPara.appendChild(br);
+        let date = document.createTextNode("(" + buildDate + ")");
+        versionPara.appendChild(date);
+      }
 
       // get URLs from prefs
       try {
         let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
 
         let links = [
           {id: "releaseNotesURL", pref: "app.releaseNotesURL"},
           {id: "supportURL",      pref: "app.support.baseURL"},
@@ -109,25 +122,16 @@
 
         links.forEach(function (link) {
           let url = formatter.formatURLPref(link.pref);
           let element = document.getElementById(link.id);
           element.setAttribute("href", url);
         });
       } catch (ex) {}
 
-      let ua = navigator.userAgent;
-      if (ua) {
-        let uaP = document.getElementById("aboutUA");
-        uaP.appendChild(document.createTextNode(ua));
-      }
-
-      Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-      Cu.import("resource://gre/modules/Services.jsm");
-
 #ifdef MOZ_UPDATER
       let Updater = {
         isChecking: false,
         update: null,
 
         get updateEnabled() {
           try {
             return Services.prefs.getBoolPref("app.update.enabled");
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -485,16 +485,22 @@ var BrowserApp = {
         // The plugin pref is actually two separate prefs, so
         // we need to handle it differently
         if (prefName == "plugin.enable") {
           // Use a string type for java's ListPreference
           pref.type = "string";
           pref.value = PluginHelper.getPluginPreference();
           prefs.push(pref);
           continue;
+        } else if (prefName == MasterPassword.pref) {
+          // Master password is not a "real" pref
+          pref.type = "bool";
+          pref.value = MasterPassword.enabled;
+          prefs.push(pref);
+          continue;
         }
 
         try {
           switch (Services.prefs.getPrefType(prefName)) {
             case Ci.nsIPrefBranch.PREF_BOOL:
               pref.type = "bool";
               pref.value = Services.prefs.getBoolPref(prefName);
               break;
@@ -547,16 +553,21 @@ var BrowserApp = {
   setPreferences: function setPreferences(aPref) {
     let json = JSON.parse(aPref);
 
     // The plugin pref is actually two separate prefs, so
     // we need to handle it differently
     if (json.name == "plugin.enable") {
       PluginHelper.setPluginPreference(json.value);
       return;
+    } else if(json.name == MasterPassword.pref) {
+      if (MasterPassword.enabled)
+        MasterPassword.removePassword(json.value);
+      else
+        MasterPassword.setPassword(json.value);
     }
 
     // when sending to java, we normalized special preferences that use
     // integers and strings to represent booleans.  here, we convert them back
     // to their actual types so we can store them.
     switch (json.name) {
       case "network.cookie.cookieBehavior":
         json.type = "int";
@@ -1510,18 +1521,18 @@ Tab.prototype = {
           this._pluginOverlayShowing = false;
         }
         break;
       }
     }
   },
 
   onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
-    if (aStateFlags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT) {
-      // Filter optimization: Only really send DOCUMENT state changes to Java listener
+    if (aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) {
+      // Filter optimization: Only really send NETWORK state changes to Java listener
       let browser = BrowserApp.getBrowserForWindow(aWebProgress.DOMWindow);
       let uri = "";
       if (browser)
         uri = browser.currentURI.spec;
 
       let message = {
         gecko: {
           type: "Content:StateChange",
@@ -3478,8 +3489,86 @@ var PermissionsHelper = {
       }
       // Re-set login saving to enabled
       Services.logins.setLoginSavingEnabled(aURI.prePath, true);
     } else {
       Services.perms.remove(aURI.host, aType);
     }
   }
 }
+
+var MasterPassword = {
+  pref: "privacy.masterpassword.enabled",
+  get _secModuleDB() {
+    delete this._secModuleDB;
+    return this._secModuleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(Ci.nsIPKCS11ModuleDB);
+  },
+
+  get _pk11DB() {
+    delete this._pk11DB;
+    return this._pk11DB = Cc["@mozilla.org/security/pk11tokendb;1"].getService(Ci.nsIPK11TokenDB);
+  },
+
+  get enabled() {
+    let slot = this._secModuleDB.findSlotByName(this._tokenName);
+    if (slot) {
+      let status = slot.status;
+      return status != Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED && status != Ci.nsIPKCS11Slot.SLOT_READY;
+    }
+    return false;
+  },
+
+  setPassword: function setPassword(aPassword) {
+    try {
+      let status;
+      let slot = this._secModuleDB.findSlotByName(this._tokenName);
+      if (slot)
+        status = slot.status;
+      else
+        return false;
+
+      let token = this._pk11DB.findTokenByName(this._tokenName);
+
+      if (status == Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED)
+        token.initPassword(aPassword);
+      else if (status == Ci.nsIPKCS11Slot.SLOT_READY)
+        token.changePassword("", aPassword);
+
+      this.updatePref();
+      return true;
+    } catch(e) {
+      dump("MasterPassword.setPassword: " + e);
+    }
+    return false;
+  },
+
+  removePassword: function removePassword(aOldPassword) {
+    try {
+      let token = this._pk11DB.getInternalKeyToken();
+      if (token.checkPassword(aOldPassword)) {
+        token.changePassword(aOldPassword, "");
+        this.updatePref();
+        return true;
+      }
+    } catch(e) {
+      dump("MasterPassword.removePassword: " + e + "\n");
+    }
+    NativeWindow.toast.show(Strings.browser.GetStringFromName("masterPassword.incorrect"), "short");
+    return false;
+  },
+
+  updatePref: function() {
+    var prefs = [];
+    let pref = {
+      name: this.pref,
+      type: "bool",
+      value: this.enabled
+    };
+    prefs.push(pref);
+
+    sendMessageToJava({
+      gecko: {
+        type: "Preferences:Data",
+        preferences: prefs
+      }
+    });
+  }
+}
--- a/mobile/android/chrome/content/config.xhtml
+++ b/mobile/android/chrome/content/config.xhtml
@@ -48,25 +48,25 @@
 <head>
   <meta name="viewport" content="width=480; initial-scale=.6667; user-scalable=0" />
   <link rel="stylesheet" href="chrome://browser/skin/config.css" type="text/css"/>
 </head>
 
 <body dir="&locale.dir;" onload="AboutConfig.init();" onunload="AboutConfig.uninit();">
 
   <div id="filter-container">
-    <input id="filter-input" type="search" placeholder="&search.placeholder;"
+    <input id="filter-input" type="search" placeholder="&search.placeholder2;"
            onchange="AboutConfig.filter_onchange();"/>
     <input id="clear-input" type="image" disabled="true"
            onclick="AboutConfig.clearInput();" alt="&clear.altText;"
            src="chrome://browser/skin/images/search-clear-30.png"/>
   </div>
 
   <div id="new-pref-container">
-    <button id="new-pref-button" onclick="AboutConfig.addNewPref();">&newpref.label;</button>
+    <button id="new-pref-button" onclick="AboutConfig.addNewPref();">&newpref.label2;</button>
   </div>
 
   <div id="prefs-container"/>
 
   <script type="application/javascript;version=1.8"><![CDATA[
     const {classes: Cc, interfaces: Ci, manager: Cm, utils: Cu} = Components;
     Cu.import("resource://gre/modules/Services.jsm");
 
--- a/mobile/android/components/PromptService.js
+++ b/mobile/android/components/PromptService.js
@@ -323,17 +323,17 @@ Prompt.prototype = {
       aCheckState.value = data.checkbox == "true";
     if (data.textbox)
       aValue.value = data.textbox;
     return (data.button == 0);
   },
 
   nsIPrompt_promptPassword: function nsIPrompt_promptPassword(
       aTitle, aText, aPassword, aCheckMsg, aCheckState) {
-    let inputs = [{ type: "password", hint: "Password", value: aPassword.value }];
+    let inputs = [{ type: "password", hint: "Password", value: aPassword.value || "" }];
     let data = this.commonPrompt(aTitle, aText, null, aCheckMsg, aCheckState, inputs);
 
     if (aCheckMsg)
       aCheckState.value = data.checkbox == "true";
     if (data.password)
       aPassword.value = data.password;
     return (data.button == 0);
   },
--- a/mobile/android/locales/en-US/chrome/browser.properties
+++ b/mobile/android/locales/en-US/chrome/browser.properties
@@ -209,8 +209,10 @@ clickToPlayPlugins.message=This page con
 clickToPlayPlugins.yes=Yes
 clickToPlayPlugins.no=No
 
 # Site settings dialog
 # LOCALIZATION NOTE (siteSettings.labelToValue): This string will be used to
 # dislay a list of current permissions settings for a site.
 # Example: "Store Offline Data: Allow"
 siteSettings.labelToValue=%S: %S
+
+masterPassword.incorrect=Incorrect password
--- a/mobile/android/locales/en-US/chrome/config.dtd
+++ b/mobile/android/locales/en-US/chrome/config.dtd
@@ -1,3 +1,3 @@
-<!ENTITY search.placeholder     "Search Preferences">
+<!ENTITY search.placeholder2    "Search Settings">
 <!ENTITY clear.altText          "Clear">
-<!ENTITY newpref.label          "Add a New Preference">
+<!ENTITY newpref.label2         "Add a New Setting">
--- a/modules/libjar/nsZipArchive.h
+++ b/modules/libjar/nsZipArchive.h
@@ -38,16 +38,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsZipArchive_h_
 #define nsZipArchive_h_
 
+#include "mozilla/Attributes.h"
+
 #define ZIP_TABSIZE   256
 #define ZIP_BUFLEN    (4*1024)      /* Used as output buffer when deflating items to a file */
 
 #ifndef PL_ARENA_CONST_ALIGN_MASK
 #define PL_ARENA_CONST_ALIGN_MASK  (sizeof(void*)-1)
 #endif
 #include "plarena.h"
 
@@ -245,24 +247,25 @@ private:
   bool          mBuiltSynthetics;
 
   // file handle
   nsRefPtr<nsZipHandle> mFd;
 
   // logging handle
   mozilla::AutoFDClose mLog;
 
+
+private:
   //--- private methods ---
-  
-  nsZipArchive& operator=(const nsZipArchive& rhs); // prevent assignments
-  nsZipArchive(const nsZipArchive& rhs);            // prevent copies
-
   nsZipItem*        CreateZipItem();
   nsresult          BuildFileList();
   nsresult          BuildSynthetics();
+
+  nsZipArchive& operator=(const nsZipArchive& rhs) MOZ_DELETE;
+  nsZipArchive(const nsZipArchive& rhs) MOZ_DELETE;
 };
 
 /** 
  * nsZipFind 
  *
  * a helper class for nsZipArchive, representing a search
  */
 class nsZipFind
@@ -275,19 +278,18 @@ public:
 
 private:
   nsRefPtr<nsZipArchive> mArchive;
   char*         mPattern;
   nsZipItem*    mItem;
   PRUint16      mSlot;
   bool          mRegExp;
 
-  //-- prevent copies and assignments
-  nsZipFind& operator=(const nsZipFind& rhs);
-  nsZipFind(const nsZipFind& rhs);
+  nsZipFind& operator=(const nsZipFind& rhs) MOZ_DELETE;
+  nsZipFind(const nsZipFind& rhs) MOZ_DELETE;
 };
 
 /** 
  * nsZipCursor -- a low-level class for reading the individual items in a zip.
  */
 class nsZipCursor {
 public:
   /**
--- a/other-licenses/android/APKOpen.cpp
+++ b/other-licenses/android/APKOpen.cpp
@@ -294,16 +294,18 @@ SHELL_WRAPPER3(callObserver, jstring, js
 SHELL_WRAPPER1(removeObserver, jstring)
 SHELL_WRAPPER1(onChangeNetworkLinkStatus, jstring)
 SHELL_WRAPPER1(reportJavaCrash, jstring)
 SHELL_WRAPPER0(executeNextRunnable)
 SHELL_WRAPPER1(cameraCallbackBridge, jbyteArray)
 SHELL_WRAPPER1(notifyUriVisited, jstring)
 SHELL_WRAPPER3(notifyBatteryChange, jdouble, jboolean, jdouble);
 SHELL_WRAPPER3(notifySmsReceived, jstring, jstring, jlong);
+SHELL_WRAPPER0(bindWidgetTexture);
+SHELL_WRAPPER0_WITH_RETURN(testDirectTexture, bool);
 
 static void * xul_handle = NULL;
 static time_t apk_mtime = 0;
 #ifdef DEBUG
 extern "C" int extractLibs = 1;
 #else
 extern "C" int extractLibs = 0;
 #endif
@@ -633,17 +635,17 @@ loadLibs(const char *apkName)
   struct stat status;
   if (!stat(apkName, &status))
     apk_mtime = status.st_mtime;
 
   struct timeval t0, t1;
   gettimeofday(&t0, 0);
   struct rusage usage1;
   getrusage(RUSAGE_THREAD, &usage1);
-
+  
   void *zip = map_file(apkName);
   struct cdir_end *dirend = (struct cdir_end *)((char *)zip + zip_size - sizeof(*dirend));
   while ((void *)dirend > zip &&
          letoh32(dirend->signature) != CDIR_END_SIG)
     dirend = (struct cdir_end *)((char *)dirend - 1);
   if (letoh32(dirend->signature) != CDIR_END_SIG) {
     __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't find end of central directory record");
     return;
@@ -699,16 +701,18 @@ loadLibs(const char *apkName)
   GETFUNC(removeObserver);
   GETFUNC(onChangeNetworkLinkStatus);
   GETFUNC(reportJavaCrash);
   GETFUNC(executeNextRunnable);
   GETFUNC(cameraCallbackBridge);
   GETFUNC(notifyUriVisited);
   GETFUNC(notifyBatteryChange);
   GETFUNC(notifySmsReceived);
+  GETFUNC(bindWidgetTexture);
+  GETFUNC(testDirectTexture);
 #undef GETFUNC
   sStartupTimeline = (uint64_t *)__wrap_dlsym(xul_handle, "_ZN7mozilla15StartupTimeline16sStartupTimelineE");
   gettimeofday(&t1, 0);
   struct rusage usage2;
   getrusage(RUSAGE_THREAD, &usage2);
   __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loaded libs in %dms total, %dms user, %dms system, %d faults",
                       (t1.tv_sec - t0.tv_sec)*1000 + (t1.tv_usec - t0.tv_usec)/1000, 
                       (usage2.ru_utime.tv_sec - usage1.ru_utime.tv_sec)*1000 + (usage2.ru_utime.tv_usec - usage1.ru_utime.tv_usec)/1000,
--- a/parser/htmlparser/src/nsExpatDriver.cpp
+++ b/parser/htmlparser/src/nsExpatDriver.cpp
@@ -942,23 +942,22 @@ nsExpatDriver::HandleError()
 
   nsAutoString sourceText(mLastLine);
   AppendErrorPointer(colNumber, mLastLine.get(), sourceText);
 
   // Try to create and initialize the script error.
   nsCOMPtr<nsIScriptError> serr(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
   nsresult rv = NS_ERROR_FAILURE;
   if (serr) {
-    nsCOMPtr<nsIScriptError2> serr2(do_QueryInterface(serr));
-    rv = serr2->InitWithWindowID(description.get(),
-                                 mURISpec.get(),
-                                 mLastLine.get(),
-                                 lineNumber, colNumber,
-                                 nsIScriptError::errorFlag, "malformed-xml",
-                                 mInnerWindowID);
+    rv = serr->InitWithWindowID(description.get(),
+                                mURISpec.get(),
+                                mLastLine.get(),
+                                lineNumber, colNumber,
+                                nsIScriptError::errorFlag, "malformed-xml",
+                                mInnerWindowID);
   }
 
   // If it didn't initialize, we can't do any logging.
   bool shouldReportError = NS_SUCCEEDED(rv);
 
   if (mSink && shouldReportError) {
     rv = mSink->ReportError(errorText.get(), 
                             sourceText.get(), 
--- a/security/manager/ssl/src/nsRecentBadCerts.h
+++ b/security/manager/ssl/src/nsRecentBadCerts.h
@@ -35,17 +35,19 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __RECENTBADCERTS_H__
 #define __RECENTBADCERTS_H__
 
+#include "mozilla/Attributes.h"
 #include "mozilla/ReentrantMonitor.h"
+
 #include "nsIRecentBadCertsService.h"
 #include "nsTHashtable.h"
 #include "nsString.h"
 #include "secitem.h"
 
 class RecentBadCert
 {
 public:
@@ -75,27 +77,18 @@ public:
 
   nsString mHostWithPort;
   SECItem mDERCert;
   bool isDomainMismatch;
   bool isNotValidAtThisTime;
   bool isUntrusted;
 
 private:
-  RecentBadCert(const RecentBadCert &other)
-  {
-    NS_NOTREACHED("RecentBadCert(const RecentBadCert &other) not implemented");
-    this->operator=(other);
-  }
-
-  RecentBadCert &operator=(const RecentBadCert &other)
-  {
-    NS_NOTREACHED("RecentBadCert &operator=(const RecentBadCert &other) not implemented");
-    return *this;
-  }
+  RecentBadCert(const RecentBadCert &other) MOZ_DELETE;
+  RecentBadCert &operator=(const RecentBadCert &other) MOZ_DELETE;
 };
 
 class nsRecentBadCertsService : public nsIRecentBadCertsService
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIRECENTBADCERTSSERVICE
 
--- a/toolkit/mozapps/extensions/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/XPIProvider.jsm
@@ -7278,19 +7278,20 @@ AddonInternal.prototype = {
    * When an add-on install is pending its metadata will be cached in a file.
    * This method reads particular properties of that metadata that may be newer
    * than that in the install manifest, like compatibility information.
    *
    * @param  aObj
    *         A JS object containing the cached metadata
    */
   importMetadata: function(aObj) {
-    ["targetApplications", "userDisabled", "softDisabled", "existingAddonID",
-     "sourceURI", "releaseNotesURI", "installDate", "updateDate",
-     "applyBackgroundUpdates", "compatibilityOverrides"].forEach(function(aProp) {
+    ["syncGUID", "targetApplications", "userDisabled", "softDisabled",
+     "existingAddonID", "sourceURI", "releaseNotesURI", "installDate",
+     "updateDate", "applyBackgroundUpdates", "compatibilityOverrides"]
+    .forEach(function(aProp) {
       if (!(aProp in aObj))
         return;
 
       this[aProp] = aObj[aProp];
     }, this);
 
     // Compatibility info may have changed so update appDisabled
     this.appDisabled = !isUsableAddon(this);
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -372,17 +372,18 @@ var gEventManager = {
       menuSep.hidden = (countEnabledMenuCmds <= 1);
       
     }, false);
   },
 
   shutdown: function() {
     Services.prefs.removeObserver(PREF_CHECK_COMPATIBILITY, this);
     Services.prefs.removeObserver(PREF_CHECK_UPDATE_SECURITY, this);
-    Services.prefs.removeObserver(PREF_AUTOUPDATE_DEFAULT, this, false);
+    Services.prefs.removeObserver(PREF_UPDATE_ENABLED, this);
+    Services.prefs.removeObserver(PREF_AUTOUPDATE_DEFAULT, this);
 
     AddonManager.removeInstallListener(this);
     AddonManager.removeAddonListener(this);
   },
 
   registerAddonListener: function(aListener, aAddonId) {
     if (!(aAddonId in this._listeners))
       this._listeners[aAddonId] = [];
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js
@@ -144,16 +144,17 @@ function run_test_1() {
   AddonManager.getInstallForFile(do_get_addon("test_bootstrap1_1"), function(install) {
     ensure_test_completed();
 
     do_check_neq(install, null);
     do_check_eq(install.type, "extension");
     do_check_eq(install.version, "1.0");
     do_check_eq(install.name, "Test Bootstrap 1");
     do_check_eq(install.state, AddonManager.STATE_DOWNLOADED);
+    do_check_neq(install.addon.syncGUID, null);
     do_check_true(install.addon.hasResource("install.rdf"));
     do_check_true(install.addon.hasResource("bootstrap.js"));
     do_check_false(install.addon.hasResource("foo.bar"));
     do_check_eq(install.addon.operationsRequiringRestart &
                 AddonManager.OP_NEEDS_RESTART_INSTALL, 0);
     do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
 
     let addon = install.addon;
@@ -162,38 +163,40 @@ function run_test_1() {
         ["onInstalling", false],
         "onInstalled"
       ]
     }, [
       "onInstallStarted",
       "onInstallEnded",
     ], function() {
       do_check_true(addon.hasResource("install.rdf"));
-      check_test_1();
+      check_test_1(addon.syncGUID);
     });
     install.install();
   });
 }
 
-function check_test_1() {
+function check_test_1(installSyncGUID) {
   let file = gProfD.clone();
   file.append("extensions.sqlite");
   do_check_true(file.exists());
 
   file.leafName = "extensions.ini";
   do_check_false(file.exists());
 
   AddonManager.getAllInstalls(function(installs) {
     // There should be no active installs now since the install completed and
     // doesn't require a restart.
     do_check_eq(installs.length, 0);
 
     AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
       do_check_neq(b1, null);
       do_check_eq(b1.version, "1.0");
+      do_check_neq(b1.syncGUID, null);
+      do_check_eq(b1.syncGUID, installSyncGUID);
       do_check_false(b1.appDisabled);
       do_check_false(b1.userDisabled);
       do_check_true(b1.isActive);
       do_check_eq(getInstalledVersion(), 1);
       do_check_eq(getActiveVersion(), 1);
       do_check_eq(getStartupReason(), ADDON_INSTALL);
       do_check_true(b1.hasResource("install.rdf"));
       do_check_true(b1.hasResource("bootstrap.js"));
--- a/toolkit/mozapps/extensions/test/xpcshell/test_install.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_install.js
@@ -100,25 +100,27 @@ function run_test_1() {
 
           prepare_test({
             "addon1@tests.mozilla.org": [
               "onInstalling"
             ]
           }, [
             "onInstallStarted",
             "onInstallEnded",
-          ], check_test_1);
+          ], function() {
+            check_test_1(install.addon.syncGUID);
+          });
           install.install();
         });
       });
     });
   });
 }
 
-function check_test_1() {
+function check_test_1(installSyncGUID) {
   ensure_test_completed();
   AddonManager.getAddonByID("addon1@tests.mozilla.org", function(olda1) {
     do_check_eq(olda1, null);
 
     AddonManager.getAddonsWithOperationsByTypes(null, function(pendingAddons) {
       do_check_eq(pendingAddons.length, 1);
       do_check_eq(pendingAddons[0].id, "addon1@tests.mozilla.org");
       let uri = NetUtil.newURI(pendingAddons[0].iconURL);
@@ -155,16 +157,17 @@ function check_test_1() {
 
       AddonManager.getAllInstalls(function(activeInstalls) {
         do_check_eq(activeInstalls, 0);
 
         AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
           do_check_neq(a1, null);
           do_check_neq(a1.syncGUID, null);
           do_check_true(a1.syncGUID.length >= 9);
+          do_check_eq(a1.syncGUID, installSyncGUID);
           do_check_eq(a1.type, "extension");
           do_check_eq(a1.version, "1.0");
           do_check_eq(a1.name, "Test 1");
           do_check_true(isExtensionInAddonsList(profileDir, a1.id));
           do_check_true(do_get_addon("test_install1").exists());
           do_check_in_crash_annotation(a1.id, a1.version);
           do_check_eq(a1.size, ADDON1_SIZE);
           do_check_false(a1.foreignInstall);
new file mode 100644
--- /dev/null
+++ b/widget/src/android/AndroidDirectTexture.cpp
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   James Willcox <jwillcox@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "AndroidDirectTexture.h"
+
+typedef gfxASurface::gfxImageFormat gfxImageFormat;
+
+namespace mozilla {
+
+AndroidDirectTexture::AndroidDirectTexture(PRUint32 width, PRUint32 height, PRUint32 usage,
+                                           gfxImageFormat format) :
+    mLock("AndroidDirectTexture.mLock")
+  , mNeedFlip(false)
+  , mWidth(width)
+  , mHeight(height)
+  , mFormat(format)
+  , mPendingReallocBuffer(NULL)
+{
+  mFrontBuffer = new AndroidGraphicBuffer(width, height, usage, format);
+  mBackBuffer = new AndroidGraphicBuffer(width, height, usage, format);
+}
+
+AndroidDirectTexture::~AndroidDirectTexture()
+{
+  if (mFrontBuffer) {
+    delete mFrontBuffer;
+    mFrontBuffer = NULL;
+  }
+
+  if (mBackBuffer) {
+    delete mBackBuffer;
+    mBackBuffer = NULL;
+  }
+}
+
+void
+AndroidDirectTexture::ReallocPendingBuffer()
+{
+  // We may have reallocated while the current back buffer was being
+  // used as the front buffer. If we have such a reallocation pending
+  // and the current back buffer is the target buffer, do it now.
+  //
+  // It is assumed that mLock is already acquired
+  if (mPendingReallocBuffer == mBackBuffer) {
+    mBackBuffer->Reallocate(mWidth, mHeight, mFormat);
+    mPendingReallocBuffer = NULL;
+  }
+}
+
+bool
+AndroidDirectTexture::Lock(PRUint32 aUsage, unsigned char **bits)
+{
+  mLock.Lock();
+  ReallocPendingBuffer();
+  return mBackBuffer->Lock(aUsage, bits);
+}
+
+bool
+AndroidDirectTexture::Lock(PRUint32 aUsage, const nsIntRect& aRect, unsigned char **bits)
+{
+  mLock.Lock();
+  ReallocPendingBuffer();
+  return mBackBuffer->Lock(aUsage, aRect, bits);
+}
+
+bool
+AndroidDirectTexture::Unlock(bool aFlip)
+{
+  if (aFlip) {
+    mNeedFlip = true;
+  }
+
+  bool result = mBackBuffer->Unlock();
+  mLock.Unlock();
+
+  return result;
+}
+
+bool
+AndroidDirectTexture::Reallocate(PRUint32 aWidth, PRUint32 aHeight) {
+  return Reallocate(aWidth, aHeight, mFormat);
+}
+
+bool
+AndroidDirectTexture::Reallocate(PRUint32 aWidth, PRUint32 aHeight, gfxASurface::gfxImageFormat aFormat)
+{
+  MutexAutoLock lock(mLock);
+
+  // We only reallocate the current back buffer. The front buffer is likely
+  // in use, so we'll reallocate it on the first Lock() after it is rotated
+  // to the back.
+  bool result = mBackBuffer->Reallocate(aWidth, aHeight, aFormat);
+  if (result) {
+    mPendingReallocBuffer = mFrontBuffer;
+  }
+
+  return result;
+}
+
+bool
+AndroidDirectTexture::Bind()
+{
+  MutexAutoLock lock(mLock);
+
+  if (mNeedFlip) {
+    AndroidGraphicBuffer* tmp = mBackBuffer;
+    mBackBuffer = mFrontBuffer;
+    mFrontBuffer = tmp;
+    mNeedFlip = false;
+  }
+
+  return mFrontBuffer->Bind();
+}
+
+} /* mozilla */
new file mode 100644
--- /dev/null
+++ b/widget/src/android/AndroidDirectTexture.h
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   James Willcox <jwillcox@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef AndroidDirectTexture_h_
+#define AndroidDirectTexture_h_
+
+#include "gfxASurface.h"
+#include "nsRect.h"
+#include "mozilla/Mutex.h"
+#include "AndroidGraphicBuffer.h"
+
+namespace mozilla {
+
+/**
+ * This is a thread safe wrapper around AndroidGraphicBuffer that handles
+ * double buffering. Each call to Bind() flips the buffer when necessary.
+ *
+ * You need to be careful when destroying an instance of this class. If either
+ * buffer is locked by the application of the driver/hardware, bad things will
+ * happen. Be sure that the OpenGL texture is no longer on the screen.
+ */
+class AndroidDirectTexture
+{
+public:
+  AndroidDirectTexture(PRUint32 width, PRUint32 height, PRUint32 usage, gfxASurface::gfxImageFormat format);
+  virtual ~AndroidDirectTexture();
+
+  bool Lock(PRUint32 usage, unsigned char **bits);
+  bool Lock(PRUint32 usage, const nsIntRect& rect, unsigned char **bits);
+  bool Unlock(bool aFlip = true);
+
+  bool Reallocate(PRUint32 aWidth, PRUint32 aHeight);
+  bool Reallocate(PRUint32 aWidth, PRUint32 aHeight, gfxASurface::gfxImageFormat aFormat);
+
+  PRUint32 Width() { return mWidth; }
+  PRUint32 Height() { return mHeight; }
+
+  bool Bind();
+
+private:
+  mozilla::Mutex mLock;
+  bool mNeedFlip;
+
+  PRUint32 mWidth;
+  PRUint32 mHeight;
+  gfxASurface::gfxImageFormat mFormat;
+
+  AndroidGraphicBuffer* mFrontBuffer;
+  AndroidGraphicBuffer* mBackBuffer;
+
+  AndroidGraphicBuffer* mPendingReallocBuffer;
+  void ReallocPendingBuffer();
+};
+
+} /* mozilla */
+#endif /* AndroidDirectTexture_h_ */
new file mode 100644
--- /dev/null
+++ b/widget/src/android/AndroidGraphicBuffer.cpp
@@ -0,0 +1,450 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   James Willcox <jwillcox@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <dlfcn.h>
+#include <android/log.h>
+#include <GLES2/gl2.h>
+#include "AndroidGraphicBuffer.h"
+
+#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "AndroidGraphicBuffer" , ## args)
+
+#define EGL_NATIVE_BUFFER_ANDROID 0x3140
+#define EGL_IMAGE_PRESERVED_KHR   0x30D2
+
+typedef void* EGLContext;
+typedef void* EGLImageKHR;
+typedef void* EGLClientBuffer;
+typedef void* EGLDisplay;
+
+typedef PRUint32 EGLenum;
+typedef PRInt32 EGLint;
+typedef PRUint32 EGLBoolean;
+
+typedef gfxASurface::gfxImageFormat gfxImageFormat;
+
+#define EGL_TRUE 1
+#define EGL_FALSE 0
+#define EGL_NONE 0x3038
+#define EGL_NO_CONTEXT (EGLContext)0
+#define EGL_DEFAULT_DISPLAY  (void*)0
+
+#define ANDROID_LIBUI_PATH "/system/lib/libui.so"
+#define ANDROID_GLES_PATH "/system/lib/libGLESv2.so"
+#define ANDROID_EGL_PATH "/system/lib/libEGL.so"
+
+// Really I have no idea, but this should be big enough
+#define GRAPHIC_BUFFER_SIZE 1024
+
+enum {
+    /* buffer is never read in software */
+    GRALLOC_USAGE_SW_READ_NEVER   = 0x00000000,
+    /* buffer is rarely read in software */
+    GRALLOC_USAGE_SW_READ_RARELY  = 0x00000002,
+    /* buffer is often read in software */
+    GRALLOC_USAGE_SW_READ_OFTEN   = 0x00000003,
+    /* mask for the software read values */
+    GRALLOC_USAGE_SW_READ_MASK    = 0x0000000F,
+
+    /* buffer is never written in software */
+    GRALLOC_USAGE_SW_WRITE_NEVER  = 0x00000000,
+    /* buffer is never written in software */
+    GRALLOC_USAGE_SW_WRITE_RARELY = 0x00000020,
+    /* buffer is never written in software */
+    GRALLOC_USAGE_SW_WRITE_OFTEN  = 0x00000030,
+    /* mask for the software write values */
+    GRALLOC_USAGE_SW_WRITE_MASK   = 0x000000F0,
+
+    /* buffer will be used as an OpenGL ES texture */
+    GRALLOC_USAGE_HW_TEXTURE      = 0x00000100,
+    /* buffer will be used as an OpenGL ES render target */
+    GRALLOC_USAGE_HW_RENDER       = 0x00000200,
+    /* buffer will be used by the 2D hardware blitter */
+    GRALLOC_USAGE_HW_2D           = 0x00000400,
+    /* buffer will be used with the framebuffer device */
+    GRALLOC_USAGE_HW_FB           = 0x00001000,
+    /* mask for the software usage bit-mask */
+    GRALLOC_USAGE_HW_MASK         = 0x00001F00,
+};
+
+enum {
+    HAL_PIXEL_FORMAT_RGBA_8888          = 1,
+    HAL_PIXEL_FORMAT_RGBX_8888          = 2,
+    HAL_PIXEL_FORMAT_RGB_888            = 3,
+    HAL_PIXEL_FORMAT_RGB_565            = 4,
+    HAL_PIXEL_FORMAT_BGRA_8888          = 5,
+    HAL_PIXEL_FORMAT_RGBA_5551          = 6,
+    HAL_PIXEL_FORMAT_RGBA_4444          = 7,
+};
+
+typedef struct AndroidRect {
+    int32_t left;
+    int32_t top;
+    int32_t right;
+    int32_t bottom;
+} AndroidRect;
+
+static bool gTryRealloc = true;
+
+static class GLFunctions
+{
+public:
+  GLFunctions() : mInitialized(false)
+  {
+  }
+
+  typedef EGLDisplay (* pfnGetDisplay)(void *display_id);
+  pfnGetDisplay fGetDisplay;
+  typedef EGLint (* pfnEGLGetError)(void);
+  pfnEGLGetError fEGLGetError;
+
+  typedef EGLImageKHR (* pfnCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+  pfnCreateImageKHR fCreateImageKHR;
+  typedef EGLBoolean (* pfnDestroyImageKHR)(EGLDisplay dpy, EGLImageKHR image);
+  pfnDestroyImageKHR fDestroyImageKHR;
+
+  typedef void (* pfnImageTargetTexture2DOES)(GLenum target, EGLImageKHR image);
+  pfnImageTargetTexture2DOES fImageTargetTexture2DOES;
+
+  typedef void (* pfnBindTexture)(GLenum target, GLuint texture);
+  pfnBindTexture fBindTexture;
+
+  typedef GLenum (* pfnGLGetError)();
+  pfnGLGetError fGLGetError;
+
+  typedef void (*pfnGraphicBufferCtor)(void*, PRUint32 w, PRUint32 h, PRUint32 format, PRUint32 usage);
+  pfnGraphicBufferCtor fGraphicBufferCtor;
+
+  typedef void (*pfnGraphicBufferDtor)(void*);
+  pfnGraphicBufferDtor fGraphicBufferDtor;
+
+  typedef int (*pfnGraphicBufferLock)(void*, PRUint32 usage, unsigned char **addr);
+  pfnGraphicBufferLock fGraphicBufferLock;
+
+  typedef int (*pfnGraphicBufferLockRect)(void*, PRUint32 usage, const AndroidRect&, unsigned char **addr);
+  pfnGraphicBufferLockRect fGraphicBufferLockRect;
+
+  typedef int (*pfnGraphicBufferUnlock)(void*);
+  pfnGraphicBufferUnlock fGraphicBufferUnlock;
+
+  typedef void* (*pfnGraphicBufferGetNativeBuffer)(void*);
+  pfnGraphicBufferGetNativeBuffer fGraphicBufferGetNativeBuffer;
+
+  typedef int (*pfnGraphicBufferReallocate)(void*, PRUint32 w, PRUint32 h, PRUint32 format);
+  pfnGraphicBufferReallocate fGraphicBufferReallocate;
+
+  bool EnsureInitialized()
+  {
+    if (mInitialized) {
+      return true;
+    }
+
+    void *handle = dlopen(ANDROID_EGL_PATH, RTLD_LAZY);
+    if (!handle) {
+      LOG("Couldn't load EGL library");
+      return false;
+    }
+
+    fGetDisplay = (pfnGetDisplay)dlsym(handle, "eglGetDisplay");
+    fEGLGetError = (pfnEGLGetError)dlsym(handle, "eglGetError");
+    fCreateImageKHR = (pfnCreateImageKHR)dlsym(handle, "eglCreateImageKHR");
+    fDestroyImageKHR = (pfnDestroyImageKHR)dlsym(handle, "eglDestroyImageKHR");
+
+    if (!fGetDisplay || !fEGLGetError || !fCreateImageKHR || !fDestroyImageKHR) {
+      LOG("Failed to find some EGL functions");
+      return false;
+    }
+
+    handle = dlopen(ANDROID_GLES_PATH, RTLD_LAZY);
+    if (!handle) {
+      LOG("Couldn't load GL library");
+      return false;
+    }
+
+    fImageTargetTexture2DOES = (pfnImageTargetTexture2DOES)dlsym(handle, "glEGLImageTargetTexture2DOES");
+    fBindTexture = (pfnBindTexture)dlsym(handle, "glBindTexture");
+    fGLGetError = (pfnGLGetError)dlsym(handle, "glGetError");
+
+    if (!fImageTargetTexture2DOES || !fBindTexture || !fGLGetError) {
+      LOG("Failed to find some GL functions");
+      return false;
+    }
+
+    handle = dlopen(ANDROID_LIBUI_PATH, RTLD_LAZY);
+    if (!handle) {
+      LOG("Couldn't load libui.so");
+      return false;
+    }
+
+    fGraphicBufferCtor = (pfnGraphicBufferCtor)dlsym(handle, "_ZN7android13GraphicBufferC1Ejjij");
+    fGraphicBufferDtor = (pfnGraphicBufferDtor)dlsym(handle, "_ZN7android13GraphicBufferD1Ev");
+    fGraphicBufferLock = (pfnGraphicBufferLock)dlsym(handle, "_ZN7android13GraphicBuffer4lockEjPPv");
+    fGraphicBufferLockRect = (pfnGraphicBufferLockRect)dlsym(handle, "_ZN7android13GraphicBuffer4lockEjRKNS_4RectEPPv");
+    fGraphicBufferUnlock = (pfnGraphicBufferUnlock)dlsym(handle, "_ZN7android13GraphicBuffer6unlockEv");
+    fGraphicBufferGetNativeBuffer = (pfnGraphicBufferGetNativeBuffer)dlsym(handle, "_ZNK7android13GraphicBuffer15getNativeBufferEv");
+    fGraphicBufferReallocate = (pfnGraphicBufferReallocate)dlsym(handle, "_ZN7android13GraphicBuffer10reallocateEjjij");
+
+    if (!fGraphicBufferCtor || !fGraphicBufferDtor || !fGraphicBufferLock ||
+        !fGraphicBufferUnlock || !fGraphicBufferGetNativeBuffer) {
+      LOG("Failed to lookup some GraphicBuffer functions");
+      return false;
+    }
+
+    mInitialized = true;
+    return true;
+  }
+
+private:
+  bool mInitialized;
+
+} sGLFunctions;
+
+namespace mozilla {
+
+static bool ensureNoGLError(const char* name)
+{
+  bool result = true;
+  GLuint error;
+
+  while ((error = glGetError()) != GL_NO_ERROR) {
+    LOG("GL error [%s]: %40x\n", name, error);
+    result = false;
+  }
+
+  return result;
+}
+
+AndroidGraphicBuffer::AndroidGraphicBuffer(PRUint32 width, PRUint32 height, PRUint32 usage,
+                                           gfxImageFormat format) :
+    mWidth(width)
+  , mHeight(height)
+  , mUsage(usage)
+  , mFormat(format)
+  , mHandle(0)
+  , mEGLImage(0)
+{
+}
+
+AndroidGraphicBuffer::~AndroidGraphicBuffer()
+{
+  DestroyBuffer();
+}
+
+void
+AndroidGraphicBuffer::DestroyBuffer()
+{
+  /**
+   * XXX: eglDestroyImageKHR crashes sometimes due to refcount badness (I think)
+   *
+   * If you look at egl.cpp (https://github.com/android/platform_frameworks_base/blob/master/opengl/libagl/egl.cpp#L2002)
+   * you can see that eglCreateImageKHR just refs the native buffer, and eglDestroyImageKHR
+   * just unrefs it. Somehow the ref count gets messed up and things are already destroyed
+   * by the time eglDestroyImageKHR gets called. For now, at least, just not calling
+   * eglDestroyImageKHR should be fine since we do free the GraphicBuffer below.
+   *
+   * Bug 712716
+   */
+#if 0
+  if (mEGLImage) {
+    if (sGLFunctions.EnsureInitialized()) {
+      sGLFunctions.fDestroyImageKHR(sGLFunctions.fGetDisplay(EGL_DEFAULT_DISPLAY), mEGLImage);
+      mEGLImage = NULL;
+    }
+  }
+#endif
+  mEGLImage = NULL;
+
+  if (mHandle) {
+    if (sGLFunctions.EnsureInitialized()) {
+      sGLFunctions.fGraphicBufferDtor(mHandle);
+    }
+    free(mHandle);
+    mHandle = NULL;
+  }
+
+}
+
+bool
+AndroidGraphicBuffer::EnsureBufferCreated(PRUint32 aWidth, PRUint32 aHeight, PRUint32 aUsage, gfxImageFormat aFormat)
+{
+  if (!mHandle) {
+    mHandle = malloc(GRAPHIC_BUFFER_SIZE);
+    sGLFunctions.fGraphicBufferCtor(mHandle, mWidth, mHeight, GetAndroidFormat(aFormat), GetAndroidUsage(aUsage));
+  }
+
+  return true;
+}
+
+bool
+AndroidGraphicBuffer::EnsureInitialized()
+{
+  if (!sGLFunctions.EnsureInitialized()) {
+    return false;
+  }
+
+  EnsureBufferCreated(mWidth, mHeight, mUsage, mFormat);
+  return true;
+}
+
+bool
+AndroidGraphicBuffer::Lock(PRUint32 aUsage, unsigned char **bits)
+{
+  if (!EnsureInitialized())
+    return true;
+
+  return sGLFunctions.fGraphicBufferLock(mHandle, GetAndroidUsage(aUsage), bits) == 0;
+}
+
+bool
+AndroidGraphicBuffer::Lock(PRUint32 aUsage, const nsIntRect& aRect, unsigned char **bits)
+{
+  if (!EnsureInitialized())
+    return false;
+
+  AndroidRect rect;
+  rect.left = aRect.x;
+  rect.top = aRect.y;
+  rect.right = aRect.x + aRect.width;
+  rect.bottom = aRect.y + aRect.height;
+
+  return sGLFunctions.fGraphicBufferLockRect(mHandle, GetAndroidUsage(aUsage), rect, bits) == 0;
+}
+
+bool
+AndroidGraphicBuffer::Unlock()
+{
+  if (!EnsureInitialized())
+    return false;
+
+  return sGLFunctions.fGraphicBufferUnlock(mHandle) == 0;
+}
+
+bool
+AndroidGraphicBuffer::Reallocate(PRUint32 aWidth, PRUint32 aHeight, gfxImageFormat aFormat)
+{
+  if (!EnsureInitialized())
+    return false;
+
+  // Sometimes GraphicBuffer::reallocate just doesn't work. In those cases we'll just allocate a brand
+  // new buffer. If reallocate fails once, never try it again.
+  if (!gTryRealloc || sGLFunctions.fGraphicBufferReallocate(mHandle, aWidth, aHeight, GetAndroidFormat(aFormat)) != 0) {
+    DestroyBuffer();
+    EnsureBufferCreated(aWidth, aHeight, mUsage, aFormat);
+
+    gTryRealloc = false;
+  }
+
+  mWidth = aWidth;
+  mHeight = aHeight;
+  mFormat = aFormat;
+
+  return true;
+}
+
+PRUint32
+AndroidGraphicBuffer::GetAndroidUsage(PRUint32 aUsage)
+{
+  PRUint32 flags = 0;
+
+  if (aUsage & UsageSoftwareRead) {
+    flags |= GRALLOC_USAGE_SW_READ_OFTEN;
+  }
+
+  if (aUsage & UsageSoftwareWrite) {
+    flags |= GRALLOC_USAGE_SW_WRITE_OFTEN;
+  }
+
+  if (aUsage & UsageTexture) {
+    flags |= GRALLOC_USAGE_HW_TEXTURE;
+  }
+
+  if (aUsage & UsageTarget) {
+    flags |= GRALLOC_USAGE_HW_RENDER;
+  }
+
+  if (aUsage & Usage2D) {
+    flags |= GRALLOC_USAGE_HW_2D;
+  }
+
+  return flags;
+}
+
+PRUint32
+AndroidGraphicBuffer::GetAndroidFormat(gfxImageFormat aFormat)
+{
+  switch (aFormat) {
+    case gfxImageFormat::ImageFormatRGB24:
+      return HAL_PIXEL_FORMAT_RGBX_8888;
+    case gfxImageFormat::ImageFormatRGB16_565:
+      return HAL_PIXEL_FORMAT_RGB_565;
+    default:
+      return 0;
+  }
+}
+
+bool
+AndroidGraphicBuffer::EnsureEGLImage()
+{
+  if (mEGLImage)
+    return true;
+
+
+  if (!EnsureInitialized())
+    return false;
+
+  EGLint eglImgAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE };
+  void* nativeBuffer = sGLFunctions.fGraphicBufferGetNativeBuffer(mHandle);
+
+  mEGLImage = sGLFunctions.fCreateImageKHR(sGLFunctions.fGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)nativeBuffer, eglImgAttrs);
+  return mEGLImage != NULL;
+}
+
+bool
+AndroidGraphicBuffer::Bind()
+{
+  if (!EnsureInitialized())
+    return false;
+
+  if (!EnsureEGLImage()) {
+    LOG("No valid EGLImage!");
+    return false;
+  }
+
+  sGLFunctions.fImageTargetTexture2DOES(GL_TEXTURE_2D, mEGLImage);
+  return ensureNoGLError("glEGLImageTargetTexture2DOES");
+}
+
+} /* mozilla */
new file mode 100644
--- /dev/null
+++ b/widget/src/android/AndroidGraphicBuffer.h
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   James Willcox <jwillcox@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef AndroidGraphicBuffer_h_
+#define AndroidGraphicBuffer_h_
+
+#include "gfxASurface.h"
+#include "nsRect.h"
+
+namespace mozilla {
+
+/**
+ * This class allows access to Android's direct texturing mechanism. Locking
+ * the buffer gives you a pointer you can read/write to directly. It is fully
+ * threadsafe, but you probably really want to use the AndroidDirectTexture
+ * class which will handle double buffering.
+ *
+ * In order to use the buffer in OpenGL, just call Bind() and it will attach
+ * to whatever texture is bound to GL_TEXTURE_2D.
+ */
+class AndroidGraphicBuffer
+{
+public:
+  enum {
+    UsageSoftwareRead = 1,
+    UsageSoftwareWrite = 1 << 1,
+    UsageTexture = 1 << 2,
+    UsageTarget = 1 << 3,
+    Usage2D = 1 << 4
+  };
+
+  AndroidGraphicBuffer(PRUint32 width, PRUint32 height, PRUint32 usage, gfxASurface::gfxImageFormat format);
+  virtual ~AndroidGraphicBuffer();
+
+  bool Lock(PRUint32 usage, unsigned char **bits);
+  bool Lock(PRUint32 usage, const nsIntRect& rect, unsigned char **bits);
+  bool Unlock();
+  bool Reallocate(PRUint32 aWidth, PRUint32 aHeight, gfxASurface::gfxImageFormat aFormat);
+
+  PRUint32 Width() { return mWidth; }
+  PRUint32 Height() { return mHeight; }
+
+  bool Bind();
+
+private:
+  PRUint32 mWidth;
+  PRUint32 mHeight;
+  PRUint32 mUsage;
+  gfxASurface::gfxImageFormat mFormat;
+
+  bool EnsureInitialized();
+  bool EnsureEGLImage();
+
+  void DestroyBuffer();
+  bool EnsureBufferCreated(PRUint32 aWidth, PRUint32 aHeight, PRUint32 aUsage, gfxASurface::gfxImageFormat aFormat);
+
+  PRUint32 GetAndroidUsage(PRUint32 aUsage);
+  PRUint32 GetAndroidFormat(gfxASurface::gfxImageFormat aFormat);
+
+  void *mHandle;
+  void *mEGLImage;
+};
+
+} /* mozilla */
+#endif /* AndroidGraphicBuffer_h_ */
--- a/widget/src/android/AndroidJNI.cpp
+++ b/widget/src/android/AndroidJNI.cpp
@@ -35,16 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/Hal.h"
 #include "nsILocalFile.h"
 #include "nsString.h"
 
 #include "AndroidBridge.h"
+#include "AndroidGraphicBuffer.h"
 
 #include <jni.h>
 #include <pthread.h>
 #include <dlfcn.h>
 #include <stdio.h>
 
 #include "nsAppShell.h"
 #include "nsWindow.h"
@@ -83,16 +84,21 @@ extern "C" {
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_callObserver(JNIEnv *, jclass, jstring observerKey, jstring topic, jstring data);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_removeObserver(JNIEnv *jenv, jclass, jstring jObserverKey);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus(JNIEnv *, jclass, jstring status);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_reportJavaCrash(JNIEnv *, jclass, jstring stack);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_executeNextRunnable(JNIEnv *, jclass);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyUriVisited(JNIEnv *, jclass, jstring uri);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyBatteryChange(JNIEnv* jenv, jclass, jdouble, jboolean, jdouble);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifySmsReceived(JNIEnv* jenv, jclass, jstring, jstring, jlong);
+
+#ifdef MOZ_JAVA_COMPOSITOR
+    NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_bindWidgetTexture(JNIEnv* jenv, jclass);
+    NS_EXPORT bool JNICALL Java_org_mozilla_gecko_GeckoAppShell_testDirectTexture(JNIEnv* jenv, jclass);
+#endif
 }
 
 
 /*
  * Incoming JNI methods
  */
 
 NS_EXPORT void JNICALL
@@ -273,8 +279,24 @@ Java_org_mozilla_gecko_GeckoAppShell_not
     };
 
     SmsMessageData message(0, eDeliveryState_Received, nsJNIString(aSender, jenv), EmptyString(),
                            nsJNIString(aBody, jenv), aTimestamp);
 
     nsCOMPtr<nsIRunnable> runnable = new NotifySmsReceivedRunnable(message);
     NS_DispatchToMainThread(runnable);
 }
+
+#ifdef MOZ_JAVA_COMPOSITOR
+
+NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_bindWidgetTexture(JNIEnv* jenv, jclass)
+{
+    nsWindow::BindToTexture();
+}
+
+NS_EXPORT bool JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_testDirectTexture(JNIEnv* jenv, jclass)
+{
+    return nsWindow::HasDirectTexture();
+}
+
+#endif
--- a/widget/src/android/Makefile.in
+++ b/widget/src/android/Makefile.in
@@ -56,16 +56,18 @@ DEFINES += -DMOZ_JAVA_COMPOSITOR
 endif
 
 CPPSRCS	= \
 	GfxInfo.cpp \
 	nsWidgetFactory.cpp \
 	nsAppShell.cpp \
 	AndroidJavaWrappers.cpp \
 	AndroidBridge.cpp \
+	AndroidDirectTexture.cpp \
+	AndroidGraphicBuffer.cpp \
 	AndroidJNI.cpp \
 	nsWindow.cpp \
 	nsLookAndFeel.cpp \
 	nsScreenManagerAndroid.cpp \
 	nsIdleServiceAndroid.cpp \
 	nsClipboard.cpp \
 	nsFilePicker.cpp \
 	nsIMEPicker.cpp \
--- a/widget/src/android/nsWindow.cpp
+++ b/widget/src/android/nsWindow.cpp
@@ -34,16 +34,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include <android/log.h>
 #include <math.h>
+#include <unistd.h>
 
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/unused.h"
 #include "mozilla/Preferences.h"
 
 using mozilla::dom::ContentParent;
 using mozilla::dom::ContentChild;
@@ -87,16 +88,30 @@ NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, n
 // The dimensions of the current android view
 static gfxIntSize gAndroidBounds = gfxIntSize(0, 0);
 static gfxIntSize gAndroidScreenBounds;
 
 #ifdef ACCESSIBILITY
 bool nsWindow::sAccessibilityEnabled = false;
 #endif
 
+#ifdef MOZ_JAVA_COMPOSITOR
+#include "mozilla/Mutex.h"
+#include "nsThreadUtils.h"
+#include "AndroidDirectTexture.h"
+
+static AndroidDirectTexture* sDirectTexture = new AndroidDirectTexture(2048, 2048,
+        AndroidGraphicBuffer::UsageSoftwareWrite | AndroidGraphicBuffer::UsageTexture,
+        gfxASurface::ImageFormatRGB16_565);
+
+static bool sHasDirectTexture = true;
+
+#endif
+
+
 class ContentCreationNotifier;
 static nsCOMPtr<ContentCreationNotifier> gContentCreationNotifier;
 // A helper class to send updates when content processes
 // are created. Currently an update for the screen size is sent.
 class ContentCreationNotifier : public nsIObserver
 {
     NS_DECL_ISUPPORTS
 
@@ -803,16 +818,63 @@ nsWindow::GetThebesSurface()
      * we need a RenderingContext to measure text against.
      */
 
     // XXX this really wants to return already_AddRefed, but this only really gets used
     // on direct assignment to a gfxASurface
     return new gfxImageSurface(gfxIntSize(5,5), gfxImageSurface::ImageFormatRGB24);
 }
 
+#ifdef MOZ_JAVA_COMPOSITOR
+
+void
+nsWindow::BindToTexture()
+{
+    sDirectTexture->Bind();
+}
+
+bool
+nsWindow::HasDirectTexture()
+{
+  // If we already tested, return early
+  if (!sHasDirectTexture)
+    return false;
+
+  AndroidGraphicBuffer* buffer = new AndroidGraphicBuffer(512, 512,
+      AndroidGraphicBuffer::UsageSoftwareWrite | AndroidGraphicBuffer::UsageTexture,
+      gfxASurface::ImageFormatRGB16_565);
+
+  unsigned char* bits = NULL;
+  if (!buffer->Lock(AndroidGraphicBuffer::UsageSoftwareWrite, &bits) || !bits) {
+    ALOG("failed to lock graphic buffer");
+    buffer->Unlock();
+    sHasDirectTexture = false;
+    goto cleanup;
+  }
+
+  if (!buffer->Unlock()) {
+    ALOG("failed to unlock graphic buffer");
+    sHasDirectTexture = false;
+    goto cleanup;
+  }
+
+  if (!buffer->Reallocate(1024, 1024, gfxASurface::ImageFormatRGB16_565)) {
+    ALOG("failed to reallocate graphic buffer");
+    sHasDirectTexture = false;
+    goto cleanup;
+  }
+
+cleanup:
+  delete buffer;
+
+  return sHasDirectTexture;
+}
+
+#endif
+
 void
 nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
 {
     if (!AndroidBridge::Bridge())
         return;
 
     nsWindow *win = TopWindow();
     if (!win)
@@ -1106,36 +1168,62 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
     if (gAndroidBounds.width <= 0 || gAndroidBounds.height <= 0)
         return;
 
     AndroidGeckoSoftwareLayerClient &client =
         AndroidBridge::Bridge()->GetSoftwareLayerClient();
     client.BeginDrawing();
 
     nsAutoString metadata;
-    unsigned char *bits = client.LockBufferBits();
+    unsigned char *bits = NULL;
+    if (sHasDirectTexture) {
+      if ((sDirectTexture->Width() != gAndroidBounds.width ||
+           sDirectTexture->Height() != gAndroidBounds.height) &&
+          gAndroidBounds.width != 0 && gAndroidBounds.height != 0) {
+        sDirectTexture->Reallocate(gAndroidBounds.width, gAndroidBounds.height);
+      }
+
+      sDirectTexture->Lock(AndroidGraphicBuffer::UsageSoftwareWrite, &bits);
+    } else {
+      bits = client.LockBufferBits();
+    }
     if (!bits) {
         ALOG("### Failed to lock buffer");
+
+        if (sHasDirectTexture) {
+          sDirectTexture->Unlock();
+        } else {
+          client.UnlockBuffer();
+        }
     } else {
         nsRefPtr<gfxImageSurface> targetSurface =
             new gfxImageSurface(bits, gfxIntSize(gAndroidBounds.width, gAndroidBounds.height), gAndroidBounds.width * 2,
                                 gfxASurface::ImageFormatRGB16_565);
         if (targetSurface->CairoStatus()) {
             ALOG("### Failed to create a valid surface from the bitmap");
         } else {
-            DrawTo(targetSurface, ae->Rect());
+            if (sHasDirectTexture) {
+              // XXX: lock only the dirty rect above and pass it in here
+              DrawTo(targetSurface);
+            } else {
+              DrawTo(targetSurface, ae->Rect());
+            }
 
             {
                 nsCOMPtr<nsIAndroidDrawMetadataProvider> metadataProvider =
                     AndroidBridge::Bridge()->GetDrawMetadataProvider();
                 if (metadataProvider)
                     metadataProvider->GetDrawMetadata(metadata);
             }
         }
-        client.UnlockBuffer();
+        if (sHasDirectTexture) {
+          sDirectTexture->Unlock();
+        } else {
+          client.UnlockBuffer();
+        }
     }
     client.EndDrawing(ae->Rect(), metadata);
     return;
 #endif
 
     if (!sSurfaceExists) {
         return;
     }
--- a/widget/src/android/nsWindow.h
+++ b/widget/src/android/nsWindow.h
@@ -172,16 +172,21 @@ public:
     gfxASurface* GetThebesSurface();
 
     NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent);
 
 #ifdef ACCESSIBILITY
     static bool sAccessibilityEnabled;
 #endif
 
+#ifdef MOZ_JAVA_COMPOSITOR
+    static void BindToTexture();
+    static bool HasDirectTexture();
+#endif
+
 protected:
     void BringToFront();
     nsWindow *FindTopLevel();
     bool DrawTo(gfxASurface *targetSurface);
     bool DrawTo(gfxASurface *targetSurface, const nsIntRect &aRect);
     bool IsTopLevel();
     void OnIMEAddRange(mozilla::AndroidGeckoEvent *ae);
 
--- a/widget/src/cocoa/nsCocoaWindow.mm
+++ b/widget/src/cocoa/nsCocoaWindow.mm
@@ -996,19 +996,54 @@ NS_IMETHODIMP nsCocoaWindow::Enable(bool
 
 NS_IMETHODIMP nsCocoaWindow::IsEnabled(bool *aState)
 {
   if (aState)
     *aState = true;
   return NS_OK;
 }
 
+#define kWindowPositionSlop 20
+
 NS_IMETHODIMP nsCocoaWindow::ConstrainPosition(bool aAllowSlop,
                                                PRInt32 *aX, PRInt32 *aY)
 {
+  if (!mWindow || ![mWindow screen]) {
+    return NS_OK;
+  }
+
+  nsIntRect screenBounds(
+    nsCocoaUtils::CocoaRectToGeckoRect([[mWindow screen] visibleFrame]));
+
+  if (aAllowSlop) {
+    if (*aX < screenBounds.x - mBounds.width + kWindowPositionSlop) {
+      *aX = screenBounds.x - mBounds.width + kWindowPositionSlop;
+    } else if (*aX >= screenBounds.x + screenBounds.width - kWindowPositionSlop) {
+      *aX = screenBounds.x + screenBounds.width - kWindowPositionSlop;
+    }
+
+    if (*aY < screenBounds.y - mBounds.height + kWindowPositionSlop) {
+      *aY = screenBounds.y - mBounds.height + kWindowPositionSlop;
+    } else if (*aY >= screenBounds.y + screenBounds.height - kWindowPositionSlop) {
+      *aY = screenBounds.y + screenBounds.height - kWindowPositionSlop;
+    }
+  } else {
+    if (*aX < screenBounds.x) {
+      *aX = screenBounds.x;
+    } else if (*aX >= screenBounds.x + screenBounds.width - mBounds.width) {
+      *aX = screenBounds.x + screenBounds.width - mBounds.width;
+    }
+
+    if (*aY < screenBounds.y) {
+      *aY = screenBounds.y;
+    } else if (*aY >= screenBounds.y + screenBounds.height - mBounds.height) {
+      *aY = screenBounds.y + screenBounds.height - mBounds.height;
+    }
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP nsCocoaWindow::Move(PRInt32 aX, PRInt32 aY)
 {
   if (!mWindow || (mBounds.x == aX && mBounds.y == aY))
     return NS_OK;
 
--- a/widget/src/xpwidgets/PuppetWidget.cpp
+++ b/widget/src/xpwidgets/PuppetWidget.cpp
@@ -524,17 +524,17 @@ PuppetWidget::SetCursor(nsCursor aCursor
 nsresult
 PuppetWidget::DispatchPaintEvent()
 {
   NS_ABORT_IF_FALSE(!mDirtyRegion.IsEmpty(), "paint event logic messed up");
 
   nsIntRect dirtyRect = mDirtyRegion.GetBounds();
   nsPaintEvent event(true, NS_PAINT, this);
   event.refPoint.x = dirtyRect.x;
-  event.refPoint.x = dirtyRect.y;
+  event.refPoint.y = dirtyRect.y;
   event.region = mDirtyRegion;
   event.willSendDidPaint = true;
 
   // reset repaint tracking
   mDirtyRegion.SetEmpty();
   mPaintTask.Revoke();
 
   nsEventStatus status;
--- a/xpcom/base/nsAutoRef.h
+++ b/xpcom/base/nsAutoRef.h
@@ -35,16 +35,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsAutoRef_h_
 #define nsAutoRef_h_
 
+#include "mozilla/Attributes.h"
+
 #include "nscore.h" // for nsnull, bool
 
 template <class T> class nsSimpleRef;
 template <class T> class nsAutoRefBase;
 template <class T> class nsReturnRef;
 template <class T> class nsReturningRef;
 
 /**
@@ -637,17 +639,17 @@ protected:
         }
         explicit LocalSimpleRef(RawRef aRawRef)
             : SimpleRef(aRawRef)
         {
         }
     };
 
 private:
-    ThisClass& operator=(const ThisClass& aSmartRef);
+    ThisClass& operator=(const ThisClass& aSmartRef) MOZ_DELETE;
     
 public:
     RawRef operator->() const
     {
         return this->get();
     }
 
     // Transfer ownership to a raw reference.
--- a/xpcom/base/nsSystemInfo.cpp
+++ b/xpcom/base/nsSystemInfo.cpp
@@ -48,17 +48,17 @@
 #ifdef MOZ_WIDGET_GTK2
 #include <gtk/gtk.h>
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidBridge.h"
 
 extern "C" {
-extern int android_sdk_version;
+NS_EXPORT int android_sdk_version;
 }
 #endif
 
 using namespace mozilla;
 
 nsSystemInfo::nsSystemInfo()
 {
 }
--- a/xpcom/ds/nsAtomTable.cpp
+++ b/xpcom/ds/nsAtomTable.cpp
@@ -31,16 +31,18 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "mozilla/Assertions.h"
+
 #include "nsAtomTable.h"
 #include "nsStaticAtom.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsUTF8Utils.h"
 #include "nsCRT.h"
 #include "pldhash.h"
 #include "prenv.h"
@@ -401,26 +403,27 @@ GetAtomHashEntry(const PRUnichar* aStrin
   AtomTableKey key(aString, aLength);
   return static_cast<AtomTableEntry*>
                     (PL_DHashTableOperate(&gAtomTable, &key, PL_DHASH_ADD));
 }
 
 class CheckStaticAtomSizes
 {
   CheckStaticAtomSizes() {
-    PR_STATIC_ASSERT((sizeof(nsFakeStringBuffer<1>().mRefCnt) ==
-                      sizeof(nsStringBuffer().mRefCount)) &&
-                     (sizeof(nsFakeStringBuffer<1>().mSize) ==
-                      sizeof(nsStringBuffer().mStorageSize)) &&
-                     (offsetof(nsFakeStringBuffer<1>, mRefCnt) ==
-                      offsetof(nsStringBuffer, mRefCount)) &&
-                     (offsetof(nsFakeStringBuffer<1>, mSize) ==
-                      offsetof(nsStringBuffer, mStorageSize)) &&
-                     (offsetof(nsFakeStringBuffer<1>, mStringData) ==
-                      sizeof(nsStringBuffer)));
+    MOZ_STATIC_ASSERT((sizeof(nsFakeStringBuffer<1>().mRefCnt) ==
+                       sizeof(nsStringBuffer().mRefCount)) &&
+                      (sizeof(nsFakeStringBuffer<1>().mSize) ==
+                       sizeof(nsStringBuffer().mStorageSize)) &&
+                      (offsetof(nsFakeStringBuffer<1>, mRefCnt) ==
+                       offsetof(nsStringBuffer, mRefCount)) &&
+                      (offsetof(nsFakeStringBuffer<1>, mSize) ==
+                       offsetof(nsStringBuffer, mStorageSize)) &&
+                      (offsetof(nsFakeStringBuffer<1>, mStringData) ==
+                       sizeof(nsStringBuffer)),
+                      "mocked-up strings' representations should be compatible");
   }
 };
 
 nsresult
 NS_RegisterStaticAtoms(const nsStaticAtom* aAtoms, PRUint32 aAtomCount)
 {
   // this does three things:
   // 1) wraps each static atom in a wrapper, if necessary
--- a/xpcom/glue/DeadlockDetector.h
+++ b/xpcom/glue/DeadlockDetector.h
@@ -34,16 +34,18 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef mozilla_DeadlockDetector_h
 #define mozilla_DeadlockDetector_h
 
+#include "mozilla/Attributes.h"
+
 #include <stdlib.h>
 
 #include "plhash.h"
 #include "prlock.h"
 
 #include "nsTArray.h"
 
 #ifdef NS_TRACE_MALLOC
@@ -561,18 +563,19 @@ public:
 
     /**
      * Protects contentious methods.
      * Nb: can't use mozilla::Mutex since we are used as its deadlock
      * detector.
      */
     PRLock* mLock;
 
-    DeadlockDetector(const DeadlockDetector& aDD);
-    DeadlockDetector& operator=(const DeadlockDetector& aDD);
+private:
+    DeadlockDetector(const DeadlockDetector& aDD) MOZ_DELETE;
+    DeadlockDetector& operator=(const DeadlockDetector& aDD) MOZ_DELETE;
 };
 
 
 template<typename T>
 const PLHashAllocOps DeadlockDetector<T>::kAllocOps = {
     DeadlockDetector<T>::TableAlloc, DeadlockDetector<T>::TableFree,
     DeadlockDetector<T>::EntryAlloc, DeadlockDetector<T>::EntryFree
 };
--- a/xpcom/glue/nsCOMArray.h
+++ b/xpcom/glue/nsCOMArray.h
@@ -34,16 +34,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsCOMArray_h__
 #define nsCOMArray_h__
 
+#include "mozilla/Attributes.h"
+
 #include "nsVoidArray.h"
 #include "nsISupports.h"
 
 // See below for the definition of nsCOMArray<T>
 
 // a class that's nsISupports-specific, so that we can contain the
 // work of this class in the XPCOM dll
 class NS_COM_GLUE nsCOMArray_base
@@ -120,17 +122,17 @@ public:
     }
 
 private:
     
     // the actual storage
     nsVoidArray mArray;
 
     // don't implement these, defaults will muck with refcounts!
-    nsCOMArray_base& operator=(const nsCOMArray_base& other);
+    nsCOMArray_base& operator=(const nsCOMArray_base& other) MOZ_DELETE;
 };
 
 // a non-XPCOM, refcounting array of XPCOM objects
 // used as a member variable or stack variable - this object is NOT
 // refcounted, but the objects that it holds are
 //
 // most of the read-only accessors like ObjectAt()/etc do NOT refcount
 // on the way out. This means that you can do one of two things:
@@ -272,13 +274,13 @@ class nsCOMArray : public nsCOMArray_bas
     // as necessary
     bool RemoveObjectsAt(PRInt32 aIndex, PRInt32 aCount) {
         return nsCOMArray_base::RemoveObjectsAt(aIndex, aCount);
     }
 
 private:
 
     // don't implement these!
-    nsCOMArray<T>& operator=(const nsCOMArray<T>& other);
+    nsCOMArray<T>& operator=(const nsCOMArray<T>& other) MOZ_DELETE;
 };
 
 
 #endif
--- a/xpcom/glue/nsStringAPI.h
+++ b/xpcom/glue/nsStringAPI.h
@@ -45,16 +45,18 @@
 
 #ifdef MOZILLA_INTERNAL_API
 #error nsStringAPI.h is only usable from non-MOZILLA_INTERNAL_API code!
 #endif
 
 #ifndef nsStringAPI_h__
 #define nsStringAPI_h__
 
+#include "mozilla/Attributes.h"
+
 #include "nsXPCOMStrings.h"
 #include "nsISupportsImpl.h"
 #include "prlog.h"
 #include "nsTArray.h"
 
 /**
  * Comparison function for use with nsACString::Equals
  */
@@ -936,17 +938,17 @@ public:
   void Rebind(const char_type* aData, size_type aLength = PR_UINT32_MAX)
   {
     NS_StringContainerFinish(*this);
     NS_StringContainerInit2(*this, aData, aLength,
                             NS_STRING_CONTAINER_INIT_DEPEND);
   }
   
 private:
-  self_type& operator=(const self_type& aString); // NOT IMPLEMENTED
+  self_type& operator=(const self_type& aString) MOZ_DELETE;
 };
 
 class nsDependentCString : public nsCString
 {
 public:
   typedef nsDependentCString        self_type;
 
   nsDependentCString() {}
@@ -959,17 +961,17 @@ public:
   void Rebind(const char_type* aData, size_type aLength = PR_UINT32_MAX)
   {
     NS_CStringContainerFinish(*this);
     NS_CStringContainerInit2(*this, aData, aLength,
                              NS_CSTRING_CONTAINER_INIT_DEPEND);
   }
   
 private:
-  self_type& operator=(const self_type& aString); // NOT IMPLEMENTED
+  self_type& operator=(const self_type& aString) MOZ_DELETE;
 };
 
 
 /**
  * conversion classes
  */
 
 inline void
@@ -1013,17 +1015,17 @@ public:
   explicit
   NS_ConvertASCIItoUTF16(const char* aData, PRUint32 aLength = PR_UINT32_MAX)
   {
     NS_CStringToUTF16(nsDependentCString(aData, aLength),
                       NS_CSTRING_ENCODING_ASCII, *this);
   }
 
 private:
-  self_type& operator=(const self_type& aString); // NOT IMPLEMENTED
+  self_type& operator=(const self_type& aString) MOZ_DELETE;
 };
 
 class NS_ConvertUTF8toUTF16 : public nsString
 {
 public:
   typedef NS_ConvertUTF8toUTF16    self_type;
 
   explicit
@@ -1035,17 +1037,17 @@ public:
   explicit
   NS_ConvertUTF8toUTF16(const char* aData, PRUint32 aLength = PR_UINT32_MAX)
   {
     NS_CStringToUTF16(nsDependentCString(aData, aLength),
                       NS_CSTRING_ENCODING_UTF8, *this);
   }
 
 private:
-  self_type& operator=(const self_type& aString); // NOT IMPLEMENTED
+  self_type& operator=(const self_type& aString) MOZ_DELETE;
 };
 
 class NS_ConvertUTF16toUTF8 : public nsCString
 {
 public:
   typedef NS_ConvertUTF16toUTF8    self_type;
 
   explicit
@@ -1057,17 +1059,17 @@ public:
   explicit
   NS_ConvertUTF16toUTF8(const PRUnichar* aData, PRUint32 aLength = PR_UINT32_MAX)
   {
     NS_UTF16ToCString(nsDependentString(aData, aLength),
                       NS_CSTRING_ENCODING_UTF8, *this);
   }
 
 private:
-  self_type& operator=(const self_type& aString); // NOT IMPLEMENTED
+  self_type& operator=(const self_type& aString) MOZ_DELETE;
 };
 
 class NS_LossyConvertUTF16toASCII : public nsCString
 {
 public:
   typedef NS_LossyConvertUTF16toASCII    self_type;
 
   explicit
@@ -1079,17 +1081,17 @@ public:
   explicit
   NS_LossyConvertUTF16toASCII(const PRUnichar* aData, PRUint32 aLength = PR_UINT32_MAX)
   {
     NS_UTF16ToCString(nsDependentString(aData, aLength),
                       NS_CSTRING_ENCODING_ASCII, *this);
   }
 
 private:
-  self_type& operator=(const self_type& aString); // NOT IMPLEMENTED
+  self_type& operator=(const self_type& aString) MOZ_DELETE;
 };
 
 
 /**
  * literal strings
  *
  * NOTE: HAVE_CPP_2BYTE_WCHAR_T may be automatically defined for some platforms
  * in nscore.h.  On other platforms, it may be defined in xpcom-config.h.
@@ -1251,17 +1253,17 @@ public:
   {
     NS_StringContainerFinish(*this);
     NS_StringContainerInit2(*this, aStart, aLength,
                             NS_STRING_CONTAINER_INIT_DEPEND |
                             NS_STRING_CONTAINER_INIT_SUBSTRING);
   }
 
 private:
-  self_type& operator=(const self_type& aString); // NOT IMPLEMENTED
+  self_type& operator=(const self_type& aString) MOZ_DELETE;
 };
 
 class NS_COM_GLUE nsDependentCSubstring : public nsCStringContainer
 {
 public:
   typedef nsDependentCSubstring self_type;
   typedef nsACString            abstract_string_type;
 
@@ -1291,17 +1293,17 @@ public:
   {
     NS_CStringContainerFinish(*this);
     NS_CStringContainerInit2(*this, aStart, aLength,
                              NS_CSTRING_CONTAINER_INIT_DEPEND |
                              NS_CSTRING_CONTAINER_INIT_SUBSTRING);
   }
 
 private:
-  self_type& operator=(const self_type& aString); // NOT IMPLEMENTED
+  self_type& operator=(const self_type& aString) MOZ_DELETE;
 };
 
 
 /**
  * Various nsDependentC?Substring constructor functions
  */
 
 // PRUnichar
--- a/xpcom/glue/nsTArray-inl.h
+++ b/xpcom/glue/nsTArray-inl.h
@@ -59,22 +59,22 @@ const nsTArrayHeader* nsTArray_base<Allo
   // Assuming |this| points to an nsAutoArray, we want to get a pointer to
   // mAutoBuf.  So just cast |this| to nsAutoArray* and read &mAutoBuf!
 
   const void* autoBuf = &reinterpret_cast<const nsAutoArrayBase<nsTArray<PRUint32>, 1>*>(this)->mAutoBuf;
 
   // If we're on a 32-bit system and elemAlign is 8, we need to adjust our
   // pointer to take into account the extra alignment in the auto array.
 
-  // Check that the auto array is padded as we expect.
-  PR_STATIC_ASSERT(sizeof(void*) != 4 ||
-                   (MOZ_ALIGNOF(mozilla::AlignedElem<8>) == 8 &&
-                    sizeof(nsAutoTArray<mozilla::AlignedElem<8>, 1>) ==
-                      sizeof(void*) + sizeof(nsTArrayHeader) +
-                      4 + sizeof(mozilla::AlignedElem<8>)));
+  MOZ_STATIC_ASSERT(sizeof(void*) != 4 ||
+                    (MOZ_ALIGNOF(mozilla::AlignedElem<8>) == 8 &&
+                     sizeof(nsAutoTArray<mozilla::AlignedElem<8>, 1>) ==
+                       sizeof(void*) + sizeof(nsTArrayHeader) +
+                       4 + sizeof(mozilla::AlignedElem<8>)),
+                    "auto array padding wasn't what we expected");
 
   // We don't support alignments greater than 8 bytes.
   NS_ABORT_IF_FALSE(elemAlign <= 4 || elemAlign == 8, "unsupported alignment.");
   if (sizeof(void*) == 4 && elemAlign == 8) {
     autoBuf = reinterpret_cast<const char*>(autoBuf) + 4;
   }
 
   return reinterpret_cast<const Header*>(autoBuf);
@@ -110,17 +110,18 @@ bool nsTArray_base<Alloc>::UsesAutoArray
   // GetAutoArrayBuffer(8) will always point inside the auto array object,
   // even if it doesn't point at the beginning of the header.
   //
   // Note that this means that we can't store elements with alignment 16 in an
   // nsTArray, because GetAutoArrayBuffer(16) could lie outside the memory
   // owned by this nsAutoTArray.  We statically assert that elem_type's
   // alignment is 8 bytes or less in nsAutoArrayBase.
 
-  PR_STATIC_ASSERT(sizeof(nsTArrayHeader) > 4);
+  MOZ_STATIC_ASSERT(sizeof(nsTArrayHeader) > 4,
+                    "see comment above");
 
 #ifdef DEBUG
   PRPtrdiff diff = reinterpret_cast<const char*>(GetAutoArrayBuffer(8)) -
                    reinterpret_cast<const char*>(GetAutoArrayBuffer(4));
   NS_ABORT_IF_FALSE(diff >= 0 && diff <= 4, "GetAutoArrayBuffer doesn't do what we expect.");
 #endif
 
   return mHdr == GetAutoArrayBuffer(4) || mHdr == GetAutoArrayBuffer(8);
--- a/xpcom/glue/nsTArray.h
+++ b/xpcom/glue/nsTArray.h
@@ -34,25 +34,27 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsTArray_h__
 #define nsTArray_h__
 
+#include "mozilla/Assertions.h"
+#include "mozilla/Util.h"
+
 #include <string.h>
 
 #include "prtypes.h"
 #include "nsAlgorithm.h"
 #include "nscore.h"
 #include "nsQuickSort.h"
 #include "nsDebug.h"
 #include "nsTraceRefcnt.h"
-#include "mozilla/Util.h"
 #include NEW_H
 
 //
 // NB: nsTArray assumes that your "T" can be memmove()d.  This is in
 // contrast to STL containers, which follow C++
 // construction/destruction rules.
 //
 // Don't use nsTArray if your "T" can't be memmove()d correctly.
@@ -1311,19 +1313,19 @@ protected:
 
 private:
   // nsTArray_base casts itself as an nsAutoArrayBase in order to get a pointer
   // to mAutoBuf.
   template<class Allocator>
   friend class nsTArray_base;
 
   void Init() {
-    // We can't handle alignments greater than 8; see
-    // nsTArray_base::UsesAutoArrayBuffer().
-    PR_STATIC_ASSERT(MOZ_ALIGNOF(elem_type) <= 8);
+    MOZ_STATIC_ASSERT(MOZ_ALIGNOF(elem_type) <= 8,
+                      "can't handle alignments greater than 8, "
+                      "see nsTArray_base::UsesAutoArrayBuffer()");
 
     *base_type::PtrToHdr() = reinterpret_cast<Header*>(&mAutoBuf);
     base_type::Hdr()->mLength = 0;
     base_type::Hdr()->mCapacity = N;
     base_type::Hdr()->mIsAutoArray = 1;
 
     NS_ASSERTION(base_type::GetAutoArrayBuffer(MOZ_ALIGNOF(elem_type)) ==
                  reinterpret_cast<Header*>(&mAutoBuf),
@@ -1362,18 +1364,20 @@ public:
 // because any type may be placed into an array, and there's no padding between
 // elements of an array.)  The compiler pads the end of the structure to
 // enforce this rule.
 //
 // If we used nsAutoTArray<PRUint32, 1> below, this assertion would fail on a
 // 64-bit system, where the compiler inserts 4 bytes of padding at the end of
 // the auto array to make its size a multiple of alignof(void*) == 8 bytes.
 
-PR_STATIC_ASSERT(sizeof(nsAutoTArray<PRUint32, 2>) ==
-                 sizeof(void*) + sizeof(nsTArrayHeader) + sizeof(PRUint32) * 2);
+MOZ_STATIC_ASSERT(sizeof(nsAutoTArray<PRUint32, 2>) ==
+                  sizeof(void*) + sizeof(nsTArrayHeader) + sizeof(PRUint32) * 2,
+                  "nsAutoTArray shouldn't contain any extra padding, "
+                  "see the comment");
 
 template<class E, PRUint32 N>
 class AutoFallibleTArray : public nsAutoArrayBase<FallibleTArray<E>, N>
 {
   typedef nsAutoArrayBase<FallibleTArray<E>, N> Base;
 
 public:
   AutoFallibleTArray() {}
--- a/xpcom/string/public/nsString.h
+++ b/xpcom/string/public/nsString.h
@@ -34,16 +34,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsString_h___
 #define nsString_h___
 
+#include "mozilla/Attributes.h"
 
 #ifndef nsSubstring_h___
 #include "nsSubstring.h"
 #endif
 
 #ifndef nsDependentSubstring_h___
 #include "nsDependentSubstring.h"
 #endif
--- a/xpcom/string/public/nsTString.h
+++ b/xpcom/string/public/nsTString.h
@@ -692,13 +692,12 @@ class nsTAdoptingString_CharT : public n
       self_type& operator=( const substring_tuple_type& tuple )                                 { Assign(tuple);    return *this; }
 
         // Adopt(), if possible, when assigning to a self_type&. Note
         // that this violates the constness of str, str is always
         // truncated when this operator is called.
       self_type& operator=( const self_type& str );
 
     private:
-        // NOT TO BE IMPLEMENTED.
-      self_type& operator=( const char_type* data );
-      self_type& operator=( char_type* data );
+      self_type& operator=( const char_type* data ) MOZ_DELETE;
+      self_type& operator=( char_type* data ) MOZ_DELETE;
   };